Skip to content

Data binding

Oyvind Ohra edited this page Jan 16, 2022 · 2 revisions

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.

Data binding concepts

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.

Binding context

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.

Direction of the data flow

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.

Updating the UI

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.

Command binding

{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.

Data templating

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.