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 aGrid
using a comma-separated syntax, for example:"Auto,10,*"
GridLayout.Rows
— makes it possible to specify the rows of aGrid
using a comma-separated syntaxGridLayout.ColumnCount
— makes it possible to specify the number of auto-sized columns of aGrid
GridLayout.RowCount
— makes it possible to specify the number of auto-sized rows of aGrid
<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>