1. 程式人生 > >WPF 繫結中Converter的應用

WPF 繫結中Converter的應用

在WPF 經常用到繫結,如果繫結的源資料和目標屬性是同類型的則不需要轉換。比如

            <TextBox x:Name="txt1" Background="Blue" Text="測試"/>
            <TextBox Background="{Binding ElementName=txt1,Path=Background}" Grid.Column="1"/>
如果是不同型別的資料我們要怎麼做呢?比如有一個文字框,一個按鈕,我一個文字框裡輸入一個的數字用來代表顏色,1表示“紅色”,2 表示“綠色”,3表示“藍色”。我輸入對應的數字,按鈕的文字顯示對應顏色。

顯然這個不是同類型的資料:文字框的資料是String型別,而按鈕的文字顏色是Brush型別,這個時候我們就需要用到轉換器(converter)來告訴我們的banding怎麼轉換我們的資料。首先定義一個轉換器(類),命名為Number2Color,要想實現轉換的功能,必須實現IValueConverter介面中的Convert和ConvertBack兩個函式。Convert函式是把我們的資料來源轉換為目標資料的方法,這裡就是把文字框裡的string型別轉換為Brush型別。我們這樣實現Convert函式,(引數value就是資料來源的值,這裡就是文字框中的資料,返回值就是Brush)

 public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int colorValue = System.Convert.ToInt32(value);
            switch (colorValue)
            {
                case 1:              //紅色
                    return new SolidColorBrush(Colors.Red);

                case 2:               //綠色
                    return new SolidColorBrush(Colors.Green);
                case 3:               //藍色
                    return new SolidColorBrush(Colors.Blue);

            }
            return new SolidColorBrush(Colors.LawnGreen);
        }


ConvertBak函式我們暫時先這樣實現
       public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {

            return new NotImplementedException();
        }
現在來到xaml程式碼,顯示一個文字框和一個按鈕,並把按鈕的前景色繫結到文字框的文字屬性上,使用自定義的Number2Color轉換器,執行程式  你修改文字框中的值,會看到按鈕顏色發生變化。


<Window x:Class="Converter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cvt="clr-namespace:Converter"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
            <cvt:Number2Color x:Key="N2C"/>
    </Window.Resources>
    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="50"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox x:Name="colorText" Text="1"  BorderBrush="Gray" BorderThickness="2" Width="200" Grid.Row="1"/>
        <Button x:Name="testBtn" Content="測試" Width="100" Grid.Row="3" FontSize="25" Foreground="{Binding Path=Text,ElementName=colorText, Converter={StaticResource N2C}}"/>
    </Grid>
</Window>
現在我們想實現如果按鈕的文字顏色發生改變,文字框中的文字也對應改變。新增3個按鈕,點選按鈕的時候改變“測試”按鈕的文字顏色。
<StackPanel Orientation="Horizontal">
            <Button Content="Red" Width="100" Foreground="Red" Click="btnClick"/>
            <Button Content="Green" Width="100" Foreground="Green" Click="btnClick"/>
            <Button Content="Blue" Width="100" Foreground="Blue" Click="btnClick"/>
 </StackPanel>
        private void btnClick(object sender, RoutedEventArgs e)
        {
            testBtn.Foreground = ((Button)sender).Foreground;
        }
執行程式,點選按鈕,發現“測試”按鈕文字顏色是改變了,但是文字框中的文字沒有發生改變。這個和我們的繫結模式有關係,預設是單向繫結,我們應設定為雙向繫結,我們為繫結增加屬性:Mode=TwoWay
<Button x:Name="testBtn"  Content="測試" Width="100" Grid.Row="3" FontSize="25" Foreground="{Binding Path=Text,ElementName=colorText, Converter={StaticResource N2C}, Mode=TwoWay}"/>
此時執行程式,點選按鈕發現,文字能變色,文字框內數字依然沒有改變,而且按鈕出現紅色邊框,提示錯誤。因為我們沒有告訴程式怎麼將Brush資料轉換為文字資料,這正是ConvertBack要做的事情。我們之前在實現這個函式的時候是丟擲一個異常,所有按鈕會出現紅色邊框,表示不允許逆向轉換。現在就讓我們告訴程式怎麼轉換資料
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            SolidColorBrush sb = (SolidColorBrush)value;
            Color c = sb.Color;
           if (c==Colors.Red)
           {
               return 1;
           }
           else if (c == Colors.Green)
           {
               return 2;
           }
            else if (c==Colors.Blue)
            {
                return 3;
            }
            return 0;
        }

    }
這樣就能實現雙向綁定了。

轉換器程式碼

namespace Converter
{
      public  class Number2Color:IValueConverter
      {
       public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int colorValue = System.Convert.ToInt32(value);
            switch (colorValue)
            {
                case 1:              //紅色
                    return new SolidColorBrush(Colors.Red);

                case 2:               //綠色
                    return new SolidColorBrush(Colors.Green);
                case 3:               //藍色
                    return new SolidColorBrush(Colors.Blue);

            }
            return new SolidColorBrush(Colors.LawnGreen);
        }

       public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            SolidColorBrush sb = (SolidColorBrush)value;
            Color c = sb.Color;
           if (c==Colors.Red)
           {
               return 1;
           }
           else if (c == Colors.Green)
           {
               return 2;
           }
            else if (c==Colors.Blue)
            {
                return 3;
            }
            return 0;
        }

    }
}

前臺程式碼
<Window x:Class="Converter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cvt="clr-namespace:Converter"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
            <cvt:Number2Color x:Key="N2C"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="50"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox x:Name="colorText" Text="1"  BorderBrush="Gray" BorderThickness="2" Width="200" Grid.Row="1"/>
        <Button x:Name="testBtn"  Content="測試" Width="100" Grid.Row="3" FontSize="25" Foreground="{Binding Path=Text,ElementName=colorText, Converter={StaticResource N2C}, Mode=TwoWay}"/>
        <StackPanel Orientation="Horizontal">
            <Button Content="Red" Width="100" Foreground="Red" Click="btnClick"/>
            <Button Content="Green" Width="100" Foreground="Green" Click="btnClick"/>
            <Button Content="Blue" Width="100" Foreground="Blue" Click="btnClick"/>
        </StackPanel>
    </Grid>
</Window>
按鈕點選程式碼
        private void btnClick(object sender, RoutedEventArgs e)
        {
            testBtn.Foreground = ((Button)sender).Foreground;
        }