可以将ItemsControl类控件的依赖项属性ItemsSource作为集合的绑定对象。那么如果集合实现了ObservableCollection<T>这个泛型接口,就能够在集合改变的时候界面也做出响应的改变。
ItemsSource = "{Binding}" <--第一种表示方式在父级控件中设置了DataContext属性 !--> ItemsSource = {Binding Source = {StaticResource XXXX}} <--第二种表示方式使用资源的方式来显示数据XXXX为资源的Key !-->
<local:Persons x:Key="Persons"></local:Persons>DataContext = "{StaticResource Persons}" 如果不使用资源作为数据可在后台使用 control.DataContext = ...这样的表达式来定义DataContext<-- 后面的这个语句是将父级控件的DataContext属性赋值为资源 !-->
DataContext共享源
如果界面中的许多的元素都绑定到相同的一个源对象上,只是不同的属性。出于这个原因wpf可以指定一个隐式的数据源,而不用显示的标记每一个Source,ElementName,RelativeSource。
可以找到一个常见的父元素,并为它指定数据上下文。设置他的DataContext属性。那么在界面显示的时候如果绑定没有显式的源对象的时候。wpf会遍历逻辑树,直到找到一个非空的DataContext的时候为止。
1 <StackPanel DataContext="{Binding Source={StaticResource Persons}}"> 2 <TextBlock Text="{Binding Path=Count}"></TextBlock> 3 <Button Width="100" Click="Button_Click">Add</Button> 4 <ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}"> 5 <ListBox.ItemTemplate> 6 <DataTemplate> 7 <StackPanel> 8 <TextBlock Text="{Binding Path=Name}"></TextBlock> 9 <Image Width="40" Height="40" Source="F:\Loose XAML PhotoGallery\Creek.jpg"></Image> 10 </StackPanel> 11 </DataTemplate> 12 </ListBox.ItemTemplate> 13 </ListBox> 14 </StackPanel>
可以按照这样的方式来使用。另外如果要避免将数据源定义为资源可以使用 name.DataContext = .....这样的方式。
数据的呈现
我们可以按照我们想要的方式来显示数据,为了达到这个目的我们可以使用两种方式,一种是使用数据模版,一种是使用数据转换器。
1. 使用数据模版:
许多wpf的控件的属性可以添加数据模板,ContentControl控件的ContentTemplate属性,可以控制Content的呈现。ItemControl的ItemTemplate会被应用到每一个项。HeaderContentControl有一个HeaderTemplate属性可以控制Header的呈现等。
5 <ListBox.ItemTemplate> 6 <DataTemplate> 7 <StackPanel> 8 <TextBlock Text="{Binding Path=Name}"></TextBlock> 9 <Image Width="40" Height="40" Source="F:\Loose XAML PhotoGallery\Creek.jpg"></Image> 10 </StackPanel> 11 </DataTemplate> 12 </ListBox.ItemTemplate>
正好一这样的方式来设置数据模版。
当然DataTemplate不需要被内联声明,他们通常被当当作一个资源。因此他们可以在多个元素间共享,无论这个属性在哪里,都可以让DataTemmplate对象自动被应用到指定的属性上。通过设置DataType属性为特定的类型就可以实现。
<DataTemplate DataType="local:Person" x:Key="PersonTemplate"> <StackPanel> <TextBlock Text="{Binding Path=Name}"></TextBlock> <Image Width="40" Height="40" Source="F:\Loose XAML PhotoGallery\Creek.jpg"></Image> </StackPanel> </DataTemplate>
<ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" ItemTemplate="{StaticResource ResourceKey=PersonTemplate}"> </ListBox>
2. 值转换器
值转换器能把源值转换为完全不同的目标值。他们可以用来插入自定义逻辑,但是不放弃数据绑定带来的好处。值转化器的目的就是实现在源和目标数据类型之间的转换。其实值转化器的使用也是分为两种情况的 1. 原值和目标值为兼容类型,只是想修改要显示的数据。 2. 原值和目标值是不兼容的,通过值转换器来实现原值的显示。
<local:BackGroundConverter x:Key="backGroundConverter"></local:BackGroundConverter> <-- 在资源中定义!-->
<TextBlock x:Name="Number" Background="{Binding ElementName=pictureBox,Path=Items.Count,Converter={StaticResource ResourceKey=backGroundConverter}, ConverterParameter=LightBlue}"></TextBlock>
上面展示的是值转换器的如何使用,值转换器的定义使用是要实现IValueConverter这个接口的
1 public class ShowTextConverter : IValueConverter 2 { 3 4 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 5 { 6 string showStr = "当前文件夹下的图片数:"; 7 int num = int.Parse(value.ToString()); 8 return (num == 1 || num == 0) ? showStr + num.ToString() + "Item" : showStr + num.ToString() + " Items"; 9 } 10 11 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 12 { 13 throw new NotImplementedException(); 14 } 15 }
// value 要转换的值
// TargetType 要转化为的类型
// parameter 在默认的情况下会被设置为null,
// culture 使用美国英语作为默认值,en-US,尽管如此Binding还是可以通过Binding.ConverterParameter和Binding.ConverterCulture控制这两个值。
注意在上面的xaml语句中有ConverterParameter=LightBlue这个语句。默认情况下Paramter会被设置为null,但是使用这个句子酒水为转换方法传入parameter参数。
使用值转换器的另外一种情况是源和目标是兼容的,但是要根据情况定制显示
1 public class ShowTextConverter : IValueConverter 2 { 3 4 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 5 { 6 string showStr = "当前文件夹下的图片数:"; 7 int num = int.Parse(value.ToString()); 8 return (num == 1 || num == 0) ? showStr + num.ToString() + "Item" : showStr + num.ToString() + " Items"; 9 } 10 11 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 12 { 13 throw new NotImplementedException(); 14 } 15 }