一般情况下,应用程序会有三层结构:数据存储层,数据处理层(业务逻辑层),数据展示层(UI界面)。
WPF是“数据驱动UI”。
- Binding实现(通过纯C#代码)
Binding分为source和target,即源和目标。
如何通过Binging实现UI元素和代码对象的连接。
首先绑定源对象要实现INotifyPropertyChanged接口,该接口引用自System.ComponentModel命名空间,所有使用前要引用该命名空间。该接口有一个PropertyChanged事件,可以帮助自动监听源对象的属性变化。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
class Student:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string name; public string Name
{
get { return name; }
set {
name = value;
if(this.PropertyChanged!=null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
} }
如上代码所示,在绑定了接口以后,当Name属性的值发生变化时,就会自动通知,然后刷新UI元素进行更新。
当然还没有结束,我们现在需要添加界面。然后在后台代码中设置Binding
其实在textBox元素中已经为我们封装好了这些,即SetBinding方法。
所以可以改写如下:
- 标记扩展进行Data Binding
- 控制Binding数据流向的是Mode属性,而控制数据更新的是UpdateSourceTrigger属性
- 没有Path的Binding
有时候,Binding源本身就是数据,比如字符串,或者int类型,他们的实例本身就是数据,而不需要通过属性来提供访问,那么在指定path时可以通过一个.来代替,或者直接不写path,在XAML代码里可以省略不写,在C#代码中必须显式写.来表示path指向实例本身。
- 为Binding指定源的几种方法
- Binding过程中可以没有path,那么可不可以没有source,当然可以,可以通过添加DataContext来隐式表达source。
- 使用集合对象作为列表控件的ItemsSource
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel; namespace WpfApp7
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); //准备数据源
List<Student> stuList = new List<Student>()
{
new Student(){Id=,Name="Tim",Age=},
new Student(){Id=,Name="Tom",Age=},
new Student(){Id=,Name="Kyle",Age=},
new Student(){Id=,Name="Tony",Age=},
new Student(){Id=,Name="Vina",Age=},
};
//为listBox设置Binding
this.listBoxStudents.ItemsSource = stuList;
this.listBoxStudents.DisplayMemberPath = "Name";
//为TextBox设置Binding
Binding binding = new Binding("SelectedItem.Id") { Source = this.listBoxStudents };
this.textBoxId.SetBinding(TextBox.TextProperty, binding);
}
} class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; } } }
界面代码如下:
<Window x:Class="WpfApp7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp7"
mc:Ignorable="d"
Title="Binding Source" Height="240" Width="300">
<StackPanel x:Name="stackPanel1" Background="LightBlue">
<TextBlock Text="Student ID" FontWeight="Bold" Margin="5"/>
<TextBox x:Name="textBoxId" Margin="5"/>
<TextBlock Text="Student List" FontWeight="Bold" Margin="5"/>
<ListBox x:Name="listBoxStudents" Height="110" Margin="5"/> </StackPanel>
</Window>
- 使用ObjectDataProvider对象作为Binding的Source
现在有一个Calculator的类,他具有加减乘除的方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; namespace ObjectDateProvider
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.SetBinding();
} private void SetBinding()
{
//创建并配置ObjectDataProvider对象
ObjectDataProvider odp = new ObjectDataProvider
{
ObjectInstance = new Calculator(),
MethodName = "Add"
};
odp.MethodParameters.Add("");
odp.MethodParameters.Add("");
//以ObjectDataProvider对象为Source创建Binding
Binding bindingToArg1 = new Binding("MethodParameters[0]")
{
Source = odp,
BindsDirectlyToSource = true,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
Binding bindingToArg2 = new Binding("MethodParameters[1]")
{
Source = odp,
BindsDirectlyToSource = true,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
}; Binding bindingToResult = new Binding(".") { Source = odp }; //将Binding关联到UI元素上
this.textBoxArg1.SetBinding(TextBox.TextProperty, bindingToArg1);
this.textBoxArg2.SetBinding(TextBox.TextProperty, bindingToArg2);
this.textBoxResult.SetBinding(TextBox.TextProperty, bindingToResult);
}
} class Calculator
{
public string Add(string arg1,string arg2)
{
double x = ;
double y = ;
double z = ;
if(double.TryParse(arg1,out x)&&double.TryParse(arg2,out y))
{
z = x + y;
return z.ToString();
}
return "Input Error";
}
}
}
界面代码如下:
<Window x:Class="ObjectDateProvider.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ObjectDateProvider"
mc:Ignorable="d"
Title="MainWindow" Height="135" Width="300">
<StackPanel Background="LightBlue">
<TextBox x:Name="textBoxArg1" Margin="5"/>
<TextBox x:Name="textBoxArg2" Margin="5"/>
<TextBox x:Name="textBoxResult" Margin="5"/> </StackPanel>
</Window>
界面代码
- 使用Binding的RelativeSource
- Binding对数据的转换与校验
Binding用于数据有效性检验的是ValidationRules属性,用于数据类型转换关卡的是Converter属性。