0%

WPF之数据绑定

一、概念:什么是数据绑定

  • WPF中的数据绑定:是在应用程序 UI 与业务逻辑之间建立连接的过程;数据绑定实质上是绑定目标与绑定源之间的桥梁。

数据绑定

  • 如上图所示:每一个绑定都包含四个部分:
  1. 绑定目标:指定需要应用到的对象。

  2. 绑定源:指定提供绑定数据的对象。

  3. 目标属性:作用到绑定目标的某一些属性。

  4. 源属性:绑定源中存储绑定数据的属性。


二、数据绑定的模式(数据流的方向)

数据绑定

OneWay:绑定导致对源属性的更改会自动更新目标属性,但是对目标属性的更改不会传播回源属性

  1. 适用于绑定的控件为隐式只读控件的情况。

  2. 可避免 TwoWay 绑定模式的系统开销

TwoWay:绑定导致对源属性的更改会自动更新目标属性,而对目标属性的更改也会自动更新源属性

  1. 此绑定类型适用于可编辑窗体或其他完全交互式 UI 方案。

OneWayToSource 与 OneWay 绑定相反

  1. 一个示例方案是您只需要从 UI 重新计算源值的情况。

OneTime 绑定未在图中显示,该绑定会导致源属性初始化目标属性,但不传播后续更改

  1. 使用当前状态的快照适合使用的或数据状态实际为静态的数据。

  2. 如果要从源属性初始化具有某个值的目标属性,并且事先不知道数据上下文,则也可以使用此绑定类型。

  3. 此绑定类型实质上是 OneWay 绑定的简化形式,在源值不更改的情况下可以提供更好的性能。

三、数据绑定的具体步骤

  1. 定义一个类(绑定目标),定义源属性

  2. 在主窗口cs文件中new一个绑定目标的实例,给要绑定源(需要绑定的控件)设定DataContext(数据上下文)

  3. 在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;
//若属性改变了,事件PropertyChanged会被对象发送出去
//而数据绑定会时刻监听属性的变化,当对象属性变化时,数据绑定检测到事件PropertyChanged,界面层也会跟着一起变化
if(PropertyChanged!=null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
}

五、ListBox的数据绑定

  1. 可以使用ListBox和数据绑定来将List里的数据显示出来
  2. ListBox显示集合用到的是ItemSource属性,不是DataContext
  3. 在XAML中可以设置ListBox的DisplayMemberPath属性来指定需要显示的源属性,默认是把每一个项的对象属性以tostring的形式显示。
  4. 在XAML中也可以设置ListBox的SelectedValuePath属性来指定绑定的源属性
  5. 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());
}
}

ListBox

六、DataGrid

  1. <DataGrid.Columes>自定义列,跟Grid布局的自定义列类似

  2. 属性AutoGenerateColumns=”False”禁止自动创建列

  3. 每列可以设置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;
}
}

DataGrid


参考资料:segmentfault

-------------本文结束感谢您的阅读-------------