【avalonia教程】13绑定控件
上面有部分讲漏了,关于Convert方法中的parameter和culture,这里补一下。
parameter是指转化的时候,可以带一个参数过来,在axaml的MultiBinding节点中使用ConverterParameter
关键字,代码如下:
<Button Content="111"><Button.IsEnabled><MultiBinding Converter="{x:Static converters:IntToBoolConverter.Instance}" ConverterParameter="test"><Binding Path="Para1"></Binding><Binding Path="Para2"></Binding></MultiBinding></Button.IsEnabled></Button>
上面相当于传了一个test字符串过去,相当于parameter参数就为test。如果我们想传一个更复杂的对象过去,可以这么写:
<Button.IsEnabled><MultiBinding Converter="{x:Static converters:IntToBoolConverter.Instance}"><MultiBinding.ConverterParameter><vm:StackPanelDataContext></vm:StackPanelDataContext></MultiBinding.ConverterParameter><Binding Path="Para1"></Binding><Binding Path="Para2"></Binding></MultiBinding></Button.IsEnabled>
关于culture,可以用来根据不同的区域性显示相应的格式、或者处理依赖于区域设置的数据类型转换,这里就先举个简单的例子,大家感受下就可以了
public class PriceConverter : IMultiValueConverter
{public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture){if (values.Count > 0 && values[0] is decimal price){// 根据不同的区域性显示不同的货币格式if (culture.Name == "zh-CN"){return "中文";}}return "其他";}
}
还有一个遗漏点也补充一下,是关于DataContext绑定的。我们在axaml中定义如下代码:
<Window xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="100"x:Class="avalonia_study.MainWindow"xmlns:vm="using:avalonia_study.ViewModels"x:DataType="vm:MainWindowViewModel"xmlns:converter="using:avalonia_study.Converters"Title="avalonia_study"><StackPanel x:DataType="vm:StackPanelViewModel"><TextBlock Text="{Binding PageDesc}"></TextBlock></StackPanel></Window>
可以看到TextBlock的Text属性绑定了StackPanel的DataContext的PageDesc,但是呢运行时又没有给StackPanel的DataContext赋值,所以呢运行起来,会发现展示内容为空,原因是开启了编译绑定,在编译的时候,强制指定了TextBlock的Text属性为StackPanel的DataContext的PageDesc属性。如果发现StackPanel没有DataContext属性,则显示为空。
但是,如果将Binding改为ReflectionBinding
,代码如下:
<Window xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="100"x:Class="avalonia_study.MainWindow"xmlns:vm="using:avalonia_study.ViewModels"x:DataType="vm:MainWindowViewModel"xmlns:converter="using:avalonia_study.Converters"Title="avalonia_study"><StackPanel x:DataType="vm:StackPanelViewModel"><TextBlock Text="{ReflectionBinding PageDesc}"></TextBlock></StackPanel></Window>
你会发现有值了!且值是MainWIndowViewModel的PageDesc属性,原因是ReflectionBinding是运行时绑定,代码运行起来后,TextBlock的Text属性会先找自己有没有DataContext呀?没有,那上一级的StackPanel有没有DataContext呀?也没有,那Window有吗?诶!有,那就用你了!
如何实现绑定到控件
之前我们提过,可以把控件的属性绑定父控件DataContext的属性上,代码如下:
<StackPanel Name="TestStackPanel"><TextBlock Text="{Binding $parent.((vm:StackPanelViewModel)DataContext).PageDesc}"></TextBlock></StackPanel>
也可以把控件的属性绑定其他控件的DataContext属性上,代码如下:
<StackPanel Name="TestStackPanel"><TextBlock Name="TestBlockDemo"></TextBlock><TextBlock Text="{Binding #TestBlockDemo.((vm:StackPanelViewModel)DataContext).PageDesc}"></TextBlock></StackPanel>
其实除了DataContext,也可以绑定到另一个控件的其他属性上,代码如下:
<StackPanel><TextBlock Text="{Binding #DemoBox.Text}"></TextBlock><TextBox Name="DemoBox"></TextBox></StackPanel>
可以发现当我们在输入框中输入内容时,上方的文本内容也跟着改变。
在这里我们补一个之前讲漏的东西,如何在代码侧,去查看一个属性的绑定方式Mode?我们以TextBlock的Text属性举例,点进属性看会发现如下代码:
public string? Text{get => GetValue(TextProperty);set => SetValue(TextProperty, value);}
点进TextProperty属性看看,代码如下:
public static readonly StyledProperty<string?> TextProperty =AvaloniaProperty.Register<TextBlock, string?>(nameof(Text));
我们点进Register方法进去,可以看到如下代码:
public static StyledProperty<TValue> Register<TOwner, TValue>(string name,TValue defaultValue = default!,bool inherits = false,BindingMode defaultBindingMode = BindingMode.OneWay,...
即可确定
接下来我们说绑定到父组件,其实我们之前讲DataContext的时候有讲到过,这里我们再回顾并拓展下,先来看个基础的用法:
<Button Width="300"><TextBlock Text="{Binding $parent.Width}"></TextBlock></Button>
那如果要找父组件的父组件呢?
<Button Height="60"><Button Width="300"><TextBlock Text="{Binding $parent[1].Height}"></TextBlock></Button></Button>
父组件的父组件的父组件就是$parent[2],以此类推。
也可以通过指定控件类型,来找到最近的父组件,代码如下:
<Button Height="60"><Button Width="300"><TextBlock Text="{Binding $parent[Button].Width}"></TextBlock></Button></Button>
那如果我想找到离我第二近的父组件呢?可以这么写:
<Button Height="60"><Button Width="300"><TextBlock Text="{Binding $parent[Button;1].Height}"></TextBlock></Button></Button>
第三近的就是$parent[Button;2],以此推类