数据绑定的关键是
System.Windows.Data.Binding
它会把两个属性粘在一起,并在它们之间建立一条通道。
最简单的绑定
建立一个窗体
<Window x:Class="eventCon.Window3" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="数据绑定" Height="294" Width="443"> <Grid x:Name="xxiu"> <TextBlock HorizontalAlignment="Left" Margin="23,100,0,0" Name="textBlock1" Width="120" Height="21" VerticalAlignment="Top" Text="{Binding Name}" /> <TextBlock Height="21" HorizontalAlignment="Left" Margin="43,0,0,53" Name="textBlock2" VerticalAlignment="Bottom" Width="120" Text="{Binding Sex}" /> </Grid> </Window>
在窗体里面有两个TextBlock对象
然后创建一个数据对象
public class user { public string Name { get; set; } public string Sex { get; set; } }
最后我们为数据绑定建立通道
user us = new user() { Name = "修修", Sex = "男" }; this.xxiu.DataContext = us;
这里用DataContent把数据与xxiu这个容器联系在一起,然后在xaml页面上面用Binding把数据绑定起来。运行一下
这里数据绑定的步骤
1.创建数据对象 user us=new user()
2.把数据对象映射到容器,DataContext=us 。在书上这里称之为数据上下文,所有的FrameworkElement的元素都会有数据上下文DataContext这个属性。
3.为容器中的对象绑定数据 Binding Name
数据绑定模式
数据绑定模式有三中绑定模式
1. OneTime 一次绑定,属于绑定后就不在管的类型
2. OneWay 单向绑定,属于绑定后数据源发生变化时更新,适用于变化的数据
3. TwoWay 双向绑定,即数据在目标或数据源中都将通知对方
我们把第一个简单例子中的绑定模式设置成OneWay ,在绑定中设置Mode=OneWay
<TextBlock Margin="33,31,53,0" Name="textBlock1" Height="21" Grid.Column="0" VerticalAlignment="Top" Text="{Binding Name,Mode=OneWay }" /> <TextBlock Height="21" Margin="42,90,44,0" Name="textBlock2" Grid.Column="0" VerticalAlignment="Top" Text="{Binding Sex,Mode=OneWay}" />
这样就完成了绑定模式的设置,当Mode没有设置时默认为OneWay。
这里我们发现当我们的数据源发生了变化的时候,显示并没有更新。这是为什么呢。
更改通知
为了使源对象的更改能够传播到目标,必须实现INotifyPropertyChanged接口。INotifyPropertyChanged具有PropertyChanged事件,该事件通知绑定引擎源已经更改,以便引擎可以更新目标值【MSDN】
现在我们对我们的对象实现INotifyPropertyChanged这个接口。
这里我们需要引入
using System.ComponentModel;
然后修改数据源对象
public class user:INotifyPropertyChanged { private string _name; private string _sex; public event PropertyChangedEventHandler PropertyChanged; public string Name { get { return _name; } set { _name = value; NotifyPropertyChanged("Name"); } } public string Sex { get { return _sex; } set { _sex = value; NotifyPropertyChanged("Sex"); } } public void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
当属性发生变化时执行PropertyChanged通知值发生了变化。这样样我们在设置Mode的属性的时候就能够看到值变化的通知了
绑定到对象集合
可以将绑定对象视为一个对象,也可以将它视为一个对象集合。比如显示一个列表,为此,需要使用ItemsControl并通过DataTemplate重复此操作,以显示集合中的每一项。
对于从ItemsPanel派生的控件都能够显示列表集合,如ListBox,ComboBox等。他们都具有ItemsSource属性,可以直接为该属性设置集合。
比如我们为一个ComBoBox设置绑定。
List<user> users = new List<user>(); users.Add(new user(){Name = "贾宝玉", Sex = "男"}); users.Add( new user() { Name ="林黛玉",Sex ="女"}); users.Add(new user() { Name = "薛宝钗", Sex = "女"}); comboBox1.ItemsSource = users;
数据绑定上去了,但是不是我们想要的结果。
为什么会出现这种情况呢,它是显示的对象返回的ToString()。我们可以重写这个对象的ToString。
public override string ToString() { return string.Format("姓名:{0}性别:{1}",_name,_sex); }
但是这样并不是很好用,是很难用,我们在做WinFrom的时候有一个绑定DisplayMenber可以用来设置数据集的绑定字段。这里提供了DisplayMenberPath这个属性。
<ComboBox Margin="42,0,44,95" Name="comboBox1" Height="23" VerticalAlignment="Bottom" DisplayMemberPath="Name"/>
这样就可以得到我们想要的结果了,但是这个似乎在有些时候也不能够满足我们的需求。
这里就要用到数据模板了。通过ItemsControl控件定义数据模板。这里的数据模板和ASP.NET里面定义GridView的模板非常的相似。
<ComboBox Margin="42,0,44,95" Name="comboBox1" Height="23" VerticalAlignment="Bottom" > <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Name}"></TextBlock> <TextBlock Text="{Binding Sex}"></TextBlock> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
这里我们只需要对ItemsControl.ItemTemplate 进行设置,并同时使用 DataTemplate 来定义数据对象的外观
就得到我们所需要的值了,当然,我们可以把模板定义的非常有个性。
<ComboBox Margin="42,0,44,95" Name="comboBox1" Height="23" VerticalAlignment="Bottom" > <ComboBox.ItemTemplate> <DataTemplate> <Grid Height="60" Margin="24,0,202,12" VerticalAlignment="Bottom" Grid.ColumnSpan="2"> <Grid.RowDefinitions> <RowDefinition Height="28*" /> <RowDefinition Height="32*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="55*" /> <ColumnDefinition Width="95*" /> </Grid.ColumnDefinitions> <Image Grid.RowSpan="2" Margin="6,6,8,6" Name="image1" Stretch="Fill" Source="/eventCon;component/image/1.png" /> <TextBlock Grid.Column="1" Margin="4,4,13,3" Name="textBlock3" Text="{Binding Name}" /> <TextBlock Margin="8,5,9,6" Name="textBlock4" Grid.Column="1" Grid.Row="1" Text="{Binding Sex}" /> </Grid> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
DataGrid控件
在ASP.NET开发中常常要用到GridView控件,而做数据绑定用的最多的也是GridView控件的使用。
我们把页面上面放一个DataGrid控件,还是用上面的数据集,只是把comboBox1替换成为dataGrid1
List<user> users = new List<user>(); users.Add(new user() { Name = "贾宝玉", Sex = "男" }); users.Add(new user() { Name = "林黛玉", Sex = "女" }); users.Add(new user() { Name = "薛宝钗", Sex = "女" }); dataGrid1.ItemsSource = users;
但是这个表头并不是我们想要的,我们希望Name的地方显示“姓名” sex的地方显示“性别”,这里我们就要用到自定义列,如果对ASP.NET的熟悉这个也是很好理解的
我们给他添加两列,并指定Binding属性绑定到的列,让自动生成列为False
<my:DataGrid AutoGenerateColumns="False" Margin="60,24,78,35" Name="dataGrid1" Background="AliceBlue" BorderBrush="Snow" Foreground="Chocolate" AlternatingRowBackground="Green" > <my:DataGrid.Columns> <my:DataGridTextColumn Header="姓名" Binding="{Binding Name}" /> <my:DataGridTextColumn Header="性别" Binding="{Binding Sex}" /> </my:DataGrid.Columns> </my:DataGrid>
我们在做ComboBox 的时候使用了模板来显示一个很特别的格式,DataGrid中当然也是支持模板的,给DataGrid添加一个模板列,然后把在ComboBox中使用的模板拿过来用用。
<my:DataGrid AutoGenerateColumns="False" Margin="12,22,43,37" Name="dataGrid1" Background="AliceBlue" BorderBrush="Snow" Foreground="Chocolate" AlternatingRowBackground="Green" > <my:DataGrid.Columns> <my:DataGridTemplateColumn Header="人 物" Width="400"> <my:DataGridTemplateColumn.CellTemplate> <DataTemplate > <Grid Height="60" Margin="24,0,202,12" VerticalAlignment="Bottom" Grid.ColumnSpan="2"> <Grid.RowDefinitions> <RowDefinition Height="28*" /> <RowDefinition Height="32*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="55*" /> <ColumnDefinition Width="95*" /> </Grid.ColumnDefinitions> <Image Grid.RowSpan="2" Margin="6,6,8,6" Name="image1" Stretch="Fill" Source="/eventCon;component/image/1.png" /> <TextBlock Grid.Column="1" Margin="4,4,13,3" Name="textBlock3" Text="{Binding Name}" /> <TextBlock Margin="8,5,9,6" Name="textBlock4" Grid.Column="1" Grid.Row="1" Text="{Binding Sex}" /> </Grid> </DataTemplate> </my:DataGridTemplateColumn.CellTemplate> <my:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate /> </my:DataGridTemplateColumn.CellEditingTemplate> </my:DataGridTemplateColumn> </my:DataGrid.Columns> </my:DataGrid>
到这里发现很多的东西在ASP.NET中有些类似。