上一章介绍了依赖属性,本章开始介绍WPF中最重要的部分-绑定。
数据绑定实际上关联数据源和目标的一种方式,其目标一般是应用程序的用户界面。数据源则可能是一个集合对象,一个XML文件,一个Web服务,一个数据表,一个自定义对象,甚至一个WPF元素,如Button。当数据发送改变时,用户界面会自动反映该变化。
在WPF中,有两种属性,属性和依赖属性。WPF也支持命令行绑定,让我们讨论下他们具体是怎么执行的。绑定分为数据绑定和类型绑定。
数据绑定是最重要也是最主要的绑定类型,WPF引入了像ObjectDataProvider和XMLDataprovider
等对象加强XAML中的对象绑定能力,WPF中数据绑定是非常灵活的。
1 <TextBox x:Name="txtName" /> 2 <TextBlock Text="{Binding ElementName=txtName, Path=Text.Length}" />
以上是绑定的基本用法,将TextBlock和TextTextBox txtName进行绑定,在程序运行时无论你什么时候改变了TextBox,TextBlock都会反映string的长度。标记扩展实际上是一个属性类,这里我们指定了ElementName和Path,ElementName决定可对象属性的归属,Path决定了对象显示的内容。
在XAML中,使用ObjectDataProvider装载数据是非常简单的。ObjectDataProvider能够作为静态资源调用,看下面的代码。
1 <StackPanel Orientation="Vertical"> 2 <StackPanel.Resources> 3 <ObjectDataProvider ObjectType="{x:Type m:StringData}" 4 x:Key="objStrings" MethodName="GetStrings"/> 5 </StackPanel.Resources> 6 <ListBox Name="lstStrings" Width="200" Height="300" 7 ItemsSource="{Binding Source={StaticResource objStrings}}" />
ObjectType是一个内置类结构,使用StaticResource调用对象,声明一个类。
1 public class StringData 2 { 3 ObservableCollection<String> lst= new ObservableCollection<String>(); 4 5 public StringData() 6 { 7 lst.Add("Abhishek"); 8 lst.Add("Abhijit"); 9 lst.Add("Kunal"); 10 lst.Add("Sheo"); 11 } 12 public ObservableCollection<String> GetStrings() 13 { 14 return lst; 15 } 16 }
在上面的代码中,我使用ObvervableCollection,ObvervableCollection能够在新对象插入时发出自动通知,使得ListBox进行更新,不需要手动进行。
WPF绑定在数据改变时需要进行通知,INotifyPropertyChanged和INotifyCollectionChanged需要在随着绑定的数据发送改变时更新UI控件,所以如果你想要在绑定数据发生改变的时候同时改变UI,实现INotifycollectionChanged是基本要求,对于像ItemsSource一样的集合,执行INotifyCollectionChanged。ObservableCollection本身包含了INotifyCollectionChanged,因此不管什么时候,当新元素插入或者旧元素删除的时候都会自动更新ListBox。
XAML支持XML绑定,能够通过Binding类中定义的XPath从XMLDataProvider绑定数据。
<TextBlock Text="{Binding XPath=@description}"/> <TextBlock Text="{Binding XPath=text()}"/>
假如你有XYZ节点,内部的文本可以使用text()属性取出,@标志用于属性,使用XPath,可以轻松的转载XML。
你可能很奇怪为什么我在讲WPF绑定的时候来讲数据文本(DataContext),DataContext是一种依赖属性当你为网格定义了一个DataContext属性,然后网格所有元素都将得到相同的DataContext。
<Grid DataContext="{StaticResource dtItem}"> <TextBox Text="{Binding MyProperty}" /> </Grid>
为网格定义一个DataContext,网格内的TextBox能够引用属性MyProperty作为dtItem对象。
绑定实际上是一种标记扩展,让我们讨论下绑定的成员:
1. Source:DataSource的源属性。默认引用了控件的DataContext属性。
2.ElementName:ElementName是在XAML中定义的需要引用的对象名字。假如path没有指定,使用ToString从源对象中获取数据。
3.Path:定义了实际属性的路径,目的是得到String Data。假如对象不是一个String,它将调用ToString得到数据。
4.Mode:定义了数据传送的模式。从图的角度来说存在3中状态。
OneWay
正如图A所说,Source影响着Target,但是Target却影响不到Source。
OneWayToSource
也正如图B中所表述的一样,Target影响Source,而Source却影响不到Target。
TwoWay
这个也就相当于无向图的边,Source与Target相互影响。
OneTime
在OneWay的基础上延伸了一个OneTime,仅绑定一次。如果大家属性Jquery中的one函数我想就可以不用表述了。
5.UpdateSourceTrigger:当源对象发生改变时触发,可以是:
PropertyChanged:默认选项,不管控件中发生什么改变,都会反映到绑定的对象中。
LostFocus:属性失去焦点是触发。
Explicit:源更新时,你需要显式的设置,使用UpdateSource和BindingExpression更新控件。
6.Converter:当源更新时,提供一个可以设置调用对象的接口。
7:ConverterParameter:Converter参数设置。
8:FallbackValue:当绑定没有返回值的时候定义的返回值,默认为空
9:StringFormat:一个格式化的字符串表明数据传输遵循的格式。
10:ValidatesOnDataErrors: DataErrors得到验证。
Binding myBinding = new Binding("DataObject"); myBinding.Source = myDataObject; myTextBlock.SetBinding(TextBlock.TextProperty, myBinding);
<TextBlock DockPanel.Dock="Top" > <TextBlock.Text> <MultiBinding Converter="{StaticResource mbindingconv}"> <Binding ElementName="lst" Path="Items.Count" /> <Binding ElementName="txtName" Path="Text" /> <Binding ElementName="txtAge" Path="Text" /> </MultiBinding> </TextBlock.Text> </TextBlock>
TextBox的值依赖与3个元素:ListBox count,txtName和txtAge,我使用Converter来确保我们能有在IMultiValueConverter块中找到所有的元素,然后一个个加载它们。IMultiValueConverter和IValueConverter是类似的,能够设置和返回与Text绑定的对象。
public class MyMultiBindingConverter : IMultiValueConverter { #region IMultiValueConverter Members public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string returnval = "Total no of Data {0}, NewData : "; if (values.Count() <= 0) return string.Empty; returnval = string.Format(returnval, values[0]); for (int i = 1; i < values.Count(); i++) returnval += "- " + values[i]; return returnval; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } #endregion }
简便起见,我合并可多个数组。
似水无痕:http://www.cnblogs.com/keylei203/