From 44ff0027c309a00fc26059f6b680d31bad1a779a Mon Sep 17 00:00:00 2001 From: Alvin Ashcraft Date: Mon, 12 Dec 2022 15:20:07 -0500 Subject: [PATCH 01/15] Adding first files to wasdk data binding topics --- .../data-binding/data-binding-in-depth.md | 32 ++ .../data-binding/data-binding-overview.md | 286 ++++++++++++++++++ .../data-binding/images/xaml-databinding0.png | Bin 0 -> 2495 bytes .../data-binding/images/xaml-databinding1.png | Bin 0 -> 2112 bytes .../data-binding/images/xaml-databinding2.png | Bin 0 -> 4530 bytes .../data-binding/images/xaml-databinding3.png | Bin 0 -> 3813 bytes .../data-binding/images/xaml-databinding4.png | Bin 0 -> 3856 bytes .../data-binding/images/xaml-databinding5.png | Bin 0 -> 3771 bytes hub/apps/develop/data-binding/index.md | 13 + hub/apps/toc.yml | 8 + hub/docfx.json | 2 + 11 files changed, 341 insertions(+) create mode 100644 hub/apps/develop/data-binding/data-binding-in-depth.md create mode 100644 hub/apps/develop/data-binding/data-binding-overview.md create mode 100644 hub/apps/develop/data-binding/images/xaml-databinding0.png create mode 100644 hub/apps/develop/data-binding/images/xaml-databinding1.png create mode 100644 hub/apps/develop/data-binding/images/xaml-databinding2.png create mode 100644 hub/apps/develop/data-binding/images/xaml-databinding3.png create mode 100644 hub/apps/develop/data-binding/images/xaml-databinding4.png create mode 100644 hub/apps/develop/data-binding/images/xaml-databinding5.png create mode 100644 hub/apps/develop/data-binding/index.md diff --git a/hub/apps/develop/data-binding/data-binding-in-depth.md b/hub/apps/develop/data-binding/data-binding-in-depth.md new file mode 100644 index 0000000000..484c8e78b6 --- /dev/null +++ b/hub/apps/develop/data-binding/data-binding-in-depth.md @@ -0,0 +1,32 @@ +--- +ms.assetid: 2a50c798-6244-4fda-9091-a10a9e87fae2 +title: Data binding in depth +description: Learn how to use data binding in Windows App SDK applications +ms.date: 12/12/2022 +ms.topic: article +keywords: windows 10, windows 11, windows app sdk, winui, windows ui +ms.localizationpriority: medium +dev_langs: + - csharp + - cppwinrt +--- + +# Data binding in depth + +## Important APIs + +- [**{x:Bind} markup extension**](../xaml-platform/x-bind-markup-extension.md) +- [**Binding class**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.binding) +- [**DataContext**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.frameworkelement.datacontext) +- [**INotifyPropertyChanged**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.inotifypropertychanged) + +## Introduction + +> [!NOTE] +> This topic describes data binding features in detail. For a short, practical introduction, see [Data binding overview](data-binding-overview.md). + +This topic is about data binding for the APIs that reside in the [**Microsoft.UI.Xaml.Data** namespace](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data). + +Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app. + +You can use data binding to simply display values from a data source when the UI is first shown, but not to respond to changes in those values. This is a mode of binding called *one-time*, and it works well for a value that doesn't change during run-time. Alternatively, you can choose to "observe" the values and to update the UI when they change. This mode is called *one-way*, and it works well for read-only data. Ultimately, you can choose to both observe and update, so that changes that the user makes to values in the UI are automatically pushed back into the data source. This mode is called *two-way*, and it works well for read-write data. Here are some examples. diff --git a/hub/apps/develop/data-binding/data-binding-overview.md b/hub/apps/develop/data-binding/data-binding-overview.md new file mode 100644 index 0000000000..bd9e0c6dd8 --- /dev/null +++ b/hub/apps/develop/data-binding/data-binding-overview.md @@ -0,0 +1,286 @@ +--- +ms.assetid: 02a08657-285d-4804-a006-168c22aa4904 +title: Data binding overview +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. +ms.date: 12/12/2022 +ms.topic: article +keywords: windows 10, windows 11, windows app sdk, winui, windows ui +ms.localizationpriority: medium +dev_langs: + - csharp +--- + +# Data binding overview + +This topic shows you how to bind a control (or other UI element) to a single item or bind an items control to a collection of items in a Windows App SDK app. In addition, we show how to control the rendering of items, implement a details view based on a selection, and convert data for display. For more detailed info, see [Data binding in depth](data-binding-in-depth.md). + +## Prerequisites + +This topic assumes that you know how to create a basic Windows App SDK app. For instructions on creating your first Windows App SDK app, see [Create your first WinUI 3 (Windows App SDK) project](/windows/apps/winui/winui3/create-your-first-winui3-app). + +## Create the project + +Create a new **Blank App, Packaged (WinUI 3 in Desktop)** C# project. Name it "Quickstart". + +## Binding to a single item + +Every binding consists of a binding target and a binding source. Typically, the target is a property of a control or other UI element, and the source is a property of a class instance (a data model, or a view model). This example shows how to bind a control to a single item. The target is the `Text` property of a `TextBlock`. The source is an instance of a simple class named `Recording` that represents an audio recording. Let's look at the class first. + +Add a new class to your project, and name the class `Recording`. + +``` csharp +namespace Quickstart +{ + public class Recording + { + public string ArtistName { get; set; } + public string CompositionName { get; set; } + public DateTime ReleaseDateTime { get; set; } + public Recording() + { + ArtistName = "Wolfgang Amadeus Mozart"; + CompositionName = "Andante in C for Piano"; + ReleaseDateTime = new DateTime(1761, 1, 1); + } + public string OneLineSummary + { + get + { + return $"{CompositionName} by {ArtistName}, released: " + + ReleaseDateTime.ToString("d"); + } + } + } + public class RecordingViewModel + { + private Recording defaultRecording = new Recording(); + public Recording DefaultRecording { get { return defaultRecording; } } + } +} +``` + +Next, expose the binding source class from the class that represents your window of markup. We do that by adding a property of type `RecordingViewModel` to **MainWindow.xaml.cs**. + +``` csharp +namespace Quickstart +{ + public sealed partial class MainWindow : Window + { + public MainWindow() + { + this.InitializeComponent(); + ViewModel = new RecordingViewModel(); + } + public RecordingViewModel ViewModel{ get; set; } + } +} +``` + +The last piece is to bind a `TextBlock` to the `ViewModel.DefaultRecording.OneLineSummary` property. + +``` xaml + + + + + +``` + +Here's the result. + +![Binding a textblock](images/xaml-databinding0.png) + +## Binding to a collection of items + +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). + +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. + +``` csharp +public class RecordingViewModel +{ + ... + private ObservableCollection recordings = new ObservableCollection(); + public ObservableCollection Recordings{ get{ return recordings; } } + public RecordingViewModel() + { + recordings.Add(new Recording(){ ArtistName = "Johann Sebastian Bach", + CompositionName = "Mass in B minor", ReleaseDateTime = new DateTime(1748, 7, 8) }); + recordings.Add(new Recording(){ ArtistName = "Ludwig van Beethoven", + CompositionName = "Third Symphony", ReleaseDateTime = new DateTime(1805, 2, 11) }); + recordings.Add(new Recording(){ ArtistName = "George Frideric Handel", + CompositionName = "Serse", ReleaseDateTime = new DateTime(1737, 12, 3) }); + } +} +``` + +And then bind a [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) to the `ViewModel.Recordings` property. + +``` xaml + + + + + +``` + +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. + +![Binding a list view 1](images/xaml-databinding1.png) + +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. + +``` xaml + + + + + + + +``` + +![Binding a list view 2](images/xaml-databinding2.png) + +``` xaml + + + + + + + + + + + + + +``` + +![Binding a list view 3](images/xaml-databinding3.png) + +For more information about XAML syntax, see [Create a UI with XAML](/visualstudio/xaml-tools/creating-a-ui-by-using-xaml-designer-in-visual-studio). For more information about control layout, see [Define layouts with XAML](/windows/apps/design/layout/layouts-with-xaml). + +## Adding a details view + +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. + +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). + +> [!NOTE] +> So far in this topic we've only used the [{x:Bind} markup extension](../xaml-platform/x-bind-markup-extension.md), but both of the techniques we'll show below require the more flexible (but less performant) [{Binding} markup extension](../xaml-platform/binding-markup-extension.md). + +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. + +``` xaml + + + + + + + + + + + + + + + + + + + + + + + +``` + +For the [**CollectionViewSource**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource) technique, first add a `CollectionViewSource` as a window resource. + +``` xaml + + + +``` + +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). + +``` xaml +... + +... + +... +``` + +And here's the identical result in each case. + +![Binding a list view 4](images/xaml-databinding4.png) + +## Formatting or converting data values for display + +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. + +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. + +``` csharp +public class StringFormatter : Microsoft.UI.Xaml.Data.IValueConverter +{ + // This converts the value object to the string to display. + // This will work with most simple types. + public object Convert(object value, Type targetType, + object parameter, string language) + { + // Retrieve the format string and use it to format the value. + string formatString = parameter as string; + if (!string.IsNullOrEmpty(formatString)) + { + return string.Format(formatString, value); + } + + // If the format string is null or empty, simply + // call ToString() on the value. + return value.ToString(); + } + + // No need to implement converting back on a one-way binding + public object ConvertBack(object value, Type targetType, + object parameter, string language) + { + throw new NotImplementedException(); + } +} +``` + +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. + +``` xaml + + + +... + +... +``` + +As you can see above, for formatting flexibility we use the markup to pass a format string into the converter by way of the converter parameter. In the code example shown in this topic, the C# value converter makes use of that parameter. + +Here's the result. + +![displaying a date with custom formatting](images/xaml-databinding5.png) + +## See also + +* [Data binding](index.md) diff --git a/hub/apps/develop/data-binding/images/xaml-databinding0.png b/hub/apps/develop/data-binding/images/xaml-databinding0.png new file mode 100644 index 0000000000000000000000000000000000000000..2ddec268610dbc49cd08c02d64ee1f2b39aab885 GIT binary patch literal 2495 zcmb7Gdpy(q9v{*|Q92BfL{S=vT*7LkAtcKrVR#lxxtrD+DwpOth&(PWb9<0n=Q1Lf z$ECR@3bPrf&fM~oCuPH?ot^V~&ht8_b9$ZUygu*m>+}A6KHtyf_4)quB{@4Gc1f#9 zgFv8NcD83-Kp-)$==kiA5P2F${@eH3cBPHk(hS@JA0 zStIWKIz(ZHQv58G8|l%vB%Aib(zZC9O5-u&=Pcnau21gR{35m^dJRwzRBRd$yyx)_ zHiqi6H$PY{4B+<-EDqDABz^J96T|QRLdiextIwGqOPxd>av%W6EZU>ZsELVk-<%ni zj7H8fWRSuhE^j}<;!Q3!pRQ{6-zu<^A*fp!9=m_*&iLWwB1ROCyO+z=7*CFNUm0l1 zf`6$ZrsesW%#!hg2(MA{mQD17MU2Km%aPM8AK?XB#M<-LvhsC5_Gt1=_Nb#LPd82w z3$dPLv4xCi5182VRd5rgELa7(Uh=hS#4%2-rAFp^FvtDdzJ6caZ-n~YL{UL=oDbyt zpz8sh-^aI&{^iXW@&EV0F$^eqKOL^Lli!&pW1DGuU`;6OZ}4WtIgp)j%_`VK;Q`j5 z7)zR+?{FF;T#KtpvPAqwyD4y6z)YTy(oNB%&Wq^RaNsQ^>dS3w2mJJ<2boP))o~9~ zWGeaDMtQ|iTa~*#Qa?9X2emB6Kx3*2a9w8y{jYgSn{Dn7 zXA8X1^H#i?nBb$<7$VtBr3}}#=vJ`OBd^W5@e7t$@Z-V>Sl7oYqBcEEun)*R$okW) z0a9RPc1#&lE_JxM)5~mi4hekD5I_#pl>VApBS$omPOdXhc@pmVLcMj3yN7!{C9HU+ z>s5W>;c>M(JDo%fsgu+E-c`S5zyOfHHmX!o?0OM+qk=mYFr#Ce?_7YUntH|RjR(Cb z<}oc+#0d=e*z;Q(9q_7iLPLR!}c z>}mOKxcQ|#{B{JRg0X>VXHd@zN{(bnRKoK8pWeNB@KvB#$qD?3Bra*1-;l7+CBYHx zJ+z(MCujeb zdM#(h@GiS8+yXO$cGGAeB%%Tj}IYeH^onK(B#5`Zx2GrTfEo(Wqe)t?7U~HLIu0HR8X&!0i zl&ZxU?qX{z?rb3*3u4dkB)cVCCieNJAu7MRhm2FNMAFKgIPY%D z;x-3VLRK;K{S6UH0~_A=}a4ZrYF| z8(EXcf#de1>YoIzT;|p4sS^oj9F@kWEzrZ0G)>dxxG0 zRu`J3#dqMo*~1Tb-7iJRrL_13b9*|yOqQ-RHKAGwV-@AzjFY_ND&surJl+7JU~w!3 zy#CSBFG^ey_;_v1ose(gXOcI$@T|OhQfi92V!mm}4bzQXfq#`E)K0x;sNWN0N3Ix+ z9_^%e_A3m~HG2JJ^6*_S@c7mtVi2Qe&<)3L#OmW4(SaK-wINePRBKR}EdnsBlBw&S z4vl{=h0Ha2;mf;I>Q;AXgq#EEUhN5LggSQ?l7Ak3@csoxZuNS>r*sOH7chpJX|r!$ z`fIG^b@y3D<BAsm(Vb)Eq(53;XL%+iJ)L>bG9#kSexhfL>^`LZ zEO>M;cL6Mi8U5*%Pen!PlX~z5ECh=(^_c)&p?QuO^}+nq%UVA&S|Kicg?3vOWh7yt z8945nDMc&bizON7Ozh{(chDAF+NZ(@-jS%8#S5<0wOnWL=#?Br7>0HTeqLvYSp*S{ z<8-vEt?RLnDNm%}xZtw{_2BAVQ}RE zfc?tlxh$XRnA3**I~}NL)%A(~4eb@2Ipl^Y5akp6jwOuB*iDJKqq?3aylag{{7(U! zp97hT{{dm_`9mVCN6@#4elR=kZ#EkD=oN@FM^bS0MQY0d2=i}g;D5UQd9muhCj2AX l^1X6Jo-Md<+blB8j5Zqf|InSO1`$mKva@kITV;j5_czxE;%5K= literal 0 HcmV?d00001 diff --git a/hub/apps/develop/data-binding/images/xaml-databinding1.png b/hub/apps/develop/data-binding/images/xaml-databinding1.png new file mode 100644 index 0000000000000000000000000000000000000000..0d7434c1a07ae2370d4c1915a2dd9536aee80b6f GIT binary patch literal 2112 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 literal 0 HcmV?d00001 diff --git a/hub/apps/develop/data-binding/images/xaml-databinding3.png b/hub/apps/develop/data-binding/images/xaml-databinding3.png new file mode 100644 index 0000000000000000000000000000000000000000..7139b228323dd6b7e6ba2c273663635e7910ee9b GIT binary patch literal 3813 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 literal 0 HcmV?d00001 diff --git a/hub/apps/develop/data-binding/images/xaml-databinding4.png b/hub/apps/develop/data-binding/images/xaml-databinding4.png new file mode 100644 index 0000000000000000000000000000000000000000..f0f5b16e1d49d6aa96bb4a0767047d65f7633fd5 GIT binary patch literal 3856 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 literal 0 HcmV?d00001 diff --git a/hub/apps/develop/data-binding/images/xaml-databinding5.png b/hub/apps/develop/data-binding/images/xaml-databinding5.png new file mode 100644 index 0000000000000000000000000000000000000000..7f3617d486b249a6a70b554a391bd2048cfad647 GIT binary patch literal 3771 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 literal 0 HcmV?d00001 diff --git a/hub/apps/develop/data-binding/index.md b/hub/apps/develop/data-binding/index.md new file mode 100644 index 0000000000..5e7a1876db --- /dev/null +++ b/hub/apps/develop/data-binding/index.md @@ -0,0 +1,13 @@ +--- +ms.assetid: adfa70f3-a4d9-45d1-8957-c26a7703a276 +title: Data binding in Windows apps +description: Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. +ms.date: 12/12/2022 +ms.topic: article +keywords: windows 10, windows 11, windows app sdk, winui, windows ui +ms.localizationpriority: medium +--- + +# Data binding in Windows apps + +Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app. In XAML markup, you can choose to use either the [{x:Bind} markup extension](../xaml-platform/x-bind-markup-extension.md) or the [{Binding} markup extension](../xaml-platform/binding-markup-extension.md). And you can even use a mixture of the two in the same app—even on the same UI element. `{x:Bind}` was new for UWP in Windows 10, is also available in Windows App SDK, and it has better performance. diff --git a/hub/apps/toc.yml b/hub/apps/toc.yml index 1fca1477d6..90833dde74 100644 --- a/hub/apps/toc.yml +++ b/hub/apps/toc.yml @@ -362,6 +362,14 @@ items: href: develop/data-access/mysql-database.md - name: Use MongoDB in a Windows App href: develop/data-access/mongodb-database.md + - name: Data binding + items: + - name: Data binding + href: develop/data-binding/index.md + - name: Data binding overview + href: develop/data-binding/data-binding-overview.md + - name: Data binding in depth + href: develop/data-binding/data-binding-in-depth.md - name: Data and files overview href: develop/data-and-files.md - name: Manage resources with MRT Core diff --git a/hub/docfx.json b/hub/docfx.json index 2d3db32cba..1b4193d439 100644 --- a/hub/docfx.json +++ b/hub/docfx.json @@ -142,6 +142,7 @@ "apps/desktop/modernize/**/*.md": "stevewhims", "apps/develop/**/*.md": "stevewhims", "apps/develop/data-access/**/*.md": "alvinashcraft", + "apps/develop/data-binding/**/*.md": "alvinashcraft", "apps/develop/platform/**/*.md": "stevewhims", "apps/develop/ui-input/**/*.md": "Karl-Bridge-Microsoft", "apps/develop/widgets/**/*.md": "drewbatgit", @@ -191,6 +192,7 @@ "apps/desktop/modernize/**/*.md": "stwhi", "apps/develop/**/*.md": "stwhi", "apps/develop/data-access/**/*.md": "aashcraft", + "apps/develop/data-binding/**/*.md": "aashcraft", "apps/develop/platform/**/*.md": "stwhi", "apps/develop/ui-input/**/*.md": "kbridge", "apps/develop/widgets/**/*.md": "drewbatgit", From 0fde7611532a6d927992df1e3844e32608b01c96 Mon Sep 17 00:00:00 2001 From: Alvin Ashcraft Date: Mon, 12 Dec 2022 15:26:42 -0500 Subject: [PATCH 02/15] Fix links --- hub/apps/develop/data-binding/data-binding-in-depth.md | 2 +- hub/apps/develop/data-binding/data-binding-overview.md | 2 +- hub/apps/develop/data-binding/index.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hub/apps/develop/data-binding/data-binding-in-depth.md b/hub/apps/develop/data-binding/data-binding-in-depth.md index 484c8e78b6..4a928f817b 100644 --- a/hub/apps/develop/data-binding/data-binding-in-depth.md +++ b/hub/apps/develop/data-binding/data-binding-in-depth.md @@ -15,7 +15,7 @@ dev_langs: ## Important APIs -- [**{x:Bind} markup extension**](../xaml-platform/x-bind-markup-extension.md) +- [**{x:Bind} markup extension**](/windows/uwp/xaml-platform/x-bind-markup-extension) - [**Binding class**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.binding) - [**DataContext**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.frameworkelement.datacontext) - [**INotifyPropertyChanged**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.inotifypropertychanged) diff --git a/hub/apps/develop/data-binding/data-binding-overview.md b/hub/apps/develop/data-binding/data-binding-overview.md index bd9e0c6dd8..07661ab360 100644 --- a/hub/apps/develop/data-binding/data-binding-overview.md +++ b/hub/apps/develop/data-binding/data-binding-overview.md @@ -174,7 +174,7 @@ You can choose to display all the details of `Recording` objects in [**ListView* 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). > [!NOTE] -> So far in this topic we've only used the [{x:Bind} markup extension](../xaml-platform/x-bind-markup-extension.md), but both of the techniques we'll show below require the more flexible (but less performant) [{Binding} markup extension](../xaml-platform/binding-markup-extension.md). +> 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). 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. diff --git a/hub/apps/develop/data-binding/index.md b/hub/apps/develop/data-binding/index.md index 5e7a1876db..4918d0ef0c 100644 --- a/hub/apps/develop/data-binding/index.md +++ b/hub/apps/develop/data-binding/index.md @@ -10,4 +10,4 @@ ms.localizationpriority: medium # Data binding in Windows apps -Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app. In XAML markup, you can choose to use either the [{x:Bind} markup extension](../xaml-platform/x-bind-markup-extension.md) or the [{Binding} markup extension](../xaml-platform/binding-markup-extension.md). And you can even use a mixture of the two in the same app—even on the same UI element. `{x:Bind}` was new for UWP in Windows 10, is also available in Windows App SDK, and it has better performance. +Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app. In XAML markup, you can choose to use either the [{x:Bind} markup extension](/windows/uwp/xaml-platform/x-bind-markup-extension) or the [{Binding} markup extension](/windows/uwp/xaml-platform/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}` was new for UWP in Windows 10, is also available in Windows App SDK, and it has better performance. From 6c66d2b218926820a4acb5494d5ab1088f9e1063 Mon Sep 17 00:00:00 2001 From: Alvin Ashcraft Date: Mon, 12 Dec 2022 15:52:23 -0500 Subject: [PATCH 03/15] Add start of remaining data binding topics --- ...ical-data-and-create-a-master-details-view.md | 16 ++++++++++++++++ .../data-binding/data-binding-and-mvvm.md | 15 +++++++++++++++ hub/apps/develop/data-binding/index.md | 11 +++++++++++ hub/apps/toc.yml | 4 ++++ 4 files changed, 46 insertions(+) create mode 100644 hub/apps/develop/data-binding/bind-to-hierarchical-data-and-create-a-master-details-view.md create mode 100644 hub/apps/develop/data-binding/data-binding-and-mvvm.md diff --git a/hub/apps/develop/data-binding/bind-to-hierarchical-data-and-create-a-master-details-view.md b/hub/apps/develop/data-binding/bind-to-hierarchical-data-and-create-a-master-details-view.md new file mode 100644 index 0000000000..229e2fb1f0 --- /dev/null +++ b/hub/apps/develop/data-binding/bind-to-hierarchical-data-and-create-a-master-details-view.md @@ -0,0 +1,16 @@ +--- +ms.assetid: 6c563dd4-3dd0-4175-a1ab-7a1103fc9559 +title: Bind hierarchical data and create a master/details view +description: You can make a multi-level master/details (also known as list-details) view of hierarchical data by binding items controls to CollectionViewSource instances that are bound together in a chain. +ms.date: 12/12/2022 +ms.topic: article +keywords: windows 10, windows 11, winui, windows app sdk, windows ui +ms.localizationpriority: medium +--- + +# Bind hierarchical data and create a master/details view + +> [!NOTE] +> Also see the [Master/detail sample](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlMasterDetail). + +You can make a multi-level master/details (also known as list-details) view of hierarchical data by binding items controls to [**CollectionViewSource**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource) instances that are bound together in a chain. In this topic we use the [{x:Bind} markup extension](/windows/uwp/xaml-platform/x-bind-markup-extension) where possible, and the more flexible (but less performant) [{Binding} markup extension](/windows/uwp/xaml-platform/binding-markup-extension) where necessary. diff --git a/hub/apps/develop/data-binding/data-binding-and-mvvm.md b/hub/apps/develop/data-binding/data-binding-and-mvvm.md new file mode 100644 index 0000000000..fa7651f7e3 --- /dev/null +++ b/hub/apps/develop/data-binding/data-binding-and-mvvm.md @@ -0,0 +1,15 @@ +--- +ms.assetid: b7a8ec88-3013-4e5a-a110-fab3f20ee4bf +title: Data binding and MVVM +description: Data binding is at the core of the Model-View-ViewModel (MVVM) UI architectural design pattern, and enables loose coupling between UI and non-UI code. +ms.date: 12/12/2022 +ms.topic: article +keywords: windows 10, windows 11, windows app sdk, winui, windows ui +ms.localizationpriority: medium +--- + +# Data binding and MVVM + +Model-View-ViewModel (MVVM) is a UI architectural design pattern for decoupling UI and non-UI code. With MVVM, you define your UI declaratively in XAML and use data binding markup to link it to other layers containing data and commands. The data binding infrastructure provides a loose coupling that keeps the UI and the linked data synchronized and routes user input to the appropriate commands. + +Because it provides loose coupling, the use of data binding reduces hard dependencies between different kinds of code. This makes it easier to change individual code units (methods, classes, controls, etc.) without causing unintended side effects in other units. This decoupling is an example of the *separation of concerns*, which is an important concept in many design patterns. diff --git a/hub/apps/develop/data-binding/index.md b/hub/apps/develop/data-binding/index.md index 4918d0ef0c..d1593f02e1 100644 --- a/hub/apps/develop/data-binding/index.md +++ b/hub/apps/develop/data-binding/index.md @@ -11,3 +11,14 @@ ms.localizationpriority: medium # Data binding in Windows apps Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app. In XAML markup, you can choose to use either the [{x:Bind} markup extension](/windows/uwp/xaml-platform/x-bind-markup-extension) or the [{Binding} markup extension](/windows/uwp/xaml-platform/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}` was new for UWP in Windows 10, is also available in Windows App SDK, and it has better performance. + +| Topic | Description | +|-------|-------------| +| [Data binding overview](data-binding-overview.md) | This topic shows you how to bind a control (or other UI element) to a single item or bind an items control to a collection of items in a Windows App SDK app. In addition, we show how to control the rendering of items, implement a details view based on a selection, and convert data for display. For more detailed info, see [Data binding in depth](data-binding-in-depth.md). | +| [Data binding in depth](data-binding-in-depth.md) | This topic describes data binding features in detail. | +| [Bind hierarchical data and create a master/details view](bind-to-hierarchical-data-and-create-a-master-details-view.md) | You can make a multi-level master/details (also known as list-details) view of hierarchical data by binding items controls to [**CollectionViewSource**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource) instances that are bound together in a chain. | +| [Data binding and MVVM](data-binding-and-mvvm.md) | This topic describes the Model-View-ViewModel (MVVM) UI architectural design pattern. Data binding is at the core of MVVM, and enables loose coupling between UI and non-UI code. | + +## See also + +* [Data binding in UWP apps](/windows/uwp/data-binding/) diff --git a/hub/apps/toc.yml b/hub/apps/toc.yml index 90833dde74..61de541299 100644 --- a/hub/apps/toc.yml +++ b/hub/apps/toc.yml @@ -370,6 +370,10 @@ items: href: develop/data-binding/data-binding-overview.md - name: Data binding in depth href: develop/data-binding/data-binding-in-depth.md + - name: Bind to hierarchical data and create a master/details view + href: develop/data-binding/bind-to-hierarchical-data-and-create-a-master-details-view.md + - name: Data binding and MVVM + href: develop/data-binding/data-binding-and-mvvm.md - name: Data and files overview href: develop/data-and-files.md - name: Manage resources with MRT Core From 7282f076c7fd2df3c4238c7888ce7413982ed4f6 Mon Sep 17 00:00:00 2001 From: Alvin Ashcraft Date: Mon, 12 Dec 2022 16:38:06 -0500 Subject: [PATCH 04/15] Update data binding in depth --- .../data-binding/data-binding-in-depth.md | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/hub/apps/develop/data-binding/data-binding-in-depth.md b/hub/apps/develop/data-binding/data-binding-in-depth.md index 4a928f817b..76188e6978 100644 --- a/hub/apps/develop/data-binding/data-binding-in-depth.md +++ b/hub/apps/develop/data-binding/data-binding-in-depth.md @@ -30,3 +30,120 @@ This topic is about data binding for the APIs that reside in the [**Microsoft.UI Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app. You can use data binding to simply display values from a data source when the UI is first shown, but not to respond to changes in those values. This is a mode of binding called *one-time*, and it works well for a value that doesn't change during run-time. Alternatively, you can choose to "observe" the values and to update the UI when they change. This mode is called *one-way*, and it works well for read-only data. Ultimately, you can choose to both observe and update, so that changes that the user makes to values in the UI are automatically pushed back into the data source. This mode is called *two-way*, and it works well for read-write data. Here are some examples. + +- You could use the one-time mode to bind an [**Image**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.image) to the current user's photo. +- You could use the one-way mode to bind a [**ListView**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) to a collection of real-time news articles grouped by newspaper section. +- You could use the two-way mode to bind a [**TextBox**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.textbox) to a customer's name in a form. + +Independent of mode, there are two kinds of binding, and they're both typically declared in UI markup. You can choose to use either the [{x:Bind} markup extension](/windows/uwp/xaml-platform/x-bind-markup-extension) or the [{Binding} markup extension](/windows/uwp/xaml-platform/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}` was new in UWP for Windows 10 and it has better performance. All the details described in this topic apply to both kinds of binding unless we explicitly say otherwise. + +### UWP Sample apps that demonstrate {x:Bind} + +- [{x:Bind} sample](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlBind). +- [QuizGame](https://github.com/microsoft/Windows-appsample-networkhelper). +- [XAML UI Basics sample](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlUIBasics). + +### UWP Sample apps that demonstrate {Binding} + +- Download the [UWP Bookstore1](https://codeload.github.com/MicrosoftDocs/windows-topic-specific-samples/zip/Bookstore1Universal_10) app. +- Download the [Bookstore2](https://codeload.github.com/MicrosoftDocs/windows-topic-specific-samples/zip/Bookstore2Universal_10) app. + +## Every binding involves these pieces + +- A *binding source*. This is the source of the data for the binding, and it can be an instance of any class that has members whose values you want to display in your UI. +- A *binding target*. This is a [**DependencyProperty**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.dependencyproperty) of the [**FrameworkElement**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.frameworkelement) in your UI that displays the data. +- A *binding object*. This is the piece that transfers data values from the source to the target, and optionally from the target back to the source. The binding object is created at XAML load time from your [{x:Bind}](/windows/uwp/xaml-platform/x-bind-markup-extension) or [{Binding}](/windows/uwp/xaml-platform/binding-markup-extension) markup extension. + +In the following sections, we'll take a closer look at the binding source, the binding target, and the binding object. And we'll link the sections together with the example of binding a button's content to a string property named `NextButtonText`, which belongs to a class named `HostViewModel`. + +### Binding source + +Here's a very rudimentary implementation of a class that we could use as a binding source. + +``` csharp +public class HostViewModel +{ + public HostViewModel() + { + NextButtonText = "Next"; + } + + public string NextButtonText { get; set; } +} +``` + +That implementation of `HostViewModel`, and its property `NextButtonText`, are only appropriate for one-time binding. But one-way and two-way bindings are extremely common, and in those kinds of binding the UI automatically updates in response to changes in the data values of the binding source. In order for those kinds of binding to work correctly, you need to make your binding source "observable" to the binding object. So in our example, if we want to one-way or two-way bind to the `NextButtonText` property, then any changes that happen at run-time to the value of that property need to be made observable to the binding object. + +One way of doing that is to derive the class that represents your binding source from [**DependencyObject**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.dependencyobject), and expose a data value through a [**DependencyProperty**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.dependencyproperty). That's how a [**FrameworkElement**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.frameworkelement) becomes observable. A `FrameworkElement` is a good binding source right out of the box. + +A more lightweight way of making a class observable—and a necessary one for classes that already have a base class—is to implement [**System.ComponentModel.INotifyPropertyChanged**](/dotnet/api/system.componentmodel.inotifypropertychanged). This really just involves implementing a single event named `PropertyChanged`. An example using `HostViewModel` is below. + +``` csharp +... +using System.ComponentModel; +using System.Runtime.CompilerServices; +... +public class HostViewModel : INotifyPropertyChanged +{ + private string nextButtonText; + + public event PropertyChangedEventHandler PropertyChanged = delegate { }; + + public HostViewModel() + { + NextButtonText = "Next"; + } + + public string NextButtonText + { + get { return nextButtonText; } + set + { + nextButtonText = value; + OnPropertyChanged(); + } + } + + public void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + // Raise the PropertyChanged event, passing the name of the property whose value has changed. + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } +} +``` + +Now the `NextButtonText` property is observable. When you author a one-way or a two-way binding to that property (we'll show how later), the resulting binding object subscribes to the `PropertyChanged` event. When that event is raised, the binding object's handler receives an argument containing the name of the property that has changed. That's how the binding object knows which property's value to go and read again. + +So that you don't have to implement the pattern shown above multiple times, if you're using C# then you can just derive from the `BindableBase` base class that you'll find in the [QuizGame](https://github.com/microsoft/Windows-appsample-networkhelper) sample (in the "Common" folder). Here's an example of how that looks. + +``` csharp +public class HostViewModel : BindableBase +{ + private string nextButtonText; + + public HostViewModel() + { + NextButtonText = "Next"; + } + + public string NextButtonText + { + get { return nextButtonText; } + set { SetProperty(ref nextButtonText, value); } + } +} +``` + +Raising the `PropertyChanged` event with an argument of [**String.Empty**](/dotnet/api/system.string.empty) or `null` indicates that all non-indexer properties on the object should be re-read. You can raise the event to indicate that indexer properties on the object have changed by using an argument of "Item\[*indexer*\]" for specific indexers (where *indexer* is the index value), or a value of "Item\[\]" for all indexers. + +A binding source can be treated either as a single object whose properties contain data, or as a collection of objects. In C# code, you can one-time bind to an object that implements [**List(Of T)**](/dotnet/api/system.collections.generic.list-1) to display a collection that doesn't change at run-time. For an observable collection (observing when items are added to and removed from the collection), one-way bind to [**ObservableCollection(Of T)**](/dotnet/api/system.collections.objectmodel.observablecollection-1) instead. To bind to your own collection classes, use the guidance in the following table. + +| Scenario | C# (CLR) | C++/WinRT | +|-|-|-| +| Bind to an object. | Can be any object. | Can be any object. | +| Get property change notifications from a bound object. | Object must implement [**INotifyPropertyChanged**](/dotnet/api/system.componentmodel.inotifypropertychanged). | Object must implement [**INotifyPropertyChanged**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.inotifypropertychanged). | +| Bind to a collection. | [**List(Of T)**](/dotnet/api/system.collections.generic.list-1) | [**IVector**](/uwp/api/windows.foundation.collections.ivector_t_) of [**IInspectable**](/windows/win32/api/inspectable/nn-inspectable-iinspectable), or [**IBindableObservableVector**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.interop.ibindableobservablevector). See [XAML items controls; bind to a C++/WinRT collection](/windows/uwp/cpp-and-winrt-apis/binding-collection) and [Collections with C++/WinRT](/windows/uwp/cpp-and-winrt-apis/collections). | +| Get collection change notifications from a bound collection. | [**ObservableCollection(Of T)**](/dotnet/api/system.collections.objectmodel.observablecollection-1)|[**IObservableVector**](/uwp/api/windows.foundation.collections.iobservablevector_t_) of [**IInspectable**](/windows/win32/api/inspectable/nn-inspectable-iinspectable). For example, [**winrt::single_threaded_observable_vector<T>**](/uwp/cpp-ref-for-winrt/single-threaded-observable-vector). | +| Implement a collection that supports binding. | Extend [**List(Of T)**](/dotnet/api/system.collections.generic.list-1) or implement [**IList**](/dotnet/api/system.collections.ilist), [**IList**](/dotnet/api/system.collections.generic.ilist-1)(Of [**Object**](/dotnet/api/system.object)), [**IEnumerable**](/dotnet/api/system.collections.ienumerable), or [**IEnumerable**](/dotnet/api/system.collections.generic.ienumerable-1)(Of **Object**). Binding to generic `IList(Of T)` and `IEnumerable(Of T)` is not supported. | Implement [**IVector**](/uwp/api/windows.foundation.collections.ivector_t_) of [**IInspectable**](/windows/win32/api/inspectable/nn-inspectable-iinspectable). See [XAML items controls; bind to a C++/WinRT collection](/windows/uwp/cpp-and-winrt-apis/binding-collection) and [Collections with C++/WinRT](/windows/uwp/cpp-and-winrt-apis/collections). | +| Implement a collection that supports collection change notifications. | Extend [**ObservableCollection(Of T)**](/dotnet/api/system.collections.objectmodel.observablecollection-1) or implement (non-generic) [**IList**](/dotnet/api/system.collections.ilist) and [**INotifyCollectionChanged**](/dotnet/api/system.collections.specialized.inotifycollectionchanged). | Implement [**IObservableVector**](/uwp/api/windows.foundation.collections.iobservablevector_t_) of [**IInspectable**](/windows/win32/api/inspectable/nn-inspectable-iinspectable), or [**IBindableObservableVector**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.interop.ibindableobservablevector). | +| Implement a collection that supports incremental loading. | Extend [**ObservableCollection(Of T)**](/dotnet/api/system.collections.objectmodel.observablecollection-1) or implement (non-generic) [**IList**](/dotnet/api/system.collections.ilist) and [**INotifyCollectionChanged**](/dotnet/api/system.collections.specialized.inotifycollectionchanged). Additionally, implement [**ISupportIncrementalLoading**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.isupportincrementalloading). | Implement [**IObservableVector**](/uwp/api/windows.foundation.collections.iobservablevector_t_) of [**IInspectable**](/windows/win32/api/inspectable/nn-inspectable-iinspectable), or [**IBindableObservableVector**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.interop.ibindableobservablevector). Additionally, implement [**ISupportIncrementalLoading**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.isupportincrementalloading) | From 16697cb2ccb121806e5a0a8a44b04d9ca3ad70ae Mon Sep 17 00:00:00 2001 From: Alvin Ashcraft Date: Tue, 13 Dec 2022 11:13:01 -0500 Subject: [PATCH 05/15] Fill in data binding in depth and func bindings --- .../data-binding/data-binding-in-depth.md | 480 ++++++++++++++++++ .../develop/data-binding/function-bindings.md | 181 +++++++ hub/apps/develop/data-binding/images/sezo.png | Bin 0 -> 43010 bytes hub/apps/toc.yml | 2 + 4 files changed, 663 insertions(+) create mode 100644 hub/apps/develop/data-binding/function-bindings.md create mode 100644 hub/apps/develop/data-binding/images/sezo.png diff --git a/hub/apps/develop/data-binding/data-binding-in-depth.md b/hub/apps/develop/data-binding/data-binding-in-depth.md index 76188e6978..d4df94b309 100644 --- a/hub/apps/develop/data-binding/data-binding-in-depth.md +++ b/hub/apps/develop/data-binding/data-binding-in-depth.md @@ -147,3 +147,483 @@ A binding source can be treated either as a single object whose properties conta | Implement a collection that supports binding. | Extend [**List(Of T)**](/dotnet/api/system.collections.generic.list-1) or implement [**IList**](/dotnet/api/system.collections.ilist), [**IList**](/dotnet/api/system.collections.generic.ilist-1)(Of [**Object**](/dotnet/api/system.object)), [**IEnumerable**](/dotnet/api/system.collections.ienumerable), or [**IEnumerable**](/dotnet/api/system.collections.generic.ienumerable-1)(Of **Object**). Binding to generic `IList(Of T)` and `IEnumerable(Of T)` is not supported. | Implement [**IVector**](/uwp/api/windows.foundation.collections.ivector_t_) of [**IInspectable**](/windows/win32/api/inspectable/nn-inspectable-iinspectable). See [XAML items controls; bind to a C++/WinRT collection](/windows/uwp/cpp-and-winrt-apis/binding-collection) and [Collections with C++/WinRT](/windows/uwp/cpp-and-winrt-apis/collections). | | Implement a collection that supports collection change notifications. | Extend [**ObservableCollection(Of T)**](/dotnet/api/system.collections.objectmodel.observablecollection-1) or implement (non-generic) [**IList**](/dotnet/api/system.collections.ilist) and [**INotifyCollectionChanged**](/dotnet/api/system.collections.specialized.inotifycollectionchanged). | Implement [**IObservableVector**](/uwp/api/windows.foundation.collections.iobservablevector_t_) of [**IInspectable**](/windows/win32/api/inspectable/nn-inspectable-iinspectable), or [**IBindableObservableVector**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.interop.ibindableobservablevector). | | Implement a collection that supports incremental loading. | Extend [**ObservableCollection(Of T)**](/dotnet/api/system.collections.objectmodel.observablecollection-1) or implement (non-generic) [**IList**](/dotnet/api/system.collections.ilist) and [**INotifyCollectionChanged**](/dotnet/api/system.collections.specialized.inotifycollectionchanged). Additionally, implement [**ISupportIncrementalLoading**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.isupportincrementalloading). | Implement [**IObservableVector**](/uwp/api/windows.foundation.collections.iobservablevector_t_) of [**IInspectable**](/windows/win32/api/inspectable/nn-inspectable-iinspectable), or [**IBindableObservableVector**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.interop.ibindableobservablevector). Additionally, implement [**ISupportIncrementalLoading**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.isupportincrementalloading) | + +You can bind list controls to arbitrarily large data sources, and still achieve high performance, by using incremental loading. For example, you can bind list controls to Bing image query results without having to load all the results at once. Instead, you load only some results immediately, and load additional results as needed. To support incremental loading, you must implement [**ISupportIncrementalLoading**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.isupportincrementalloading) on a data source that supports collection change notifications. When the data binding engine requests more data, your data source must make the appropriate requests, integrate the results, and then send the appropriate notifications in order to update the UI. + +### Binding target + +In the two examples below, the `Button.Content` property is the binding target, and its value is set to a markup extension that declares the binding object. First [{x:Bind}](/windows/uwp/xaml-platform/x-bind-markup-extension) is shown, and then [{Binding}](/windows/uwp/xaml-platform/binding-markup-extension). Declaring bindings in markup is the common case (it's convenient, readable, and toolable). But you can avoid markup and imperatively (programmatically) create an instance of the [**Binding**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.binding) class instead if you need to. + +``` xaml +