當Source端Path所關聯的數據與Target端目標屬性數據類型不一致時,添加數據轉換器(Data Converter),
簡單的數據轉換(如double轉string)WPF類庫會自動轉換。
手動轉換時需要手動寫Converter,創建一個類,並實現IValueConverter接口。
public interface IValueConverter
{
object Convert(object value, Type targetType, object parameter, CultureInfo culture);//當數據從Binding的Source流向Target時調用
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);//反之調用ConvertBack
}
例:
用於在UI上顯示圖片和將Source的三個值映射到CheckBox控件的IsChecked屬性值(bool?類型)
//種類,用於顯示圖片
public enum Category
{
Bomber,
Fighter
}
//狀態 CheckBox對應的三種狀態
public enum State
{
Available,
Locked,
Unknown
}
//飛機類
public class Plane
{
public Category Category { set; get; }
public string Name { set; get; }
public State State { set; get; }
}
提供兩個Converter用於轉換數據,一個將Category單項轉爲string(XAML自動解析爲圖片),另一個實現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.Bomber:
return @"\Icons\Bomber.png";//數據在項目Icons目錄裏
case Category.Fighter:
return @"\Icons\Fighter.png";
default:
return null;
}
}
//不被調用
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
//將Stae轉換爲bool?
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
State s = (State)value;
switch (s)
{
case State.Available:
return true;
case State.Locked:
return false;
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
<Window x:Class="Windows6.Window6_4_2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Windows6.BLL"
Title="Window6_4_2" Height="266" Width="300">
<Window.Resources>
<local:CategoryToSourceConverter x:Key="cts"/>
<local:StateToNullableBollConverter x:Key="stnb"/>
</Window.Resources>
<StackPanel Background="LightBlue">
<ListBox x:Name="listBoxPlan" 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="btnSave" Content="Save" Height="25" Margin="5,5"
Click="btnSave_Click"/>
</StackPanel>
</Window>
最後實現兩個按鈕的點擊事件
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.Fighter, Name = "F-22", State = State.Unknown}
};
this.listBoxPlan.ItemsSource = planeList;
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (Plane p in listBoxPlan.Items)
{
sb.AppendLine(string.Format("Category={0},Name={1},State={2}", p.Category, p.Name, p.State));
}
File.WriteAllText(@"D:\test\PlaneList.txt", sb.ToString());
}