Binding在Slider控件与TextBox控件之间建立关联,值可以互相绑定,但是它们的数据类型是不同的,Slider是Double类型,Text为String。原来,Binding有一种机制称为数据转换(Data Converter),当数据绑定的源与目标不同类型时,处理比较简单时,系统就自动的进行了类型转换,但是对于相对复杂的类型转换时,就需要我们手动进行了。
下面用一个例子来说明Convert的应用,程序的用途是在列表里面向玩家显示一些球的状态。
首先创建几个自定义数据类型:
public enum Category { Basketball, football } public enum State { Available, Locked, Unknown } public class ball { public Categroy Categroy { get;set; } public string Name { get; set; } public State State { get; set; } }
程序后面要用到的图片已经加载到程序中,球的State属性在UI里被映射为CheckBox。因为存在两个映射关系,我们需要提供两个Convert:一个是由Category类型单向转换为string,另一个State与bool?类型之间相互转换。代码如下:
public class CategoryToSourceConverter : IValueConverter { //将Category转换为Uri public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Category c = (Category)value; switch (c) { case Category.Basketball: return @"basketball.png"; case Category.football: return @"football.png"; default: return null; } } //不会被调用 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } public class StateToNullableBoolConvert : IValueConverter { //将state转换为bool? public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { State s = (State)value; switch (s) { case State.Locked: return false; case State.Available: return true; case State.Unknown: default: return null; } } //将bool?转换为State public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { bool? nb = (bool?)value; switch (nb) { case true: return State.Available; case false: return State.Locked; case null: default: return State.Unknown; } } }
下面我们看看如何在XAML里消费这些Converter。XAML代码的框架如下:
<Window x:Class="DataConverter.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataConverter" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <local:CategoryToSourceConverter x:Key="cts"/> <local:StateToNullableBoolConvert x:Key="stnb"/> </Window.Resources> <Grid> <StackPanel Background="LightBlue"> <ListBox x:Name="listBoxPlan" Height="160" Margin="5,0"></ListBox> <Button x:Name="buttonLoad" Content="Load" Height="25" Margin="5,0"></Button> <Button x:Name="buttonSave" Content="Save" Height="25" Margin="5,5"></Button> </StackPanel> </Grid> </Window>
XAML代码中已经添加了对程序集的引用并映射为名称空间local,以资源的形式创建了两个Convert的实例。名为ListBoxPlan的ListBox控件需要为它添加用于显示数据的DataTemplate。我们把焦点集中在ListBox控件的ItemTemplate属性上:
<ListBox x:Name="listBoxPlan" Height="160" Margin="5,0"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Width="20" Height="20" Source="{Binding Path=Category,Converter={StaticResource cts}}"></Image> <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>
Load按钮的Click事件处理负责把一组球的数据赋值给ListBox的ItemSource属性,Save按钮的Click事件处理器负责把用户更改过的数据写入文件:
//Load按钮Click事件处理器 private void buttonLoad_Click(object sender, RoutedEventArgs e) { List<Ball> ballList = new List<Ball>() { new Ball(){Category = Category.Basketball,Name = "NBA",State = State.Unknown}, new Ball(){Category = Category.Basketball,Name = "CBA",State = State.Unknown}, new Ball(){Category = Category.football,Name = "世界杯",State = State.Unknown}, new Ball(){Category = Category.football,Name = "欧冠",State = State.Unknown}, new Ball(){Category = Category.Basketball,Name = "WNBA",State = State.Unknown}, new Ball(){Category = Category.football,Name = "英超",State = State.Unknown} }; this.listBoxPlan.ItemsSource = ballList; } //Save按钮Click事件处理器 private void buttonSave_Click(object sender, RoutedEventArgs e) { StringBuilder sb = new StringBuilder(); foreach (Ball b in listBoxPlan.Items) { sb.AppendLine(string.Format("Category={0},Name={1},State={2}", b.Category, b.Name, b.State)); } File.WriteAllText(@"D:\BallList.txt", sb.ToString()); }
运行程序并单击CheckBox更改State,效果图如下:
单击Save按钮后打开D:\BallList.txt:
注*读《深入浅出WPF》读书笔记
WPF之Binding对数据的转换(第五天)
时间: 2024-10-14 02:25:47