值得转换
返回到BookDemo应用程序中。图书的作者还没有显示在用户界面中。如果将Authors属性绑定到标签元素上,就要调用Array类的ToString()方法,它值返回类型的名称。一种解决方法是将Authors属性绑定到一个列表框上。对于该列表框,可以定义一个末班,以显示特定的视图。另一种解决方法是将Athors属性返回的字符串数组转换为一个字符串,在将该字符串用于绑定。
StringArrayConverter 类可以将字符串数组转换为字符串。WPF转换器类必须实现System.Windows.Data名称空间中的IValueConverter接口。这个接口定义了Convert()和ConvertBack()方法。在StringArrayConverter类中,Convert()方法会通过String.Join()方法吧Value变量中的字符串数组转换为字符串。从Convert()方法接受的parameter变量中提取Join()方法的分隔符参数
using System;
using System.Globalization;
using System.Windows.Data;
namespace BooksDemo.Utilities
{
[ValueConversion(typeof(string[]), typeof(string))]
class StringArrayConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
string[] stringCollection = (string[])value;
string separator = parameter?.ToString() ?? string.Empty;
return String.Join(separator, stringCollection);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
在XAML代码中,StringArrayConverter类可以声明为一个资源,一遍从Binding标记扩展中引用它:
<UserControl x:Class="BooksDemo.Controls.BookUC"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BooksDemo.Models"
xmlns:utils="clr-namespace:BooksDemo.Utilities"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<utils:StringArrayConverter x:Key="stringArrayConverter"/>
<!--etc.-->
为了输出多行结果,声明了一个TextBlock元素,将其TextWrapping属性设置为Wrap,以便可以显示多个作者。在Binding标记扩展中。将Path设置为Authors,它定义为一个返回字符串数组的属性。Converter属性指定字符串数组从stringArrayConverter资源中转换。转换器实现的Convert()方法接受ConverterParameter=','作为输入来分隔多个作者。
<Label Content="Title" Grid.Row="0" Grid.Column="0" Margin="10,0,5,0"
HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Label Content="Publisher" Grid.Row="1" Grid.Column="0"
Margin="10,0,5,0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Label Content="Isbn" Grid.Row="2" Grid.Column="0"
Margin="10,0,5,0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Label Content="Authors" Grid.Row="3" Grid.Column="0"
Margin="10,0,5,0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<TextBox Text="{Binding Title}" Grid.Row="0" Grid.Column="1" Margin="5"/>
<TextBox Text="{Binding Publisher}" Grid.Row="1" Grid.Column="1" Margin="5"/>
<TextBox Text="{Binding Isbn}" Grid.Row="2" Grid.Column="1" Margin="5"/>
<TextBlock Text="{Binding Authors,Converter={StaticResource stringArrayConverter},ConverterParameter=','}" Grid.Row="3" Grid.Column="1" Margin="5"
VerticalAlignment="Center" TextWrapping="Wrap"/>
效果图:
动态添加列表项
如果列表项要动态添加,就必须通知wpf元素:要在列表中添加元素。
在wpf应用程序的xaml代码中,要给stackPanel添加一个按钮元素。给CLick事件指定OnAddBook()方法
<StackPanel Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"
Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="Show Book" Margin="5" Click="OnShowbook"/>
<Button Content="change Book" Margin="5" Click="OnChangeBook"/>
<Button Margin="5" Padding="4" Content="Add Book" Click="OnAddBook" />
</StackPanel>
在OnAddBook方法中,将一个新的Book对象添加到列表中。
private void OnAddBook(object sender, RoutedEventArgs e)
{
((this.FindResource("books") as ObjectDataProvider).Data as IList<Book>).Add(new Book("new book", "zhangcao", "12344", "3434353", "kshfkjhadfh", "34wg"));
}
赋予DataContext的对象必须实现INotifyCollectionChanged接口。这个接口定义了由WPF应用程序使用的CollectionChanged事件。出了用自定义集合类实现这个接口之外,还可以使用泛类型集合类ObservableCollection<T>,该类在WindowsBase程序集的System.Collections.ObjectModel名称空间中定义。现在,把第一个新类表项添加到集合中,这个新列表项会立即表示在列表框中。
private ObservableCollection<Book> _books1 = new ObservableCollection<Book>();