WPF的Binding机制给程序的开发带来极大方便,但有时源数据和绑定对象之间需要进行一定的逻辑转换,直接的简单绑定不能满足使用要求,WPF当然考虑了这一点,在Binding中我们可以添加自定义的转换逻辑,即转换器Converter。WPF中的转换器是一个非常好的数据类型转换解决方案,实用和强大, 它的作用是将源数据转换为WPF自身需要的类型,对数据实体没有侵略性,会在项目工程中频繁使用。所以掌握转换器是WPF开发的必备技能。
比如DateTime类型的时间转换为yyyyMMdd的日期,还比如要将0,1转换成男,女,这种情况下,就需要定制自己的Converter。
.Net Framework提供了两种Converter接口,单值转换的接口IValueConverter和多值转换的接口IMultiValueConverter,它们都属于System.Windows.Data命名空间,在程序集PresentationFramework.dll中。这两种值转换器都是分区域性的。其中方法Convert和ConvertBack都具有指示区域性信息的culture参数。如果区域性信息与转换无关,那么在自定义转换器中可以忽略该参数。下面来看下具体操作
一、单值转换器IValueConverter
1、在项目中control文件夹创建一个窗口文件ConverterWin.xaml,并在启动文件app.xaml修改启动文件为ConverterWin.xaml
2、在项目的common文件夹中添加一个类TimeConverter,意为时间转换器类,代码是:
3、在ConverterWin.xaml文件里添加控件,并导入命名空间,设置资源,具体代码是:
<Window x:Class="WpfApp6.control.ConverterWin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:local="clr-namespace:WpfApp6.control"
xmlns:utils="clr-namespace:WpfApp6.common"
mc:Ignorable="d"
Title="ConverterWin" Height="450" Width="800">
<!--定义窗口资源,utils是定义的命名空间别名,TimeConverter是common文件夹中的类TimeConverter,key是取个键名-->
<Window.Resources>
<utils:TimeConverter x:Key="cvtDate"/>
</Window.Resources>
<Grid>
<DatePicker x:Name="dateOne" HorizontalAlignment="Left" Margin="85,50,0,0" VerticalAlignment="Top" Width="183" SelectedDateFormat="Long"/>
<!--textbox控件的text属性绑定了日期控件,并使用前面定义的转换器cvtDate-->
<TextBox x:Name="textBox" Text="{Binding ElementName=dateOne,Path=SelectedDate,Converter={StaticResource cvtDate}}" HorizontalAlignment="Left"
Height="23" Margin="85,105,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="183"/>
<Label x:Name="label" Content="选择结果:" HorizontalAlignment="Left" Margin="19,105,0,0" VerticalAlignment="Top"/>
<Label x:Name="label1" Content="{Binding ElementName=dateOne,Path=Text}" HorizontalAlignment="Left" Margin="85,145,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
4、运行程序,效果是:
这个就是单值转换器,看到效果可以理解吧!
二、多值转换器IMultiValueConverter
多值转换器IMultiValueConverter意思是指可以转换多值的数据源,它需要继承IMultiValueConverter接口,接口使用和IValueConverter逻辑相同。我们要操作的例子是:当纵向流量大于横向流量时指示灯应为绿色,当纵向流量小于横向流量时指示灯应为红色,否则指示灯为黄色。
1、在common文件夹中添加类ColorConverter,代码是:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
namespace WpfApp6.common
{
public class ColorConverter : IMultiValueConverter
{
//当值从绑定源传播给绑定目标时,values是一个数组
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Length <0 )
{
return DependencyProperty.UnsetValue;//返回没有设置属性值
}
double verValue = (double)values[0];//获取数组中的第一个参数,即sliderVer控件的值
double horValue = (double)values[1];//获取sliderHor控件的值
if (verValue > horValue)
{
return new SolidColorBrush(Colors.Green);
}
else if (verValue < horValue)
{
return new SolidColorBrush(Colors.Red);
}
return new SolidColorBrush(Colors.Yellow);
}
//反向修改
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
//返回空,标记不可双向转换
return null;
}
}
}
2、在ConverterWin.xaml文件中添加标签控件2个,滑动控件2个,圆控件1个,完整代码是:
<Window x:Class="WpfApp6.control.ConverterWin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:local="clr-namespace:WpfApp6.control"
xmlns:utils="clr-namespace:WpfApp6.common"
mc:Ignorable="d"
Title="ConverterWin" Height="450" Width="800">
<!--定义窗口资源,utils是定义的命名空间别名,TimeConverter是common文件夹中的类TimeConverter,key是取个键名,ColorConverter同理-->
<Window.Resources>
<utils:TimeConverter x:Key="cvtDate"/>
<utils:ColorConverter x:Key="cvtColor"/>
</Window.Resources>
<Grid>
<DatePicker x:Name="dateOne" HorizontalAlignment="Left" Margin="85,50,0,0" VerticalAlignment="Top" Width="183" SelectedDateFormat="Long"/>
<!--textbox控件的text属性绑定了日期控件,并使用前面定义的转换器cvtDate-->
<TextBox x:Name="textBox" Text="{Binding ElementName=dateOne,Path=SelectedDate,Converter={StaticResource cvtDate}}" HorizontalAlignment="Left"
Height="23" Margin="85,105,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="183"/>
<Label x:Name="label" Content="选择结果:" HorizontalAlignment="Left" Margin="19,105,0,0" VerticalAlignment="Top"/>
<Label x:Name="label1" Content="{Binding ElementName=dateOne,Path=Text}" HorizontalAlignment="Left" Margin="85,145,0,0" VerticalAlignment="Top"/>
<!--多值转换器-->
<Label Content="纵向值" HorizontalAlignment="Left" Margin="363,50,0,0" VerticalAlignment="Top"/>
<Slider x:Name="sliderVer" HorizontalAlignment="Left" Margin="473,50,0,0" VerticalAlignment="Top" Height="25" Width="278"/>
<Label Content="横向值" HorizontalAlignment="Left" Margin="363,105,0,0" VerticalAlignment="Top"/>
<Slider x:Name="sliderHor" HorizontalAlignment="Left" Margin="473,105,0,0" VerticalAlignment="Top" Height="25" Width="278"/>
<Ellipse HorizontalAlignment="Left" Height="100" Margin="554,145,0,0" Stroke="Black" VerticalAlignment="Top" Width="100">
<Ellipse.Fill>
<MultiBinding Converter="{StaticResource cvtColor}">
<!--第一个绑定关联sliderVer控件的value-->
<Binding ElementName="sliderVer" Path="Value"/>
<!--第二个绑定关联sliderHor控件的value-->
<Binding ElementName="sliderHor" Path="Value"/>
</MultiBinding>
</Ellipse.Fill>
</Ellipse>
</Grid>
</Window>
3、运行程序:
拖动纵向值,这时纵向值比横向值大,所以填充绿色,
拖动横向值滑动条,当超过纵向值时,填充的是红色,效果是
这就是多值转换器里的代码进行判断生效的。
转换器作用:可以将源数据和目标数据之间进行特定的转化
还是蛮帅的,变变声。