学习笔记:
1.
使用{Binding}
标记拓展在XAML中进行绑定。通过绑定,所有数据上下文的变化都将自动更新到控件上。
<TextBlock Text="{Binding Name}"/>
2. 绑定模式
可以通过指定{Binding}
的Mode
来修改绑定的行为:
|
源的变化自动传播到目标 |
|
源和目标的变化互相传播 |
|
源的初始值会应用到目标,但后续的变化会被无视 |
|
目标的变化自动传播到源 |
|
依据属性而定 |
3.绑定变化通知
private int _selectedParityIndex;
public int SelectParityIndex
{
get => _selectedParityIndex;
set => this.RaiseAndSetIfChanged(ref _selectedParityIndex, value);
}
4。与控件绑定
<TextBox Name="tb1">
<!-- 绑定到命名为“tb1”控件的Text属性 -->
<TextBlock Text="{Binding #tb1.Text}"/>
5. 绑定到父级
<Border Tag="Hello Avalonia!">
<TextBlock Text="{Binding $parent.Tag}"/>
</Border>
<!-- 绑定到祖先级 -->
<Border Tag="Hello Avalonia!">
<Border>
<TextBlock Text="{Binding $parent[1].Tag}"/>
</Border>
</Border>
<!-- 按类型绑定到祖先 -->
<Border Tag="Hello Avalonia!">
<Decorator>
<TextBlock Text="{Binding $parent[Border].Tag}"/>
</Decorator>
</Border>
6. 绑定到转换器
<Window.Resources>
<local:MyConverter x:Key="converter1"/>
</Window.Resources>
<TextBlock Text="{Binding Value, Converter={StaticResource converter1}}"/>
内置转换器
转换器 | 描述 |
---|---|
|
如果输入的字符串为null或empty,则返回 |
|
如果输入的字符串不为null或empty,则返回 |
|
如果输入为null,则返回 |
|
如果输入为null,则返回 |
|
一种多值转换器,如果所有输入均为true,则返回 |
|
一种多值转换器,如果其中任意输入为true,则返回 |
可以作为管道使用,也可以作为控制控件的现实和隐藏。
<!-- 控制是否隐藏 -->
<TextBlock Text="{Binding MyText}"
IsVisible="{Binding MyText, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<!-- 转换大小写 -->
<TextBlock Text="{Binding TheContent,
Converter={StaticResource textCaseConverter},
ConverterParameter=lower}" />
7. 绑定到命令
<Button Command="{Binding DoTheThing}">Do the thing!</Button>
public ReactiveCommand<Unit, Unit> DoTheThing { get; }
public MainWindowViewModel()
{
DoTheThing = ReactiveCommand.Create(RunTheThing);
}
void RunTheThing()
{
// 此处执行命令的代码。
}
8. 绑定到方法
public void RunTheThing(string parameter)
{
// 此处执行命令的代码。
}
可用CommandParameter传递参数。
如果需要从viewmodel里面触发CanExcute,则必须用一个或多个DependsOn属性来修饰它。
[DependsOn(nameof(IsTheThingEnabled))]
bool CanRunTheThing(/* CommandParameter */object parameter)
{
return IsTheThingEnabled && parameter != null;
}
9.绑定到任务
public Task<string> MyAsyncText => GetTextAsync();
private async Task<string> GetTextAsync()
{
await Task.Delay(1000);
return "Hello from async operation";
}
<TextBlock Text="{Binding MyAsyncText^, FallbackValue='Wait a second'}" />
10.订阅属性的更改
var textBlock = new TextBlock();
var text = textBlock.GetObservable(TextBlock.TextProperty);
text.Subscribe(value => Console.WriteLine(value + " Changed"));
11.绑定到可观察对象
// 我们在这里使用Rx Subject,以便我们可以使用OnNext推送新值
var source = new Subject<string>();
var textBlock = new TextBlock();
// 将TextBlock.Text绑定到源
var subscription = textBlock.Bind(TextBlock.TextProperty, source);
// 将textBlock.Text设置为“hello”
source.OnNext("hello");
// 将textBlock.Text设置为“world!”
source.OnNext("world!");
// 终止绑定
subscription.Dispose();
12.控件模板中绑定
<TextBlock Name="tb" Text="{TemplateBinding Caption}"/>
<!-- 也能写成这样 -->
<TextBlock Name="tb" Text="{Binding Caption, RelativeSource={RelativeSource TemplatedParent}}"/>
TemplateBinding
只接受单个属性而不是属性路径,因此如果要使用属性路径进行绑定,则必须使用第二种语法:
<!-- 这不起作用,因为TemplateBinding只接受单个属性 -->
<TextBlock Name="tb" Text="{TemplateBinding Caption.Length}"/>
<!-- 在这种情况下,必须使用此语法 -->
<TextBlock Name="tb" Text="{Binding Caption.Length, RelativeSource={RelativeSource TemplatedParent}}"/>
TemplateBinding
仅支持单向绑定(OneWay
) 、只能用于IStyledElement
<!-- 这不起作用,因为GeometryDrawing不是IStyledElement -->
<GeometryDrawing Brush="{TemplateBinding Foreground}"/>
<!-- 在这种情况下,必须使用此语法 -->
<GeometryDrawing Brush="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"/>