You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: hub/apps/develop/data-binding/data-binding-overview.md
+27-22Lines changed: 27 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,13 +1,14 @@
1
1
---
2
2
ms.assetid: 02a08657-285d-4804-a006-168c22aa4904
3
-
title: Windows data binding overview
4
-
description: This topic shows you how to bind a control (or other UI element) to a single item or bind an item's control to a collection of items in a Windows App SDK app.
5
-
ms.date: 12/12/2022
6
-
ms.topic: article
3
+
title: Windows data binding overview for developers
4
+
description: This topic shows you how to bind a control (or other UI element) to a single item or bind an item's control to a collection of items in a WinUI app with Windows App SDK.
5
+
ms.date: 01/10/2025
6
+
ms.topic: concept-article
7
7
keywords: windows 10, windows 11, windows app sdk, winui, windows ui
8
8
ms.localizationpriority: medium
9
9
dev_langs:
10
10
- csharp
11
+
# Customer intent: As a Windows developer, I want to learn how to bind a control to a single item or bind an item's control to a collection of items in a WinUI app.
11
12
---
12
13
13
14
# Windows data binding overview
@@ -94,9 +95,9 @@ Here's the result.
94
95
95
96
## Binding to a collection of items
96
97
97
-
A common scenario is to bind to a collection of business objects. In C#, the generic [**ObservableCollection<T>**](/dotnet/api/system.collections.objectmodel.observablecollection-1) class is a good collection choice for data binding, because it implements the [**INotifyPropertyChanged**](/dotnet/api/system.componentmodel.inotifypropertychanged) and [**INotifyCollectionChanged**](/dotnet/api/system.collections.specialized.inotifycollectionchanged) interfaces. These interfaces provide change notification to bindings when items are added or removed or a property of the list itself changes. If you want your bound controls to update with changes to properties of objects in the collection, the business object should also implement `INotifyPropertyChanged`. For more info, see [Data binding in depth](data-binding-in-depth.md).
98
+
A common scenario is to bind to a collection of business objects. In C#, the generic [ObservableCollection<T>](/dotnet/api/system.collections.objectmodel.observablecollection-1) class is a good collection choice for data binding, because it implements the [INotifyPropertyChanged](/dotnet/api/system.componentmodel.inotifypropertychanged) and [INotifyCollectionChanged](/dotnet/api/system.collections.specialized.inotifycollectionchanged) interfaces. These interfaces provide change notification to bindings when items are added or removed or a property of the list itself changes. If you want your bound controls to update with changes to properties of objects in the collection, the business object should also implement `INotifyPropertyChanged`. For more info, see [Data binding in depth](data-binding-in-depth.md).
98
99
99
-
This next example binds a [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) to a collection of `Recording` objects. Let's start by adding the collection to our view model. Just add these new members to the `RecordingViewModel` class.
100
+
This next example binds a [ListView](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) to a collection of `Recording` objects. Let's start by adding the collection to our view model. Just add these new members to the `RecordingViewModel` class.
100
101
101
102
```csharp
102
103
publicclassRecordingViewModel
@@ -116,7 +117,7 @@ public class RecordingViewModel
116
117
}
117
118
```
118
119
119
-
And then bind a [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) to the `ViewModel.Recordings` property.
120
+
And then bind a [ListView](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) to the `ViewModel.Recordings` property.
120
121
121
122
```xaml
122
123
<Windowx:Class="Quickstart.MainWindow" ... >
@@ -127,11 +128,11 @@ And then bind a [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.x
127
128
</Window>
128
129
```
129
130
130
-
We haven't yet provided a data template for the `Recording` class, so the best the UI framework can do is to call [**ToString**](/dotnet/api/system.object.tostring#System_Object_ToString) for each item in the [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview). The default implementation of `ToString` is to return the type name.
131
+
We haven't yet provided a data template for the `Recording` class, so the best the UI framework can do is to call [ToString](/dotnet/api/system.object.tostring#System_Object_ToString) for each item in the [ListView](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview). The default implementation of `ToString` is to return the type name.
131
132
132
133

133
134
134
-
To remedy this, we can either override [**ToString**](/dotnet/api/system.object.tostring#System_Object_ToString) to return the value of `OneLineSummary`, or we can provide a data template. The data template option is a more usual solution, and a more flexible one. You specify a data template by using the [**ContentTemplate**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.contentcontrol.contenttemplate) property of a content control or the [**ItemTemplate**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.itemscontrol.itemtemplate) property of an items control. Here are two ways we could design a data template for `Recording` together with an illustration of the result.
135
+
To remedy this, we can either override [ToString](/dotnet/api/system.object.tostring#System_Object_ToString) to return the value of `OneLineSummary`, or we can provide a data template. The data template option is a more usual solution, and a more flexible one. You specify a data template by using the [ContentTemplate](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.contentcontrol.contenttemplate) property of a content control or the [ItemTemplate](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.itemscontrol.itemtemplate) property of an items control. Here are two ways we could design a data template for `Recording` together with an illustration of the result.
@@ -169,14 +170,14 @@ For more information about XAML syntax, see [Create a UI with XAML](/visualstudi
169
170
170
171
## Adding a details view
171
172
172
-
You can choose to display all the details of `Recording` objects in [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) items. But that takes up a lot of space. Instead, you can show just enough data in the item to identify it and then, when the user makes a selection, you can display all the details of the selected item in a separate piece of UI known as the details view. This arrangement is also known as a master/details view, or a list/details view.
173
+
You can choose to display all the details of `Recording` objects in [ListView](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) items. But that takes up a lot of space. Instead, you can show just enough data in the item to identify it and then, when the user makes a selection, you can display all the details of the selected item in a separate piece of UI known as the details view. This arrangement is also known as a master/details view, or a list/details view.
173
174
174
-
There are two ways to go about this. You can bind the details view to the [**SelectedItem**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.selector.selecteditem) property of the [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview). Or you can use a [**CollectionViewSource**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource), in which case you bind both the `ListView` and the details view to the `CollectionViewSource` (doing so takes care of the currently-selected item for you). Both techniques are shown below, and they both give the same results (shown in the illustration).
175
+
There are two ways to go about this. You can bind the details view to the [SelectedItem](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.selector.selecteditem) property of the [ListView](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview). Or you can use a [CollectionViewSource](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource), in which case you bind both the `ListView` and the details view to the `CollectionViewSource` (doing so takes care of the currently-selected item for you). Both techniques are shown below, and they both give the same results (shown in the illustration).
175
176
176
177
> [!NOTE]
177
178
> So far in this topic we've only used the [{x:Bind} markup extension](/windows/uwp/xaml-platform/x-bind-markup-extension), but both of the techniques we'll show below require the more flexible (but less performant) [{Binding} markup extension](/windows/uwp/xaml-platform/binding-markup-extension).
178
179
179
-
First, here's the [**SelectedItem**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.selector.selecteditem) technique. For a C# application, the only change necessary is to the markup.
180
+
First, here's the [SelectedItem](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.selector.selecteditem) technique. For a C# application, the only change necessary is to the markup.
180
181
181
182
```xaml
182
183
<Windowx:Class="Quickstart.MainWindow" ... >
@@ -205,15 +206,18 @@ First, here's the [**SelectedItem**](/windows/windows-app-sdk/api/winrt/microsof
205
206
</Window>
206
207
```
207
208
208
-
For the [**CollectionViewSource**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource) technique, first add a `CollectionViewSource` as a window resource.
209
+
For the [CollectionViewSource](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource) technique, first add a `CollectionViewSource` as a resource of the top-level `Grid`.
And then adjust the bindings on the [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) (which no longer needs to be named) and on the details view to use the [**CollectionViewSource**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource). Note that by binding the details view directly to the `CollectionViewSource`, you're implying that you want to bind to the current item in bindings where the path cannot be found on the collection itself. There's no need to specify the `CurrentItem` property as the path for the binding, although you can do that if there's any ambiguity).
217
+
> [!NOTE]
218
+
> The Window class in WinUI doesn't have a `Resources` property. You can add the `CollectionViewSource` to the top-level `Grid` (or other parent UI element like `StackPanel`) element instead. If you're working within a `Page`, you can add the `CollectionViewSource` to the `Page.Resources`.
219
+
220
+
And then adjust the bindings on the [ListView](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) (which no longer needs to be named) and on the details view to use the [CollectionViewSource](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource). Note that by binding the details view directly to the `CollectionViewSource`, you're implying that you want to bind to the current item in bindings where the path cannot be found on the collection itself. There's no need to specify the `CurrentItem` property as the path for the binding, although you can do that if there's any ambiguity.
217
221
218
222
```xaml
219
223
...
@@ -229,7 +233,7 @@ And here's the identical result in each case.
229
233
230
234
## Formatting or converting data values for display
231
235
232
-
There is an issue with the rendering above. The `ReleaseDateTime` property is not just a date, it's a [**DateTime**](/uwp/api/windows.foundation.datetime). So, it's being displayed with more precision than we need. One solution is to add a string property to the `Recording` class that returns the equivalent of `ReleaseDateTime.ToString("d")`. Naming that property `ReleaseDate` would indicate that it returns a date, and not a date-and-time. Naming it `ReleaseDateAsString` would further indicate that it returns a string.
236
+
There is an issue with the rendering above. The `ReleaseDateTime` property is not just a date, it's a [DateTime](/uwp/api/windows.foundation.datetime). So, it's being displayed with more precision than we need. One solution is to add a string property to the `Recording` class that returns the equivalent of `ReleaseDateTime.ToString("d")`. Naming that property `ReleaseDate` would indicate that it returns a date, and not a date-and-time. Naming it `ReleaseDateAsString` would further indicate that it returns a string.
233
237
234
238
A more flexible solution is to use something known as a value converter. Here's an example of how to author your own value converter. Add the code below to your **Recording.cs** source code file.
235
239
@@ -262,12 +266,13 @@ public class StringFormatter : Microsoft.UI.Xaml.Data.IValueConverter
262
266
}
263
267
```
264
268
265
-
Now we can add an instance of `StringFormatter` as a page resource and use it in the binding of the `TextBlock` that displays the `ReleaseDateTime` property.
269
+
Now we can add an instance of `StringFormatter` as a resource and use it in the binding of the `TextBlock` that displays the `ReleaseDateTime` property.
0 commit comments