Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: new binding updates #2185

Merged
merged 5 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions doc/Learn/Markup/Binding101.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public partial class MainPage : Page
.Content(
new TextBlock()
.Text(x => x
.Bind(() => vm.Title)
.Binding(() => vm.Title)
.Mode(BindingMode.OneTime)
)
)
Expand All @@ -68,7 +68,7 @@ public partial class MainPage : Page
.Content(
new TextBlock()
.Text(x => x
.Bind(() => vm.Title)
.Binding(() => vm.Title)
.OneTime()
)
)
Expand All @@ -88,7 +88,7 @@ public partial class MainPage : Page
.Content(
new TextBlock()
.Text(x => x
.Bind(() => vm.Query)
.Binding(() => vm.Query)
.Convert(query => $"Search: {query}")
)
)
Expand Down Expand Up @@ -125,7 +125,7 @@ public partial class MainPage : Page
.Content(
new TextBox()
.Text(x => x
.Bind(() => vm.Enabled)
.Binding(() => vm.Enabled)
.Convert(enabled => $"Enabled: {enabled}")
.ConvertBack(text => bool.TryParse(text.Replace("Search: ", ""), out var enabled) ? enabled : false)
)
Expand All @@ -137,7 +137,7 @@ public partial class MainPage : Page

## Binding to other sources

Sometimes you may want or need to bind to your ViewModel. The first case we'll take a look at is one in which we want to bind to a property of another element. In this case we will use the `ElementName` method on the `BindingFactory` to update our binding so that it will bind to a named element in the Visual Tree.
Sometimes you may want or need to bind to your ViewModel. The first case we'll take a look at is one in which we want to bind to a property of another element. In this case we will use the `Source` method to update our binding so that it will bind to a named element in the Visual Tree.

```cs
public partial class MainPage : Page
Expand All @@ -152,8 +152,8 @@ public partial class MainPage : Page
.Name("SearchBox"),
new TextBox()
.Text(x => x
.Bind(() => searchBox.Text)
.ElementName("SearchBox"))
.Source("SearchBox")
.Binding(() => searchBox.Text))
)
);
}
Expand All @@ -173,7 +173,8 @@ public partial class MainPage : Page
.Content(
new MyCustomControl()
.DataContext(x => x
.Bind(() => this.DataContext)
.Source(this)
.Binding(() => this.DataContext)
.Convert(dataContext => {
if (dataContext is MyViewModel myViewModel)
{
Expand All @@ -182,7 +183,6 @@ public partial class MainPage : Page
return null;
})
.OneTime()
.Source(this)
)
)
);
Expand All @@ -198,4 +198,4 @@ Learn more about:
- [Styles](xref:Uno.Extensions.Markup.Styles)
- [Templates](xref:Uno.Extensions.Markup.Templates)
- [VisualStateManagers](xref:Uno.Extensions.Markup.VisualStateManager)
- [Generating C# Extensions for your libraries](xref:Uno.Extensions.Markup.GeneratingExtensions)
- [Generating C# Extensions for your libraries](xref:Uno.Extensions.Markup.GeneratingExtensions)
10 changes: 5 additions & 5 deletions doc/Learn/Markup/Converters.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class Converters
}

new Button()
.Enabled(x => x.Bind(() => vm.IsBusy)
.Enabled(x => x.Binding(() => vm.IsBusy)
.Converter(Converters.InverseBoolConverter));
```

Expand All @@ -40,7 +40,7 @@ public partial class MainPage : Page
new TextBox()
.Text(() => vm.Query)
new TextBlock()
.Text(x => x.Bind(() => vm.Query)
.Text(x => x.Binding(() => vm.Query)
.Convert(query => $"Search: {query}"))
)
));
Expand All @@ -64,7 +64,7 @@ Sometimes, we may want to make conditionals or apply specific rules to values or
```csharp
new TextBox()
.Text(() => vm.Query)
.Foreground(x => x.Bind(() => vm.Query)
.Foreground(x => x.Binding(() => vm.Query)
.Convert(query => new SolidColorBrush(!string.IsNullOrEmpty(query) && query.Length > 5 ? Colors.Green : Colors.Red)));
```

Expand All @@ -84,7 +84,7 @@ And use like this:
```csharp

new Button()
.Enabled(x => x.Bind(() => vm.IsBusy)
.Enabled(x => x.Binding(() => vm.IsBusy)
.Converter(Converters.InverseBoolConverter));
```

Expand All @@ -100,7 +100,7 @@ public partial class MainPage : Page
{
this.DataContext<MyViewModel>((page, vm) => page
.Content(new TextBox()
.Text(x => x.Bind(() => vm.Enabled)
.Text(x => x.Binding(() => vm.Enabled)
.Convert(enabled => $"Enabled: {enabled}")
.ConvertBack(text => bool.TryParse(text.Replace("Search: ", ""), out var enabled) ? enabled : false))
));
Expand Down
12 changes: 7 additions & 5 deletions doc/Learn/Markup/DependencyPropertyBuilder.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The `DependencyPropertyBuilder` provides a fluent API to help you create a bindi

```cs
new TextBlock()
.Text(x => x.Bind(() => vm.Message))
.Text(x => x.Binding(() => vm.Message))
```

When creating a simplified binding such as the one above you may alternatively simply provide the binding expression like:
Expand Down Expand Up @@ -50,16 +50,18 @@ Sometimes you aren't binding to the `DataContext` of element and instead you nee
```cs
new Slider().Assign(out var slider),
new TextBlock()
.Text(x => x.Bind(() => slider.Value)
.Source(slider))
.Text(x => x
.Source(slider)
.Binding(() => slider.Value))
```

The second is that we can leverage the element name for our binding such as the following:

```cs
new TextBlock()
.Text(x => x.Bind(() => slider.Value)
.ElementName("slider")),
.Text(x => x
.Source("slider")
.Binding(() => slider.Value)),
new Slider().Name("slider")
```

Expand Down
118 changes: 118 additions & 0 deletions doc/Learn/Markup/SourceUsage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
uid: Uno.Extensions.Markup.SourceUsage
---
# Source and Relative Source

Sometimes, when working with binding expressions, specifying the source or a relative source becomes necessary. In this section, we'll explore how to do that using strongly typed sources.

## Source Binding

Binding a property directly from one UI element to another is a common scenario. Here's how you can bind the Text property of a TextBox to the Content property of a button, and vice versa:

```csharp
new StackPanel()
.Children(
new Button()
.Assign(out var button)
.Content("I am a button"),

// Creating a TextBox and binding its Text property to a Button's Content
new TextBox()
.Text(x => x.Source(button)
.Binding(() => button.Content));
)
```

```csharp
new StackPanel()
.Children(
new TextBox()
.Assign(out var textBox)
.Text("I am a TextBox"),

// Creating a Button and binding its Content property to the TextBox's Text property with TwoWay binding
new Button()
.Content(x => x.Source(textBox)
.Binding(() => textBox.Text)
.TwoWay());
)
```

```csharp
// Binding with a string identifier for the source button
new TextBox()
.Text(x => x.Source<Button>("myButton")
.Binding(b => b.Content));
```

```csharp
new StackPanel()
.Children(
new Button()
.Assign(out var button)
.Content("I am a button"),

// Binding to a property of a DataContext
new TextBox()
.Text(x => x.Source(button)
.DataContext<MockViewModel>()
.Binding(v => v.Message));
)
```

## Relative Source Binding

RelativeSource binding allows you to bind to a property of the element itself or a relative element, such as a parent. This can be useful in various scenarios, including styling and templating:

Example of using RelativeSource to bind to another property of the same element:

```csharp

var textBlock = new TextBlock()
.Tag("Uno Platform!")
// Binding an element's property to itself using RelativeSource
.Text(x => x.RelativeSource<TextBlock>(RelativeSourceMode.Self)
.Binding(t => t.Tag));

```



Example of using RelativeSource to bind a parent property to the element property:

```csharp

var button = new Button()
.Style(
new Style<Button>()
.Setters(s => s
.Template(b => new Border()
// Using RelativeSource to bind to a TemplatedParent property in a style template
.Background(x => x.RelativeSource<Button>(RelativeSourceMode.TemplatedParent)
.Binding(x => x.Background)
)
)
)
)
.Background(Colors.Blue);

```

## Binding Expression Methods

Below is a list of methods available for use within binding expressions:

| Property | Description |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `Binding()` | Sets the Binding Path |
| `DataContext<TDataContext>()` | Sets the DataContext |
| `Mode(BindingMode)` | Sets Binding Mode |
| `OneTime()` | Sets Binding Mode to OneTime |
| `OneWay()` | Sets the Binding Mode to OneWay |
| `TwoWay()` | Sets the Binding Mode to TwoWay |
| `Converter(IValueConverter)` | Sets a custom IValueConverter to convert data between the source and target during binding |
| `Convert(Func<TSource, TTarget>)` | Sets a conversion function to transform the source data to the target type during binding |
| `ConvertBack(Func<TTarget, TSource>)` | Sets a conversion function to transform the target data back to the source type during binding (TwoWay binding) |
| `FallbackValue(T)` | Sets a fallback value to be used when the source data is null or cannot be converted |
| `TargetNullValue(T)` | Sets a value to be used as the target when the source data is null |
| `UpdateSourceTrigger(UpdateSourceTrigger)`| Sets the trigger that determines when the source property is updated during TwoWay binding. |
Loading