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

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

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

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

时间: 2024-10-14 02:25:47

WPF之Binding对数据的转换(第五天)的相关文章

WPF Data Binding之数据的转换和校验【四】

Binding的作用就是架在Source和Target之间的桥梁,数据可以在这座桥梁的帮助下来流通.就像现实社会中桥梁需要设置安检和关卡一样,Binding这座桥上也可以设置关卡对数据进行验证,不仅如此,如果Binding两端需要不同的数据类型的时候我们还可以为数据设置转换器. Binding用于数据有效性校验的关卡是他的ValidationRules属性,用于数据类型转换的关卡是它的Convert属性. 1.1 Binding的数据校验 Binding的ValidationRules属性是Co

【转载一篇WPF之Binding】WPF之Binding深入探讨

1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的程序来说,算法一般分布在这几处: A.数据库内部. B.读取和写回数据. C.业务逻辑. D.数据展示. E.界面与逻辑的交互. A,B两部分的算法一般都非常稳定,不会轻易去改动,复用性也很高:C处与客户需求最紧密,最复杂,变化最大,大多少算法都集中在这里.D,E负责UI和逻辑的交互,也占有一定量的

WPF之Binding深入探讨

1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都非常重要.但算法在3层中的分布是不均匀的,对于一个3层结构的程序来说,算法一般分布在这几处: A.数据库内部. B.读取和写回数据. C.业务逻辑. D.数据展示. E.界面与逻辑的交互. A,B两部分的算法一般都非常稳定,不会轻易去修改,复用性也非常高:C处与客户需求最紧密,最复杂,变化最大,大多少算法都集中在这里.D,E负责UI和逻辑的交互,也占有一定

WPF之Binding【转】

WPF之Binding[转] 看到WPF如此之炫,也想用用,可是一点也不会呀. 从需求谈起吧: 首先可能要做一个很炫的界面.见MaterialDesignInXAMLToolKit. 那,最主要的呢,还是想显示数据. 就先来数据,数据可以从数据库里得到,可是如何显示出来呢? 本文的主角出来了:(以下内容全转载他人,具体 原文见上面的链接) ==================================== 1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.

[转]深入浅出WPF(7)——数据的绿色通道,Binding

本文转自:http://liutiemeng.blog.51cto.com/120361/95273 小序: 怎么直接从2蹦到7啦?!啊哦,实在是不好意思,最近实在是太忙了,忙的原因也非常简单——自己的技术太差了,还有很多东西要学呀.门里门外,发现专业程序员非常重要的一项技能是读别人写的代码,这项技能甚至比自己写代码更重要.Anstinus同学就是读代码的高手,我写的代码他看两眼就知道怎么回事了,并且能够立刻修改,而他的代码我读了好几天还不知道是怎么回事儿呢. 2到7之间是留给XAML语言基础的

WPF Data Binding之地位与基础【一】

[1]Data Binding在WPF中的地位 从传统的Winform转移到WPF上,对于一个三层程序而言,数据存储层由数据库和文件系统组成,数据传输和处理仍然使用.NetFramework的ADO.NET等基本类(与Winform开发一样).展示层则使用WPF类库来实现,而展示层和逻辑层的沟通就使用Data Binding来实现.可见,Data Binding在WPF中所起的作用就是高速公路的作用.有了这条高速公路,加工好的数据自动送达用户界面并加以显示,被用户修改过的数据也会自动传回业务逻辑

WPF自学入门(七)WPF 初识Binding

今天记录一下Binding的基础和具体的使用方法,说起这个Binding,在WPF中,Binding是很重要的特征,在传统的Windows软件来看,大多数都是UI驱动程序的模式,也可以说事件驱动程序,这个程序模式在工作过几年的程序员中是根深蒂固的,WPF作为Winform的升级,它把UI驱动程序彻底改变了,核心回到了数据驱动程序的模式上面,这样,程序就回到了算法和数据.数据,才是真正需要重点处理的! Binding在数据驱动程序模式中起着至关重要的作用,它最为重要的一个特点就是通讯,连接着前台与

WPF之Binding

Bingding是什么 WPF中的Binding注重表达的是一种像桥梁一样的关系,它的两段分别是Binding的源(Source)和目标(Target).数据从哪里来哪里就是源,Binding是架在中间的桥梁,Binding的目标是数据要往哪去儿.一般情况下,Binding源是逻辑层的对象,Binging的目标是UI层的控件对象. Binding如何传递数据变化 前面说过数据源是一个对象,但一个对象身上可能有很多数据,这些数据又通过属性暴露给外界.其中你想通过Binding送达UI元素的数据,或

【python cookbook】【数据结构与算法】19.同时对数据做转换和换算

问题:我们需要调用一个换算函数(例如sum().min().max()),但是首先需对数据做转换或者筛选处理 解决方案:非常优雅的方法---在函数参数中使用生成器表达式 例如: # 计算平方和 nums=[1,2,3,4,5] s1=sum((x*x for x in nums)) s2=sum(x*x for x in nums) #更优雅的用法 s3=sum([x*x for x in nums]) #不使用生成器表达式 print(s1) print(s2) print(s3) # 判断一