WPF学习笔记:Binding的数据转换

前面我们讲解的数据绑定都是非常简单的数据类型,基本上都是int或者string,都可以很容易地显示在界面上。现在想象一个这样的场景:我们定义了一个枚举,这个枚举有2个枚举值,checked和unchecked。界面上有一个checkbox,当枚举值为checked时,复选框被选中。因为checkbox是无法识别枚举值的,所以这里需要一个数据的转换,把枚举值转换成bool值。

下面我们看一个例子:

xaml代码:

<Window x:Class="BindValidationRule.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BindValidationRule"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="800">
    <Window.Resources>
        <local:CategoryToSourceConverter x:Key="cts"/>
        <local:StateToNullableBoolConverter x:Key="stnb"/>
    </Window.Resources>
        
    <StackPanel>
        <ListBox x:Name="listBoxPlane" Height="160" Margin="5">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Width="60" Text="{Binding Path=Category, Converter={StaticResource cts}}"/>
                        <TextBlock Text="{Binding Path=Name}" Width="60"/>
                        <CheckBox IsThreeState="True" IsChecked="{Binding Path=State,Converter={StaticResource stnb}}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button x:Name="btnLoad" Content="Load" Height="30" Click="btnLoad_Click"/>
    </StackPanel>
</Window>

c#代码:

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void btnLoad_Click(object sender, RoutedEventArgs e)
        {
            List<Plane> planes = new List<Plane>()
            {
                new Plane(){Category= Category.Bomber,Name="B-1",State= State.Unknown},
                new Plane(){Category= Category.Bomber,Name="B-2",State= State.Avalible},
                new Plane(){Category= Category.Fighter,Name="B-3",State= State.Locked},
            };

            listBoxPlane.ItemsSource = planes;
        }
    }

    public enum Category
    {
        Bomber,
        Fighter
    }

    public enum State
    {
        Avalible,
        Locked,
        Unknown
    }

    public class Plane
    {
        public Category Category { get; set; }
        public State State { get; set; }
        public string Name { get; set; }
    }

    public class CategoryToSourceConverter:IValueConverter
    {
        public object Convert(object value,Type targetType,object parameter,CultureInfo cultureInfo)
        {
            Category category = (Category)value;
            switch(category)
            {
                case Category.Bomber:
                    return "A";
                case Category.Fighter:
                    return "B";
                default:
                    return null;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo)
        {
            throw new NotImplementedException();
        }
    }

    public class StateToNullableBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo)
        {
            State state = (State)value;
            switch (state)
            {
                case State.Avalible:
                    return true;
                case State.Locked:
                    return false;
                default:
                    return null;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo)
        {
            bool? nb = (bool?)value;
            switch(nb)
            {
                case true:
                    return State.Avalible;
                case false:
                    return State.Locked;
                default:
                    return State.Unknown;
            }
        }
    }

 当我们点击load按钮时,界面显示效果如下:

 我们这里给第一列的TextBlock的Text属性指定了binding,path=Category,而我们定义了Category是一个枚举。所以我们也给这个binding指定了一个Converter。这个转换器定义在Window.Resources里面。下面我们重点看一下它是如何实现转换的:

我们看CategoryToSourceConverter类,它继承自IValueConverter接口,这个接口的定义是这样的:

 它只有2个函数,Convert是把源数据转换成目标数据,ConvertBack则相反。在我们这个例子里面,源指的就是Category这个枚举,目标数据指的就是TextBlock的Text属性值。

 第一个参数value是源的值,第二个参数用于确定方法的返回类型;第三个参数用于把额外的信息传入方法,若需要传递多个信息则可以把信息放入一个集合对象来传入方法;第四个参数用于提供有关特定区域性的信息。

在这个例子里面,因为我们知道value的值是Category,所以直接把value强制转换成Category。然后根据不同的枚举值返回相应的数据,我做的例子是为了方便随便写的字符串。

 前台设置转换器,后台实现转换逻辑,这样一个完整的转换器就做好了。我们这里暂时不考虑把目标数据转换到源数据,所以并没有实现ConvertBack方法。

 下面checkbox的转换思想和上面TextBlock是一样的,这里就不再赘述了。

但是这里有个地方要提一下,我们看到checkbox有一个属性IsThreeState=true。checkbox默认是2种状态,选中或者没选中,但是它还有一种状态就是半选中。当IsChecked=null时,它就是半选中状态。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值