Skip to content

Commit

Permalink
Use compiled bindings (#2807)
Browse files Browse the repository at this point in the history
* Use compiled bindings.

* Use compiled bindings.

* Use compiled bindings.

* Use compiled bindings.
  • Loading branch information
davidbritch authored Feb 27, 2025
1 parent d99afc0 commit 7efc00f
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 104 deletions.
2 changes: 1 addition & 1 deletion docs/fundamentals/accessibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ The accessibility information for an element can also be defined on another elem
```xaml
<Label x:Name="label"
Text="Enable dark mode: " />
<Switch SemanticProperties.Description="{Binding Source={x:Reference label} Path=Text}" />
<Switch SemanticProperties.Description="{Binding x:DataType='Label', Source={x:Reference label}, Path=Text}" />
```

Alternatively, it can be set in C# as follows:
Expand Down
19 changes: 14 additions & 5 deletions docs/fundamentals/controltemplate.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ The following XAML example shows a <xref:Microsoft.Maui.Controls.ControlTemplate
```xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:ControlTemplateDemos.Controls"
...>
<ContentPage.Resources>
<ControlTemplate x:Key="CardViewControlTemplate">
<ControlTemplate x:Key="CardViewControlTemplate"
x:DataType="controls:CardView">
<Border BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
BackgroundColor="{Binding CardColor}"
Stroke="{Binding BorderColor}"
Expand Down Expand Up @@ -195,8 +197,10 @@ For example, the `CardViewUI` custom control defines its user interface using th
```xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:ControlTemplateDemos.Controls"
x:Class="ControlTemplateDemos.Controls.CardViewUI"
x:Name="this">
x:Name="this"
x:DataType="controls:CardViewUI">
<Border BindingContext="{x:Reference this}"
BackgroundColor="{Binding CardColor}"
Stroke="{Binding BorderColor}"
Expand All @@ -211,9 +215,11 @@ However, the controls that comprise this UI can be replaced by defining a new vi
```xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:ControlTemplateDemos.Controls"
...>
<ContentPage.Resources>
<ControlTemplate x:Key="CardViewCompressed">
<ControlTemplate x:Key="CardViewCompressed"
x:DataType="controls:CardView">
<Grid RowDefinitions="100"
ColumnDefinitions="100, *">
<Image Source="{TemplateBinding IconImageSource}"
Expand Down Expand Up @@ -360,13 +366,15 @@ The following XAML example shows a page that consumes a viewmodel named `PeopleV
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ControlTemplateDemos"
xmlns:controls="clr-namespace:ControlTemplateDemos.Controls"
x:DataType="local:PeopleViewModel"
...>
<ContentPage.BindingContext>
<local:PeopleViewModel />
</ContentPage.BindingContext>

<ContentPage.Resources>
<DataTemplate x:Key="PersonTemplate">
<DataTemplate x:Key="PersonTemplate"
x:DataType="local:Person">
<controls:CardView BorderColor="DarkGray"
CardTitle="{Binding Name}"
CardDescription="{Binding Description}"
Expand All @@ -383,7 +391,8 @@ The following XAML example shows a page that consumes a viewmodel named `PeopleV
In this example, the <xref:Microsoft.Maui.Controls.BindableObject.BindingContext> of the page is set to a `PeopleViewModel` instance. This viewmodel exposes a `People` collection and an <xref:System.Windows.Input.ICommand> named `DeletePersonCommand`. The <xref:Microsoft.Maui.Controls.StackLayout> on the page uses a bindable layout to data bind to the `People` collection, and the [`ItemTemplate`](xref:Microsoft.Maui.Controls.BindableLayout.ItemTemplateProperty) of the bindable layout is set to the `PersonTemplate` resource. This <xref:Microsoft.Maui.Controls.DataTemplate> specifies that each item in the `People` collection will be displayed using a `CardView` object. The visual structure of the `CardView` object is defined using a <xref:Microsoft.Maui.Controls.ControlTemplate> named `CardViewControlTemplate`:

```xaml
<ControlTemplate x:Key="CardViewControlTemplate">
<ControlTemplate x:Key="CardViewControlTemplate"
x:DataType="controls:CardView">
<Border BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
BackgroundColor="{Binding CardColor}"
Stroke="{Binding BorderColor}"
Expand Down
29 changes: 17 additions & 12 deletions docs/fundamentals/data-binding/basic-bindings.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Basic bindings"
description: ".NET MAUI data binding links a pair of properties between two objects, at least one of which is usually a user-interface object. These two objects are called the target and the source."
ms.date: 09/26/2024
ms.date: 02/27/2025
---

# Basic bindings
Expand Down Expand Up @@ -70,7 +70,7 @@ The <xref:Microsoft.Maui.Controls.Label> object is the binding target so that's
> [!IMPORTANT]
> The target property must be backed by a bindable property. Therefore, the target object must be an instance of a class that derives from <xref:Microsoft.Maui.Controls.BindableObject>. For more information, see [Bindable properties](../bindable-properties.md).
The source property is specified using a lambda expression, and uses a technique called compiled bindings. For more information about compiled bindings, see [Compiled bindings](compiled-bindings.md).
In the example above the binding source is specified using a `Func`, which ensures that the binding expression is compiled for increased runtime performance. For more information about compiled bindings, see [Compiled bindings](compiled-bindings.md).

As you manipulate the <xref:Microsoft.Maui.Controls.Slider>, the <xref:Microsoft.Maui.Controls.Label> rotates accordingly:

Expand All @@ -84,7 +84,8 @@ Alternatively, the data binding can be specified in XAML:
x:Class="DataBindingDemos.BasicXamlBindingPage"
Title="Basic XAML Binding">
<StackLayout Padding="10, 0">
<Label Text="TEXT"
<Label x:DataType="Slider"
Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="Center"
Expand All @@ -105,23 +106,23 @@ Just as in code, the data binding is set on the target object, which is the <xre

For more information about XAML markup extensions, see [Consume XAML markup extensions](../../xaml/markup-extensions/consume.md).

In addition, the `x:DataType` attribute on the `Label` instructs the XAML compiler to compile the binding expression on the `Label` for increased runtime performance, and specifies that the binding expression should be resolved against the `Slider` type. For more information, see [Compiled bindings](compiled-bindings.md).

> [!NOTE]
> The source property is specified with the `Path` property of the `Binding` markup extension, which corresponds with the `Path` property of the `Binding` class.
XAML markup extensions such as `x:Reference` and `Binding` can have *content property* attributes defined, which for XAML markup extensions means that the property name doesn't need to appear. The `Name` property is the content property of `x:Reference`, and the `Path` property is the content property of `Binding`, which means that they can be eliminated from the expressions:

```xaml
<Label Text="TEXT"
<Label x:DataType="Slider"
Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="Center"
BindingContext="{x:Reference slider}"
Rotation="{Binding Value}" />
```

> [!IMPORTANT]
> Binding performance can be improved by using compiled bindings. For more information, see [Compiled bindings](compiled-bindings.md).
## Bindings without a binding context

The `BindingContext` property is an important component of data bindings, but it is not always necessary. The source object can instead be specified in the `SetBinding` call or the `Binding` markup extension:
Expand Down Expand Up @@ -177,7 +178,8 @@ Alternatively, the data binding can be specified in XAML:
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="Center"
Scale="{Binding Source={x:Reference slider},
Scale="{Binding x:DataType='Slider',
Source={x:Reference slider},
Path=Value}" />

<Slider x:Name="slider"
Expand All @@ -193,7 +195,7 @@ In this example, the `Binding` markup extension has two properties set, `Source`
The content property of the `Binding` markup extension is `Path`, but the `Path=` part of the markup extension can only be eliminated if it is the first property in the expression. To eliminate the `Path=` part, you need to swap the two properties:

```xaml
Scale="{Binding Value, Source={x:Reference slider}}" />
Scale="{Binding Value, Source={x:Reference slider}, x:DataType='Slider'}" />
```

Although XAML markup extensions are usually delimited by curly braces, they can also be expressed as object elements:
Expand All @@ -204,7 +206,8 @@ Although XAML markup extensions are usually delimited by curly braces, they can
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.Scale>
<Binding Source="{x:Reference slider}"
<Binding x:DataType="Slider"
Source="{x:Reference slider}"
Path="Value" />
</Label.Scale>
</Label>
Expand All @@ -218,7 +221,8 @@ In this example, the `Source` and `Path` properties are regular XAML attributes.
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.Scale>
<Binding Path="Value">
<Binding x:DataType="Slider"
Path="Value">
<Binding.Source>
<x:Reference Name="slider" />
</Binding.Source>
Expand Down Expand Up @@ -249,7 +253,8 @@ The following XAML example demonstrates binding context inheritance:
x:Class="DataBindingDemos.BindingContextInheritancePage"
Title="BindingContext Inheritance">
<StackLayout Padding="10">
<StackLayout VerticalOptions="Fill"
<StackLayout x:DataType="Slider"
VerticalOptions="Fill"
BindingContext="{x:Reference slider}">

<Label Text="TEXT"
Expand Down
4 changes: 2 additions & 2 deletions docs/fundamentals/data-binding/binding-fallbacks.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Binding fallbacks"
description: ".NET MAUI data bindings can be made more robust by defining fallback values that will be used if binding fails."
ms.date: 10/04/2024
ms.date: 02/27/2025
---

# Binding fallbacks
Expand Down Expand Up @@ -55,7 +55,7 @@ The following example demonstrates setting the <xref:Microsoft.Maui.Controls.Bin
<ListView ItemsSource="{Binding Monkeys}"
...>
<ListView.ItemTemplate>
<DataTemplate>
<DataTemplate x:DataType="local:Monkey">
<ViewCell>
<Grid>
...
Expand Down
12 changes: 8 additions & 4 deletions docs/fundamentals/data-binding/binding-mode.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Binding mode"
description: "In .NET MAUI, every bindable property has a default binding mode, which indicates the binding mode in effect when that property is a data-binding target. The binding mode controls the flow of information between source and target, and is specified with a member of the BindingMode enumeration. "
ms.date: 01/19/2022
ms.date: 02/27/2025
---

# Binding mode
Expand All @@ -24,6 +24,7 @@ The following example shows a data binding defined on a <xref:Microsoft.Maui.Con
HorizontalOptions="Center"
VerticalOptions="Center" />
<Slider x:Name="slider"
x:DataType="Label"
VerticalOptions="Center"
Value="{Binding Source={x:Reference label},
Path=Opacity}" />
Expand Down Expand Up @@ -188,7 +189,8 @@ The following XAML consumes the `HslColorViewModel`:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.SimpleColorSelectorPage">
x:Class="DataBindingDemos.SimpleColorSelectorPage"
x:DataType="local:HslColorViewModel">
<ContentPage.BindingContext>
<local:HslColorViewModel Color="MediumTurquoise" />
</ContentPage.BindingContext>
Expand Down Expand Up @@ -237,7 +239,8 @@ However, setting the `Mode` property doesn't always produce the expected result.
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="{Binding Source={x:Reference slider},
Scale="{Binding x:DataType='Slider',
Source={x:Reference slider},
Path=Value,
Mode=TwoWay}" />
```
Expand All @@ -251,7 +254,8 @@ Alternatively, you can set the binding mode to `OneWayToSource`:
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="{Binding Source={x:Reference slider},
Scale="{Binding x:DataType='Slider',
Source={x:Reference slider},
Path=Value,
Mode=OneWayToSource}" />
```
Expand Down
44 changes: 27 additions & 17 deletions docs/fundamentals/data-binding/binding-path.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Binding path"
description: ".NET MAUI data bindings can be used to access sub-properties and collection members with the Path property of the Binding class."
ms.date: 01/19/2022
ms.date: 02/27/2025
---

# Binding path
Expand All @@ -19,7 +19,8 @@ For example, suppose a page contains a <xref:Microsoft.Maui.Controls.TimePicker>
The `Time` property of <xref:Microsoft.Maui.Controls.TimePicker> is of type `TimeSpan`, and it has a `TotalSeconds` property. A data binding can be created that references the `TotalSeconds` property of that `TimeSpan` value:

```xaml
{Binding Source={x:Reference timePicker},
{Binding x:DataType='TimePicker',
Source={x:Reference timePicker},
Path=Time.TotalSeconds}
```

Expand Down Expand Up @@ -47,18 +48,22 @@ The following XAML shows multiple examples of binding to sub-properties:

<StackLayout Margin="10, 0">
<TimePicker x:Name="timePicker" />
<Label Text="{Binding Source={x:Reference timePicker},
<Label Text="{Binding x:DataType='TimePicker',
Source={x:Reference timePicker},
Path=Time.TotalSeconds,
StringFormat='{0} total seconds'}" />
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children.Count,
<Label Text="{Binding x:DataType='StackLayout',
Source={x:Reference page},
Path=Children.Count,
StringFormat='There are {0} children in this StackLayout'}" />
<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
<Label Text="{Binding x:DataType='globe:CultureInfo',
Source={x:Static globe:CultureInfo.CurrentCulture},
Path=DateTimeFormat.DayNames[3],
StringFormat='The middle day of the week is {0}'}" />
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
<Binding x:DataType="globe:CultureInfo"
Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
Expand All @@ -70,8 +75,9 @@ The following XAML shows multiple examples of binding to sub-properties:
</Binding>
</Label.Text>
</Label>
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children[1].Text.Length,
<Label Text="{Binding x:DataType='Label',
Source={x:Reference label},
Path=Text.Length,
StringFormat='The second Label has {0} characters'}" />
</StackLayout>
</ContentPage>
Expand All @@ -84,7 +90,8 @@ In the second <xref:Microsoft.Maui.Controls.Label>, the binding source is the pa
In the example above, the binding in the third <xref:Microsoft.Maui.Controls.Label> references the [`CultureInfo`](xref:System.Globalization.CultureInfo) class in the `System.Globalization` namespace:

```xaml
<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
<Label Text="{Binding x:DataType='globe:CultureInfo',
Source={x:Static globe:CultureInfo.CurrentCulture},
Path=DateTimeFormat.DayNames[3],
StringFormat='The middle day of the week is {0}'}" />
```
Expand All @@ -96,7 +103,8 @@ The fourth <xref:Microsoft.Maui.Controls.Label> does something similar but for t
```xaml
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
<Binding x:DataType="globe:CultureInfo",
Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
Expand All @@ -112,15 +120,16 @@ The fourth <xref:Microsoft.Maui.Controls.Label> does something similar but for t

For more information about specifying constructor arguments in XAML, see [Pass constructor arguments](~/xaml/pass-arguments.md#pass-constructor-arguments).

The last <xref:Microsoft.Maui.Controls.Label> is similar to the second, except that it references one of the children of the <xref:Microsoft.Maui.Controls.StackLayout>:
The last <xref:Microsoft.Maui.Controls.Label> references the second <xref:Microsoft.Maui.Controls.Label> on the page:

```xaml
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children[1].Text.Length,
StringFormat='The first Label has {0} characters'}" />
<Label Text="{Binding x:DataType='Label',
Source={x:Reference label},
Path=Text.Length,
StringFormat='The second Label has {0} characters'}" />
```

That child is a <xref:Microsoft.Maui.Controls.Label>, which has a `Text` property of type `String`, which has a `Length` property. The first <xref:Microsoft.Maui.Controls.Label> reports the `TimeSpan` set in the <xref:Microsoft.Maui.Controls.TimePicker>, so when that text changes, the final <xref:Microsoft.Maui.Controls.Label> changes as well:
<xref:Microsoft.Maui.Controls.Label> has a `Text` property of type `String`, which has a `Length` property. The second <xref:Microsoft.Maui.Controls.Label> reports the `TimeSpan` set in the <xref:Microsoft.Maui.Controls.TimePicker>, so when that text changes, the final <xref:Microsoft.Maui.Controls.Label> changes as well:

:::image type="content" source="media/binding-path/pathvariations.png" alt-text="Path variations.":::

Expand All @@ -136,7 +145,8 @@ Complex path definitions can be difficult to construct. You need to know the typ
That displays the type of the binding source, or `DataBindingDemos.PathVariationsPage`. You know `PathVariationsPage` derives from <xref:Microsoft.Maui.Controls.ContentPage>, so it has a `Content` property:

```xaml
<Label Text="{Binding Source={x:Reference page},
<Label Text="{Binding x:DataType='ContentPage',
Source={x:Reference page},
Path=Content,
StringFormat='{0}'}" />
```
Expand Down
Loading

0 comments on commit 7efc00f

Please sign in to comment.