• 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》读书笔记

  • 相关阅读:
    Linux多cuda版本切换
    国庆节换头像热潮:国旗渐变微信头像和微信头像加上国旗!制作教程来了,你会了吗???
    《手把手教你》系列技巧篇(二十八)-java+ selenium自动化测试-处理模态对话框弹窗(详解教程)
    《手把手教你》系列技巧篇(二十七)-java+ selenium自动化测试- quit和close的区别(详解教程)
    《手把手教你》系列技巧篇(二十六)-java+ selenium自动化测试-浏览器操作(详细教程)
    《手把手教你》系列技巧篇(二十五)-java+ selenium自动化测试-FluentWait(详细教程)
    《手把手教你》系列技巧篇(二十四)-java+ selenium自动化测试-三大延时等待(详细教程)
    《手把手教你》系列技巧篇(二十三)-java+ selenium自动化测试-webdriver处理浏览器多窗口切换下卷(详细教程)
    《手把手教你》系列技巧篇(二十二)-java+ selenium自动化测试-webdriver处理浏览器多窗口切换上卷(详细教程)
    《将博客搬至CSDN》
  • 原文地址:https://www.cnblogs.com/laoqi/p/3835688.html
Copyright © 2020-2023  润新知