原文:
数据绑定(十)Binding的数据转换
Plane类型的Category将在界面上转换为图片,而State类型将会转换成界面上的CheckBox显示,由于存在两个转换,因此需要提供两个Converter,第一个转换是做Category类型与字符类型的转换,字符串是图片的路径
由于UI上不能修改图片,所以只实现了从Source到Target的转换
界面代码:
加粗的部分是XAML中对转换器的使用,后台代码中实现了Load和Save两个按钮的点击事件
当Source端Path所关联的数据与Target端目标属性数据类型不一致时,需要添加数据转换器,数据转换器是一个自定义的类,这个类需要实现IValueConverter接口,这个接口有两个方法需要实现:Convert和ConvertBack,当数据从Source流向Target时,将调用Convert方法,反之,将调用ConvertBack方法
例子,首先定义飞机类型
public enum Category { Bomber, Fighter } public enum State { Available, Locked, Unknown } public class Plane { public Category Category { get; set; } public string Name { get; set; } public State State { get; set; } }
Plane类型的Category将在界面上转换为图片,而State类型将会转换成界面上的CheckBox显示,由于存在两个转换,因此需要提供两个Converter,第一个转换是做Category类型与字符类型的转换,字符串是图片的路径
class CategoryToSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { Category c = (Category)value; switch (c) { case Category.Bomber: { return @"\Icons\close.png"; } case Category.Fighter: { return @"\Icons\closeing.png"; } default: { return null; } } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return new NotImplementedException(); } }
由于UI上不能修改图片,所以只实现了从Source到Target的转换
另一个转换用于将State数据转换为bool?
public class StateToNullableBoolConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { State s = (State)value; switch (s) { case State.Locked: { return false; } case State.Available: { return true; } case State.Unknown: default: { return null; } } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { bool? nb = (bool?)value; switch (nb) { case true: { return State.Available; } case false: { return State.Locked; } case null: default: { return State.Unknown; } } } }
界面代码:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" Title="MainWindow" Height="275" Width="275"> <Window.Resources> <local:CategoryToSourceConverter x:Key="cts" /> <local:StateToNullableBoolConverter x:Key="stnb" /> </Window.Resources> <StackPanel Background="LightBlue"> <ListBox x:Name="listBoxPlane" Height="160" Margin="5"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Width="20" Height="20" Source="{Binding Path=Category, Converter={StaticResource cts}}" /> <TextBlock Text="{Binding Path=Name}" Width="60" Margin="80,0" /> <CheckBox IsThreeState="True" IsChecked="{Binding Path=State, Converter={StaticResource stnb}}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Button x:Name="buttonLoad" Content="Load" Height="25" Margin="5,0" Click="buttonLoad_Click" /> <Button x:Name="buttonSave" Content="Save" Height="25" Margin="5,0" Click="buttonSave_Click" /> </StackPanel> </Window>
加粗的部分是XAML中对转换器的使用,后台代码中实现了Load和Save两个按钮的点击事件
private void buttonLoad_Click(object sender, RoutedEventArgs e) { List<Plane> planeList = new List<Plane>() { new Plane(){Category=Category.Bomber, Name="B-1", State=State.Unknown}, new Plane(){Category=Category.Bomber, Name="B-2", State=State.Unknown}, new Plane(){Category=Category.Fighter, Name="F-22", State=State.Unknown}, new Plane(){Category=Category.Fighter, Name="Su-47", State=State.Unknown}, new Plane(){Category=Category.Bomber, Name="B-52", State=State.Unknown}, new Plane(){Category=Category.Fighter, Name="J-10", State=State.Unknown} }; listBoxPlane.ItemsSource = planeList; } private void buttonSave_Click(object sender, RoutedEventArgs e) { StringBuilder sb = new StringBuilder(); foreach (Plane p in listBoxPlane.Items) { sb.AppendLine(string.Format("Category={0}, Name={1}, State={2}", p.Category, p.Name, p.State)); } File.WriteAllText(@"d:\PlaneList.txt", sb.ToString()); }
界面效果如图:
当改变checkbox的选中状态时,Plane对象中的值会发生变化