Go to content

Bulletcode.NET

Controls

The Bulletcode.Desktop.Controls namespace contains UI elements, converters, attached properties, behaviors and markup extensions for desktop applications using WPF. This namespace can be imported into a XAML file:

<UserControl
    x:Class="App.Views.ExampleControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ctrl="clr-namespace:Bulletcode.Desktop.Controls;assembly=Bulletcode.Desktop.Wpf"
    >
    <!-- TODO -->
</UserControl>

UI Elements

The DateTextBox control is similar to the built-in DatePicker control, but it inherits TextBox and has a more modern look. The date can be typed manually or selected using a drop-down Calendar control. The SelectedDate property contains the current date. This control also supports the read-only mode, where the calendar button is hidden.

<ctrl:DateTextBox SelectedDate="{Binding BirthDate}"/>

The DecimalTextBox control inherits TextBox and makes handling decimal values easier. It has a Value property which can be bound directly to a decimal property in the view model. The StringFormat property defines the format which is used to convert decimal values to text; the default value is "N2". The text is automatically reformatted when the control loses focus. This control also supports the read-only mode.

<ctrl:DecimalTextBox Value="{Binding Amount}"/>

The PrefixTextBox control combines a TextBox with a drop-down list for selecting the prefix. It can be used, for example, to enter a phone number with the country prefix. This control inherits TextBox, and contains properties controlling the drop-down list: ItemsSource, SelectedItem, DisplayMemberPath and MaxDropDownHeight.

The optional ItemTemplate is used to present the items in the drop-down list, and the optional PrefixTemplate and PrefixTemplateSelector are used to present the selected item in the drop-down button within the control.

The Prefix property contains the text of the selected item. It is retrieving using either the TextSearch.TextPath attached property, which can be set for this control, the DisplayMemberPath, or the ToString() method.

The FullText property contains the text of the selected item combined with the text entered into the text box.

<ctrl:PrefixTextBox
    FullText="{Binding PhoneNumber}"
    Prefix="{Binding PhonePrefix}"
    ItemsSource="{Binding PhonePrefixes}"
    PrefixTemplate="{StaticResource PhonePrefixTemplate}"
    ItemTemplate="{StaticResource PhonePrefixItemTemplate}"
    TextSearch.TextPath="Prefix"
    />

The RoundedButton control is a subclass of the Button control with an additional CornerRadius property.

<ctrl:RoundedButton CornerRadius="5">OK</ctrl:RoundedButton>

The SymbolIcon is a simple static UI element which displays an icon using the Segoe MDL2 Assets font, which is available in Windows 10 and newer. The Symbol property selects the displayed icon.

<ctrl:SymbolIcon Symbol="Refresh"/>

The SymbolButton and SymbolToggleButton controls are subclasses of Button and ToggleButton, respectively, which display the selected Symbol next to their content. The optional SymbolColor property defines the color of the icon.

<ctrl:SymbolButton Symbol="Refresh">Refresh</ctrl:SymbolButton>

Attached Properties

The following attached properties are available for the Grid control:

  • GridLayout.Columns — makes it possible to specify the columns of a Grid using a comma-separated syntax, for example: "Auto,10,*"
  • GridLayout.Rows — makes it possible to specify the rows of a Grid using a comma-separated syntax
  • GridLayout.ColumnCount — makes it possible to specify the number of auto-sized columns of a Grid
  • GridLayout.RowCount — makes it possible to specify the number of auto-sized rows of a Grid
<Grid ctrl:GridLayout.Columns="Auto,10,*" ctrl:GridLayout.RowCount="5">
    <!-- TODO -->
</Grid>

Behaviors

Bulletcode.NET uses the XAML Behaviors library to modify the behavior of built-in controls without the need to subclass them.

The AutocompleteBehavior makes it possible to add autocompletion to a TextBox or any control which inherits it. The AutocompleteSource property specifies the object which provides a list items based on the entered prefix. This object must implement the IAutocompleteSource interface, which has a GetItemsAsync() method. The SelectedValue, SelectedValuePath, DisplayMemberPath and ItemTemplate properties control the drop-down list used to display the autocompletion items.

<TextBox Text="{Binding City}" TextSearch.TextPath="Name">
    <b:Interaction.Behaviors>
        <ctrl:AutocompleteBehavior
            AutocompleteSource="{Binding CitySource}"
            SelectedValue="{Binding CityId}"
            SelectedValuePath="Id"
            ItemTemplate="{StaticResource CityItemTemplate}"
            />
    </b:Interaction.Behaviors>
</TextBox>

The ConversionErrorsBehavior makes it possible for the view model to detect conversion errors which occur in control bindings. See Validation for more information.

The DataGridSortBindingBehavior makes it possible to bind the sort order of columns in the DataGrid control to the view model, which is useful when the grid is populated from an API.

<DataGrid ItemsSource="{Binding Items}">
    <b:Interaction.Behaviors>
        <ctrl:DataGridSortBindingBehavior SortDescription="{Binding SortDescription}"/>
    </b:Interaction.Behaviors>
    <DataGrid.Columns>
        <!-- TODO -->
    </DataGrid.Columns>
</DataGrid>

The GridItemsControlBehavior makes it possible to use a Grid layout as the items panel in an ItemsControl. It passes the Grid.Row and Grid.Column attached properties from the item template to the content presenter element which contains it.

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid
                ctrl:GridLayout.RowCount="{Binding RowCount}"
                ctrl:GridLayout.ColumnCount="{Binding ColumnCount}"
                >
                <b:Interaction.Behaviors>
                    <ctrl:GridItemsControlBehavior/>
                </b:Interaction.Behaviors>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button
                Grid.Row="{Binding Row}"
                Grid.Column="{Binding Column}"
                Content="{Binding Content}"
                />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

The ItemsControlScrollBehavior makes it possible to control the number of items scrolled in a single step using the mouse wheel in an ItemsControl. The ScrollViewerScrollBehavior makes it possible to control the number of pixels scrolled in a single step using the mouse wheel in a ScrollViewer container.

<DataGrid ItemsSource="{Binding Items}">
    <b:Interaction.Behaviors>
        <ctrl:ItemsControlScrollBehavior MouseWheelStep="5"/>
    </b:Interaction.Behaviors>
    <DataGrid.Columns>
        <!-- TODO -->
    </DataGrid.Columns>
</DataGrid>

The PasswordBindingBehavior makes it possible to bind the value of the PasswordBox control to the view model.

<PasswordBox>
    <b:Interaction.Behaviors>
        <ctrl:PasswordBindingBehavior Password="{Binding Password}"/>
    </b:Interaction.Behaviors>
</PasswordBox>

The TabControlAutosizeBehavior adjusts the size of a TabControl to the width of the widest tab (when Width is set to true) and/or the height of the highest tab (when Height is set to true).

<TabControl>
    <b:Interaction.Behaviors>
        <ctrl:TabControlAutosizeBehavior Height="True"/>
    </b:Interaction.Behaviors>
    <!-- TODO -->
</TabControl>

Markup extensions

The Instance markup extension creates an object of the specified type. This is useful for specifying binding converters without having to add them to the static resource dictionary. For example:

<Button Visibility="{Binding CanDownload, Converter={ctrl:Instance BooleanToVisibilityConverter}}">
    Download
</Button>

The RootObject markup extension returns the root object of the XAML file. This is useful for specifying the binding source without having to use an explicit name.

<UserControl>
    <Button "Content={Binding Content, Source={ctrl:RootObject}}"/>
</UserControl>

The i18n:Translate, i18n:Format and i18n:MultiFormat markup extensions are used to provide translations in XAML files. See Internationalization for more information.

Converters

The CollapsedWhenNullConverter converts a non-null value to Visible and a null value to Collapsed.

<Border Visibility="{Binding Message, Converter={ctrl:Instance ctrl:CollapsedWhenNullConverter}}">
    <Label Margin="10">
        <TextBlock Text="{Binding Message}"/>
    </Label>
</Border>

The DarkenColorConverter converts a SolidColorBrush to another SolidColorBrush by darkening the color by the amount specified by the converter parameter. For example, it can be used to darken the background of an element when the mouse hovers over it:

<Trigger Property="IsMouseOver" Value="True">
    <Setter
        Property="Background"
        Value="{Binding Background,
            RelativeSource={RelativeSource TemplatedParent},
            Converter={ctrl:Instance ctrl:DarkenColorConverter},
            ConverterParameter=0.1}"
        />
</Trigger>

The RadioConverter converts the value to a string and compares it to the converter parameters; it returns true if the strings are equal and false otherwise. It can be used to bind radio buttons to a view model, for example:

<RadioButton IsChecked="{Binding Value,
    Converter={ctrl:Instance ctrl:RadioConverter},
    ConverterParameter=True}">Yes</RadioButton>
<RadioButton
    IsChecked="{Binding Value,
    Converter={ctrl:Instance ctrl:RadioConverter},
    ConverterParameter=False}">No</RadioButton>

The StringFormatConverter formats a value using the format passed as the converter parameter. It can be used when the target of the binding is not a string, and StringFormat is not applied to the binding, for example when specifying an image source using a path:

<Image Source="{Binding CountryCode,
    Converter={ctrl:Instance ctrl:StringFormatConverter},
    ConverterParameter='/Resources/Flags/{0}.png'}"/>

The TimeConverter converts a TimeSpan value to a string, using the "hh:mm" format. It can be used to create a text box for entering time values, for example:

<TextBox Text="{Binding Time,
    UpdateSourceTrigger=PropertyChanged,
    Converter={ctrl:Instance ctrl:TimeConverter}}"/>

The ToUpperConverter converts a string to an uppercase string by calling the ToUpper() method, for example:

<DataGridTextColumn
    Header="Name"
    Binding="{Binding Name, Converter={ctrl:Instance ctrl:ToUpperConverter}}"
    />

The TrimmedTextBlockConverter can be used to conditionally display a tooltip when the text inside a TextBlock is trimmed, for example:

<Setter Property="ToolTip">
    <Setter.Value>
        <ToolTip
            Content="{Binding PlacementTarget.Text,
                RelativeSource={RelativeSource Self}}"
            Visibility="{Binding PlacementTarget,
                RelativeSource={RelativeSource Self},
                Converter={ctrl:Instance ctrl:TrimmedTextBlockConverter}}"
            />
    </Setter.Value>
</Setter>