WPF之Binding对数据的转换(第五天)

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,效果图如下:

QQ截图20140710142657

单击Save按钮后打开D:\BallList.txt:

QQ截图20140710133155

注*读《深入浅出WPF》读书笔记

你可能感兴趣的:(bind)