天天看點

資料綁定(十)Binding的資料轉換

原文: 資料綁定(十)Binding的資料轉換

當Source端Path所關聯的資料與Target端目标屬性資料類型不一緻時,需要添加資料轉換器,資料轉換器是一個自定義的類,這個類需要實作IValueConverter接口,這個接口有兩個方法需要實作:Convert和ConvertBack,當資料從Source流向Target時,将調用Convert方法,反之,将調用ConvertBack方法

例子,首先定義飛機類型

public enum Category
    {
        Bomber,
        Fighter
    }

    public enum State
    {
        Available,
        Locked,
        Unknown
    }

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

Plane類型的Category将在界面上轉換為圖檔,而State類型将會轉換成界面上的CheckBox顯示,由于存在兩個轉換,是以需要提供兩個Converter,第一個轉換是做Category類型與字元類型的轉換,字元串是圖檔的路徑

class CategoryToSourceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Category c = (Category)value;
            switch (c)
            {
                case Category.Bomber:
                    {
                        return @"\Icons\close.png";
                    }
                case Category.Fighter:
                    {
                        return @"\Icons\closeing.png";
                    }
                default:
                    {
                        return null;
                    }
            }
        }

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

由于UI上不能修改圖檔,是以隻實作了從Source到Target的轉換

另一個轉換用于将State資料轉換為bool?

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

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

界面代碼:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="275" Width="275">
    <Window.Resources>
        <local:CategoryToSourceConverter x:Key="cts" />
        <local:StateToNullableBoolConverter x:Key="stnb" />
    </Window.Resources>
    <StackPanel Background="LightBlue">
        <ListBox x:Name="listBoxPlane" Height="160" Margin="5">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Width="20" Height="20" Source="{Binding Path=Category, Converter={StaticResource cts}}" />
                        <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>
        <Button x:Name="buttonLoad" Content="Load" Height="25" Margin="5,0" Click="buttonLoad_Click" />
        <Button x:Name="buttonSave" Content="Save" Height="25" Margin="5,0" Click="buttonSave_Click" />
    </StackPanel>
</Window>      

加粗的部分是XAML中對轉換器的使用,背景代碼中實作了Load和Save兩個按鈕的點選事件

private void buttonLoad_Click(object sender, RoutedEventArgs e)
        {
            List<Plane> planeList = new List<Plane>()
            {
                new Plane(){Category=Category.Bomber, Name="B-1", State=State.Unknown},
                new Plane(){Category=Category.Bomber, Name="B-2", State=State.Unknown},
                new Plane(){Category=Category.Fighter, Name="F-22", State=State.Unknown},
                new Plane(){Category=Category.Fighter, Name="Su-47", State=State.Unknown},
                new Plane(){Category=Category.Bomber, Name="B-52", State=State.Unknown},
                new Plane(){Category=Category.Fighter, Name="J-10", State=State.Unknown}
            };

            listBoxPlane.ItemsSource = planeList;
        }

        private void buttonSave_Click(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Plane p in listBoxPlane.Items)
            {
                sb.AppendLine(string.Format("Category={0}, Name={1}, State={2}", p.Category, p.Name, p.State));
            }
            File.WriteAllText(@"d:\PlaneList.txt", sb.ToString());
        }      

界面效果如圖:

資料綁定(十)Binding的資料轉換
資料綁定(十)Binding的資料轉換

當改變checkbox的選中狀态時,Plane對象中的值會發生變化

上一篇: 控件篇

繼續閱讀