一、概念:什么是数据绑定
- WPF中的数据绑定:是在应用程序 UI 与业务逻辑之间建立连接的过程;数据绑定实质上是绑定目标与绑定源之间的桥梁。
绑定目标:指定需要应用到的对象。
绑定源:指定提供绑定数据的对象。
目标属性:作用到绑定目标的某一些属性。
源属性:绑定源中存储绑定数据的属性。
二、数据绑定的模式(数据流的方向)
OneWay:绑定导致对源属性的更改会自动更新目标属性,但是对目标属性的更改不会传播回源属性
适用于绑定的控件为隐式只读控件的情况。
可避免 TwoWay 绑定模式的系统开销
TwoWay:绑定导致对源属性的更改会自动更新目标属性,而对目标属性的更改也会自动更新源属性
- 此绑定类型适用于可编辑窗体或其他完全交互式 UI 方案。
OneWayToSource 与 OneWay 绑定相反
- 一个示例方案是您只需要从 UI 重新计算源值的情况。
OneTime 绑定未在图中显示,该绑定会导致源属性初始化目标属性,但不传播后续更改
使用当前状态的快照适合使用的或数据状态实际为静态的数据。
如果要从源属性初始化具有某个值的目标属性,并且事先不知道数据上下文,则也可以使用此绑定类型。
此绑定类型实质上是 OneWay 绑定的简化形式,在源值不更改的情况下可以提供更好的性能。
三、数据绑定的具体步骤
定义一个类(绑定目标),定义源属性
在主窗口cs文件中new一个绑定目标的实例,给要绑定源(需要绑定的控件)设定DataContext(数据上下文)
在XAML中的绑定目标中输入目标属性和源属性的binding语句,
- 例Text=”{Binding Name}”,在这里Text为绑定属性,Name为目标属性。
- 补充:几乎所有控件属性都可以进行这样的数据绑定
1
| <TextBox x:Name="txtname" Text="{Binding Name}" ToolTip="{Binding Name}"/>
|
```.cs
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//txtname.DataContext = p;
//txtage.DataContext = p;
//txtheight.DataContext = p;
//cbman.DataContext = p;
//子控件以及所有后代控件都默认继承父控件的DataContext
grid.DataContext = p;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| * 如上所示,可以编写TextBox控件的Text属性为Text="{Binding Name}"使其绑定在.cs文件中用数据上下文指定的对象上,其中TextBox为绑定目标,Text和ToolTip都为目标属性,p为绑定源,Name为源属性。
### 四、创建动态的数据绑定
* 由于控件一般都有ContextChanged的事件,所以当界面改变时,逻辑层的属性也会跟着一起改变,如果要求界面层的属性跟逻辑层的属性一起发生改变,则需要实现INotifyPropertyChanged接口,并在属性值变化后触发事件:PropertyChanged
* INotifyPropertyChanged:
1. INotifyPropertyChanged接口是.net内置的接口 2. 数据绑定会检测DataContext是否实现了INotifyPropertyChanged,若实现了,就会监听PropertyChanged得知属性发生变化 3. 若不用监听,则没必要实现INotifyPropertyChanged接口
```C# class Person : INotifyPropertyChanged { private string name; public event PropertyChangedEventHandler PropertyChanged; public string Name { get { return name; } set { this.name = value; if(PropertyChanged!=null) { PropertyChanged(this, new PropertyChangedEventArgs("Name")); } } } }
|
五、ListBox的数据绑定
- 可以使用ListBox和数据绑定来将List里的数据显示出来
- ListBox显示集合用到的是ItemSource属性,不是DataContext
- 在XAML中可以设置ListBox的DisplayMemberPath属性来指定需要显示的源属性,默认是把每一个项的对象属性以tostring的形式显示。
- 在XAML中也可以设置ListBox的SelectedValuePath属性来指定绑定的源属性
- SelectedItem获得的是选中行的对应对象,若没选中行就是null;SelectedValue获得的是选中行对应的对象的“SelectedValuePath标志的属性名”
1
| <ListBox DisplayMemberPath="Name" SelectedValuePath="Age" x:Name="listboxperson"\>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { List<Person> list = new List<Person>(); list.Add(new Person()); list.Add(new Person("苏坤", 20)); list.Add(new Person(false, 160, "黄蓉", 16)); //ListBox显示的集合是ItemSource属性,不是DataContext listboxperson.ItemsSource = list; } private void Button_Click(object sender, RoutedEventArgs e) { //SelectedItem获得的是选中行的对应对象,若没选中行就是null object sItem = listboxperson.SelectedItem; //SelectedValue获得的是选中行对应的对象的“SelectedValuePath标志的属性名” object sValue = listboxperson.SelectedValue; MessageBox.Show(sValue.ToString()); } }
|
六、DataGrid
<DataGrid.Columes>自定义列,跟Grid布局的自定义列类似
属性AutoGenerateColumns=”False”禁止自动创建列
每列可以设置IsReadOnly来禁止编辑;整个表格也可以在DataGrid中设置IsReadOnly来禁止编辑
1 2 3 4 5 6 7 8
| <DataGrid x:Name="datagrid" IsReadOnly="True" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Name}" Header="姓"/> <DataGridCheckBoxColumn Binding="{Binding Gender}" Header="性别"/> <DataGridTextColumn Binding="{Binding Age}" Header="年龄"/> <DataGridTextColumn Binding="{Binding Score}" Header="分数"/> </DataGrid.Columns> </DataGrid>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public partial class DataGridTest : Window { public DataGridTest() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { List<Student> list = new List<Student>(); list.Add(new Student { Name = "小明", Age = 18, Score = 80, Gender = true, Class = "一班" }); list.Add(new Student { Name = "小红", Age = 25, Score = 60, Gender = false, Class = "二班" }); list.Add(new Student { Name = "小姐姐", Age = 20, Score = 100, Gender = false, Class = "三班" }); datagrid.ItemsSource = list; List<string> strlist = new List<string>(); strlist.Add("一班"); strlist.Add("二班"); strlist.Add("三班"); classcc.ItemsSource = strlist; } }
|
参考资料:segmentfault