Skip to content

Commit a3fdb4e

Browse files
Merge pull request #5089 from MicrosoftDocs/alvinashcraft/main-update-winui-data-binding-overview-resources
Update WinUI data binding overview to fix Resources use
2 parents e4e789f + 054a7db commit a3fdb4e

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

hub/apps/develop/data-binding/data-binding-overview.md

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
---
22
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
77
keywords: windows 10, windows 11, windows app sdk, winui, windows ui
88
ms.localizationpriority: medium
99
dev_langs:
1010
- 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.
1112
---
1213

1314
# Windows data binding overview
@@ -94,9 +95,9 @@ Here's the result.
9495

9596
## Binding to a collection of items
9697

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).
9899

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

101102
``` csharp
102103
public class RecordingViewModel
@@ -116,7 +117,7 @@ public class RecordingViewModel
116117
}
117118
```
118119

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

121122
``` xaml
122123
<Window x:Class="Quickstart.MainWindow" ... >
@@ -127,11 +128,11 @@ And then bind a [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.x
127128
</Window>
128129
```
129130

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

132133
![Binding a list view 1](images/xaml-databinding1.png)
133134

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

136137
``` xaml
137138
<ListView ItemsSource="{x:Bind ViewModel.Recordings}"
@@ -169,14 +170,14 @@ For more information about XAML syntax, see [Create a UI with XAML](/visualstudi
169170

170171
## Adding a details view
171172

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

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).
175176

176177
> [!NOTE]
177178
> 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).
178179
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.
180181

181182
``` xaml
182183
<Window x:Class="Quickstart.MainWindow" ... >
@@ -205,15 +206,18 @@ First, here's the [**SelectedItem**](/windows/windows-app-sdk/api/winrt/microsof
205206
</Window>
206207
```
207208

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`.
209210

210211
``` xaml
211-
<Window.Resources>
212+
<Grid.Resources>
212213
<CollectionViewSource x:Name="RecordingsCollection" Source="{x:Bind ViewModel.Recordings}"/>
213-
</Window.Resources>
214+
</Grid.Resources>
214215
```
215216

216-
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.
217221

218222
``` xaml
219223
...
@@ -229,7 +233,7 @@ And here's the identical result in each case.
229233

230234
## Formatting or converting data values for display
231235

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

234238
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.
235239

@@ -262,12 +266,13 @@ public class StringFormatter : Microsoft.UI.Xaml.Data.IValueConverter
262266
}
263267
```
264268

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

267271
``` xaml
268-
<Window.Resources>
272+
<Grid.Resources>
273+
...
269274
<local:StringFormatter x:Key="StringFormatterValueConverter"/>
270-
</Window.Resources>
275+
</Grid.Resources>
271276
...
272277
<TextBlock Text="{Binding ReleaseDateTime,
273278
Converter={StaticResource StringFormatterValueConverter},
@@ -281,6 +286,6 @@ Here's the result.
281286

282287
![displaying a date with custom formatting](images/xaml-databinding5.png)
283288

284-
## See also
289+
## Related content
285290

286-
* [Data binding](index.md)
291+
- [Data binding](index.md)

0 commit comments

Comments
 (0)