第7章:数据绑定 本章目标
理解路由事件
掌握键盘输入事件
掌握鼠标输入事件
掌握多点触控输入事件
数据绑定概述 什么是数据绑定 将WPF中的至少一个带有依赖项属性的两个对象的两个属性进行绑定,使某一个依赖项属性可以更新和它绑定的属性的功能。
数据绑定涉及两个方面:一个是绑定源,再一个是绑定目标。绑定源即空间绑定所使用的源数据,绑定目标即数据显示的控件。
对于绑定源,在WPF中可以是以下4种 :
CLR对象:可以绑定到CLR类的公开属性/子属性/索引器上
ADO.net 对象:例如DataTable/DataView 等。
XML文件:使用XPath 进行解析
DependencyObject: 绑定到依赖项属性上,即控件绑定控件。
对于绑定目标,必须是WPF中的DependencyObject,将数据绑定到其依赖项属性上 。
数据绑定的绑定源
使用接口 INoitfyPropertyChanged
使用依赖属性 DependecyProperty
数据绑定的语法 1 {Binding ElementName=元素名,Path=属性,Mode=绑定模式}
绑定DependencyObject对象 根据元素名称绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <StackPanel> <TextBox x:Name="txt1" TextWrapping="Wrap" Height="100"></TextBox> <TextBlock Text="{Binding ElementName=txt1,Path=Text}"></TextBlock> </StackPanel> </Window>
相对于自身或父元素绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <StackPanel Height="150"> <Button Height="40" Content="{Binding RelativeSource={RelativeSource Mode=Self},Path=Height}" /> <Button Height="40" Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel},Path=Height}"/> </StackPanel> </Window>
绑定CLR对象 绑定到单个对象
xaml:
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 37 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Name="mainWindow" Title="MainWindow" Height="450" Width="800"> <StackPanel> <Label HorizontalAlignment="Center" FontSize="20">学生信息</Label> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="200"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" Content="名字" HorizontalAlignment='Right'/> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Name}" /> <Label Grid.Row="1" Grid.Column="0" Content="性别" HorizontalAlignment='Right'/> <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Sex}" /> <Label Grid.Row="2" Grid.Column="0" Content="年龄" HorizontalAlignment='Right'/> <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Age}" /> </Grid> </StackPanel> </Window>
cs:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;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 WPF_CH07_Demo01 { public partial class MainWindow : Window { public MainWindow () { InitializeComponent(); Student student = new Student() { Name = "孙悟空" , Sex = "男" , Age = 18 }; this .DataContext = student; } } public class Student { public string Name { get ; set ; } public string Sex { get ; set ; } public int Age { get ; set ; } } }
绑定到集合元素-1
xaml代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <StackPanel> <TextBlock>姓名:</TextBlock> <ListBox ItemsSource="{Binding NameList}"> </ListBox> </StackPanel> </Window>
cs代码:
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 37 38 39 40 41 42 43 44 45 using System;using System.Collections.Generic;using System.Collections.ObjectModel;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 WPF_CH07_Demo01 { public partial class MainWindow : Window { public MainWindow () { InitializeComponent(); this .NameList = new ObservableCollection<string >(); this .NameList.Add("孙悟空" ); this .NameList.Add("猪八戒" ); this .NameList.Add("沙悟净" ); this .DataContext = this ; } public ObservableCollection<string > NameList { get ; set ; } } }
绑定到集合元素-2
xaml:
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 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <StackPanel> <TextBlock>学生:</TextBlock> <ListBox ItemsSource="{Binding StuList}"> <ListBox.ItemTemplate> <DataTemplate> <UniformGrid Columns="3"> <TextBlock Text="{Binding Name}" Margin="5"/> <TextBlock Text="{Binding Sex}" Margin="5"/> <TextBlock Text="{Binding Age}" Margin="5"/> </UniformGrid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Window>
cs:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 using System;using System.Collections.Generic;using System.Collections.ObjectModel;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 WPF_CH07_Demo01 { public partial class MainWindow : Window { public MainWindow () { InitializeComponent(); this .StuList = new ObservableCollection<Student>(); this .StuList.Add(new Student { Name="孙悟空" ,Sex="男" ,Age=150 }); this .StuList.Add(new Student { Name = "猪八戒" , Sex = "男" , Age = 120 }); this .StuList.Add(new Student { Name = "沙悟净" , Sex = "男" , Age = 100 }); this .DataContext = this ; } public ObservableCollection<Student> StuList { get ; set ; } } public class Student { public string Name { get ; set ; } public string Sex { get ; set ; } public int Age { get ; set ; } } }
MVVM模式实现数据绑定
xaml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <StackPanel> <TextBlock Text="{Binding School}" /> <TextBlock Text="{Binding TeacherCount}" /> <TextBlock Text="{Binding StudentCount}" /> </StackPanel> </Window>
cs:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 using System;using System.Collections.Generic;using System.Collections.ObjectModel;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 WPF_CH07_Demo01 { public partial class MainWindow : Window { public MainWindow () { InitializeComponent(); MainViewModel mvm = new MainViewModel(); mvm.School = "广创" ; mvm.TeacherCount = 20 ; mvm.StudentCount = 500 ; this .DataContext = mvm; } } public class MainViewModel { public string School { get ; set ; } public int TeacherCount { get ; set ; } public int StudentCount { get ; set ; } } }
属性改变通知进行数据绑定
xaml:
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 37 38 39 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Name="mainWindow" Title="MainWindow" Height="450" Width="800"> <StackPanel> <Label HorizontalAlignment="Center" FontSize="20">学生信息</Label> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="200"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" Content="名字" HorizontalAlignment='Right'/> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Name}" /> <Label Grid.Row="1" Grid.Column="0" Content="性别" HorizontalAlignment='Right'/> <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Sex}" /> <Label Grid.Row="2" Grid.Column="0" Content="年龄" HorizontalAlignment='Right'/> <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Age}" /> <Button Name="btn1" Grid.Row="3" Grid.Column="1" Width="120" Height="40" Margin="5" Click="btn1_Click">显示对象信息</Button> <Button Name="btn2" Grid.Row="4" Grid.Column="1" Width="120" Height="40" Margin="5" Click="btn2_Click">清除对象信息</Button> </Grid> </StackPanel> </Window>
cs:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;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 WPF_CH07_Demo01 { public partial class MainWindow : Window { Student student; public MainWindow () { InitializeComponent(); student = new Student() { Name = "孙悟空" , Sex = "男" , Age = 18 }; this .DataContext = student; } private void btn1_Click (object sender, RoutedEventArgs e ) { MessageBox.Show(this .student.ToString()); } private void btn2_Click (object sender, RoutedEventArgs e ) { this .student.Name = null ; this .student.Sex = null ; this .student.Age = null ; } } public class Student : INotifyPropertyChanged { private string name; public string Name { get { return name; } set { name = value ; OnPropertyChanged("Name" ); } } private string sex; public string Sex { get { return sex; } set { sex = value ; OnPropertyChanged("Sex" ); } } private int ? age; public int ? Age { get { return age; } set { age = value ; OnPropertyChanged("Age" ); } } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged (string property ) { PropertyChanged?.Invoke(this , new PropertyChangedEventArgs(property)); } public override string ToString () { return string .Format("姓名:{0},性别:{1},年龄:{2}" , Name, Sex, Age); } } }
绑定ADO.NET 对象
xaml:
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 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Name="mainWindow" Title="MainWindow" Height="450" Width="800"> <StackPanel> <TextBlock>学生:</TextBlock> <ListBox ItemsSource="{Binding StuListData}"> <ListBox.ItemTemplate> <DataTemplate> <UniformGrid Columns="3"> <TextBlock Text="{Binding Name}" Margin="5"/> <TextBlock Text="{Binding Sex}" Margin="5"/> <TextBlock Text="{Binding Age}" Margin="5"/> </UniformGrid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Window>
cs:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Data;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 WPF_CH07_Demo01 { public partial class MainWindow : Window { public MainWindow () { InitializeComponent(); this .InitialData(); this .DataContext = this ; } public void InitialData () { this .StuListData = new DataTable(); this .StuListData.Columns.Add("Name" , typeof (string )); this .StuListData.Columns.Add("Sex" , typeof (string )); this .StuListData.Columns.Add("Age" , typeof (int )); DataRow row1 = this .StuListData.NewRow(); row1["Name" ] = "孙悟空" ; row1["Sex" ] = "男" ; row1["Age" ] = 18 ; DataRow row2 = this .StuListData.NewRow(); row2["Name" ] = "猪八戒" ; row2["Sex" ] = "男" ; row2["Age" ] = 19 ; DataRow row3 = this .StuListData.NewRow(); row3["Name" ] = "沙悟净" ; row3["Sex" ] = "男" ; row3["Age" ] = 20 ; this .StuListData.Rows.Add(row1); this .StuListData.Rows.Add(row2); this .StuListData.Rows.Add(row3); } public DataTable StuListData { get ; set ; } } }
绑定XML对象
xaml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Name="mainWindow" Title="MainWindow" Height="450" Width="800"> <StackPanel> <ListBox ItemsSource="{Binding Source={StaticResource PeopleData}}"> <ListBox.ItemTemplate> <DataTemplate> <UniformGrid Columns="2"> <TextBlock Width="200" Text="{Binding XPath='@Name'}"/> <TextBlock Width="200" Text="{Binding XPath='@Age'}"/> </UniformGrid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Window>
xml:
1 2 3 4 5 6 <?xml version="1.0" encoding="utf-8" ?> <People > <Person Name ="孙悟空" Age ="30" /> <Person Name ="猪八戒" Age ="25" /> <Person Name ="沙悟净" Age ="35" /> </People >
App.xaml:
1 2 3 4 5 6 7 8 9 10 <Application x:Class="WPF_CH07_Demo01.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WPF_CH07_Demo01" StartupUri="MainWindow.xaml"> <Application.Resources> <XmlDataProvider x:Key="PeopleData" XPath="People/Person" Source="data.xml"/> </Application.Resources> </Application>
WPF的5种绑定模式
OneWay(源变就更新目标属性)
TwoWay(源变就更新目标并且目标变就更新源)
OneTime(只根据源来设置目标,以后都不会变)
OneWayToSource(与OneWay相反)
Default(可以单向或双向,是靠被值定的源或目标是否有get或set来指定的)
xaml:
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 37 38 <Window x:Class="WPF_CH07_Demo01.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:WPF_CH07_Demo01" mc:Ignorable="d" Name="MainWindow1" Title="MainWindow" Height="450" Width="800"> <StackPanel> <Slider Name="sb1" Minimum="0" Maximum="100" Value="50" Width="300" Height=" 30" SmallChange="1"/> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="300"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" Content="OneWay"/> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ElementName=sb1,Path=Value,Mode=OneWay}"/> <Label Grid.Row="1" Grid.Column="0" Content="OneWayToSource"/> <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ElementName=sb1,Path=Value,Mode=OneWayToSource}"/> <Label Grid.Row="2" Grid.Column="0" Content="TwoWay"/> <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding ElementName=sb1,Path=Value,Mode=TwoWay}"/> <Label Grid.Row="3" Grid.Column="0" Content="OneTime"/> <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding ElementName=sb1,Path=Value,Mode=OneTime}"/> </Grid> </StackPanel> </Window>
课后作业 略