-
Notifications
You must be signed in to change notification settings - Fork 0
Data binding
Data binding is the process that establishes a connection between the app UI and the data it displays.
There are two kinds of binding, and they're both typically declared in UI markup (XAML). You can choose to use either the {x:Bind}
markup extension or the {Binding}
markup extension. And you can even use a mixture of the two in the same app—even on the same UI element. {x:Bind} is new for Windows 10 and it has better performance.
See this section for a feature comparison of {x:bind}
and {Binding}
.
See these articles on Data binding in depth and Data binding overview for more information. (Do note that even though articles referred to in this section typically refer to WPF or UWP, the concepts discussed are still just as relevant for WinUI.)
In the following we'll refer to the WinUI app created in the Windows Template Studio Win UI sample.
Regardless of what element you're binding and the nature of your data source, each binding always follows the model illustrated by the following figure.
As the figure shows, data binding is essentially the bridge between your binding target and your binding source. The figure demonstrates the following fundamental data binding concepts:
Typically, each binding has four components:
- A binding target object, e.g., a
TextBox
. - A target property, e.g., the
Text
property. - A binding source, e.g., an
Employee
. - A path to the value in the binding source to use, e.g., a
Name
property.
The target property must be a dependency property. Most UIElement properties are dependency properties, and most dependency properties, except read-only ones, support data binding by default. Only types derived from DependencyObject
can define dependency properties. All UIElement types derive from DependencyObject
.
TextBox
is a sample of a control that inherits from UIElement, so the Text
property of the TextBox
is a dependency property, and can be used in a data binding.
When data binding is declared on XAML elements, with the {Binding}
markup extension, they resolve data binding by looking at their immediate DataContext
property. The data context is typically the binding source object for the binding source value path evaluation. You can override this behaviour in the binding and set a specific binding source object value. If the DataContext
property for the object hosting the binding isn't set, the parent element's DataContext
property is checked, and so on, up until the root of the XAML object tree. In short, the data context used to resolve binding is inherited from the parent unless explicitly set on the object. When the DataContext
property changes, all bindings that could be affected by the data context are re-evaluated.
When the x:Bind
XAML extension is used, the binding context will default to the class itself. Examine the ListDetailsPage
page from the tutorial (given in the start of this article), the ListDetailsView
control is the target object and the control's ItemsSource
property is the target property.
ItemsSource="{x:Bind ViewModel.SampleItems}"
The binding source is resolved by examining the ListDetailsPage
class for a ViewModel
property (defined in the class' code behind file), further this view model (ListDetailsViewModel
) exposes a SampleItems
property, which becomes the source of the binding.
The direction of the data flow (from source to target and vice versa) is controlled by the Mode
of the binding, e.g. examine the ListDetailsView
control's SelectedItem
property:
SelectedItem="{x:Bind ViewModel.Selected, Mode=TwoWay}"
The different types of binding mode are:
- OneWay: Updates the binding target (target) property when the binding source (source) changes.
- TwoWay: Causes changes to either the source property or the target property to automatically update the other.
- OneWayToSource: Updates the source property when the target property changes.
- OneTime: Updates the binding target when the application starts or when the data context changes.
The default binding mode, when {Binding}
is used, is Default
, which returns the default binding mode value of the target dependency property. However, the default value varies for each dependency property. In general, user-editable control properties, such as those of text boxes and check boxes, default to two-way bindings, whereas most other properties default to one-way bindings.
The default binding mode, when {x:Bind}
is used, is one-time.
To detect source changes, the source must implement a suitable property change notification mechanism such as INotifyPropertyChanged
. See How to: Implement property change notification (.NET Framework)
for an example of an INotifyPropertyChanged
implementation.
In the sample above the ItemsSource
is bound to the SampleItems
property which is of type ObservableCollection
, a built-in implementation of a data collection that implements the INotifyCollectionChanged
interface, this interface will signal the target object of any changes to the collection, allowing the UI to automatically update.
{x:Bind}
supports a feature called event binding. With this feature, you can specify the handler for an event using a binding, e.g., a Click event. Most controls that executes a command, e.g. a Button
support the Command
property, e.g., examine the SettingsPage
page's RadioButton
control's Command
property (line 24):
Command="{x:Bind ViewModel.SwitchThemeCommand}"
Commands are an implementation of the ICommand
interface:
- The method Execute(object) is called when the command is actuated. It has one parameter, which can be used to pass additional information from the caller to the command.
- The method CanExecute(object) returns a Boolean. If the return value is true, it means that the command can be executed. The parameter is the same one as for the Execute method. When used in XAML controls that support the Command property, the control will be automatically disabled if CanExecute returns false.
- The CanExecuteChanged event handler must be raised by the command implementation when the CanExecute method needs to be re-evaluated.
You easily create commands by using the RelayCommand
class, e.g., see the SettingsViewModel
's SwitchThemeCommand
property.
The DataTemplate
controls the presentation of data, templates are typically applied to any elements that should be styled before they are presented in the UI. Examine the ListDetailsPage
page's ListDetailsView
control's ItemTemplate
property (line 94):
ItemTemplate="{StaticResource ItemTemplate}"
The ItemTemplate
is a DataTemplate
that controls each and every element displayed in the list. The ItemTemplate
is defined as a resource for the page, see line 15:
<DataTemplate x:Key="ItemTemplate" x:DataType="models:SampleOrder">
<Grid Height="60">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<FontIcon
Grid.Column="0"
VerticalAlignment="Center"
FontSize="32"
Glyph="{x:Bind Symbol}"
AutomationProperties.Name="{x:Bind SymbolName}" />
<StackPanel
Grid.Column="1"
Margin="{StaticResource SmallLeftMargin}"
VerticalAlignment="Center">
<TextBlock Text="{x:Bind Company}" Style="{StaticResource ListTitleStyle}" />
<TextBlock Text="{x:Bind Status}" Style="{StaticResource ListSubTitleStyle}" />
</StackPanel>
</Grid>
</DataTemplate>
More information on data templating can be found in the Data Templating Overview.