【avalonia教程】12自定义Converter
最后,我们再说下如何自定义一个Converter。我们分单值转化器和多值转化器来讲。
先来说单值,就是只绑定一个值(这个值可以是数据上下文对象的一个属性,也可以是其他控件的属性值,后者我们后续会详细讲解)。
我们还是举个例子:我们想新建一个Converter,传参是int类型,如果传参大于10,返回true;传参小于10,返回false。
首先,新建一个Converter类,实现IValueConverter,代码如下:
public class IntBoolConverter : IValueConverter
{// 初始化一个实例对象,便于axaml中使用public static IntBoolConverter IntToBoolConverter = new();// 将MainWindowViewModel中的int值转换成Button控件IsEnabled属性的boolpublic object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture){if (value is int valueInt && valueInt > 10){return true;}return false;}// 将Button控件IsEnabled属性的bool转换成MainWindowViewModel中的int// 这里我们不需要,直接让其抛出异常即可public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture){throw new NotImplementedException();}
}
在MainWindowViewModel中定义一个Count变量,让其后续与Button的IsEnabled属性绑定
public class MainWindowViewModel
{public int? Count { get; set; } = 20;
}
在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"><Button IsEnabled="{Binding Count,Converter={x:Static converter:IntBoolConverter.IntToBoolConverter}}">test</Button>
</Window>
首先使用xmlns:converter=“using:avalonia_study.Converters”,定义一个命名空间,让这个axaml文件可以引用。然后再在Converter中使用如上代码引入IntBoolConverter类中的静态变量IntToBoolConverter。运行后即可看到效果。
这么写可以实现功能,但是稍微有点麻烦,我们参考官方提供的ObjectConverters.IsNull
的写法,可以使用现成的FuncValueConverter去定义,修改一下:
public class IntBoolConverter
{public static FuncValueConverter<int?, bool> IntToBoolConverter = new FuncValueConverter<int?, bool>(x => x > 10);
}
再来说多值,就是绑定多个值。接下来我们涉及这么一个功能:在MainWindowViewModel中定义两个int类型的参数,让Button的IsEnabled属性绑定这两个int类型,并做如下逻辑:有且仅当这两个int类型的参数值大于10时,IsEnabled属性为true,其他时候为false。
MainWindowViewModel代码如下:
public class MainWindowViewModel
{public int? Para1 { get; set; } = 5;public int? Para2 { get; set; } = 50;
}
接下来我们自定义一个Converter,取名IntAndIntToBoolConverter,让其实现一个IMultiValueConverter接口,代码如下:
public class IntAndIntToBoolConverter : IMultiValueConverter
{// 定义一个可通过类名访问的静态实例public static IntAndIntToBoolConverter Instance = new IntAndIntToBoolConverter();public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture){// 判断参数个数if (values.Count != 2){return false;}// 判断转化值是否为boolif (targetType != typeof(bool)){return false;}foreach (object value in values){// 参数是否为int类型if (value is not int){return false;}if ((int)value < 10){return false;}}return true;}
}
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"><Button Content="test"><Button.IsEnabled><MultiBinding Converter="{x:Static converter:IntAndIntToBoolConverter.Instance}"><Binding Path="Para1"></Binding><Binding Path="Para2"></Binding></MultiBinding></Button.IsEnabled></Button>
</Window>
同样的,我们再参考官方的多值转化器BoolConverters.And
,简化一下上述代码,新代码如下:
public class IntAndIntToBoolConverter
{public static readonly IMultiValueConverter Instance =new FuncMultiValueConverter<int, bool>(x => x.All(y => y > 10));}