在webform中,如果提到“绑定”二字,相信大家都不会陌生,绑定,让我们的代码更加的简洁优美,在wpf中也存在各种神马的绑定,
当然使用上都是行隔理不隔。
一: 控件到控件的绑定
既然是绑定,那么肯定就有”源对象“和”目标对象“两种状态实体,从图的角度上来说存在三种状态:
确实在wpf中存在这三种模式的对应方式,
1:OneWay
正如图A所说,Source影响着Target,但是Target却影响不到Source。
2:OneWayToSource
也正如图B中所表述的一样,Target影响Source,而Source却影响不到Target。
3:TwoWay
这个也就相当于无向图的边,Source与Target相互影响。
4:OneTime
在OneWay的基础上延伸了一个OneTime,仅绑定一次。如果大家属性Jquery中的one函数我想就可以不用表述了。
1 <Window x:Class="WpfApplication1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="MainWindow" Height="350" Width="525"> 5 <Canvas> 6 <ScrollBar Height="24" Name="scrollBar1" Width="237" Orientation="Horizontal" Canvas.Left="103" Canvas.Top="51" Minimum="1" Maximum="100" SmallChange="1" /> 7 <Label Canvas.Left="41" Canvas.Top="121" Content="OneWay" Height="28" Name="label1" /> 8 <TextBox Canvas.Left="165" Canvas.Top="121" Height="23" 9 Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneWay}"10 Name="textBox1" Width="120" />11 <Label Canvas.Left="41" Canvas.Top="160" Content="OneWayToSource" Height="28" Name="label2" />12 <TextBox Canvas.Left="165" Canvas.Top="160" Height="23"13 Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneWayToSource}"14 Name="textBox2" Width="120" />15 <Label Canvas.Left="41" Canvas.Top="202" Content="TwoWay" Height="28" Name="label3" />16 <TextBox Canvas.Left="165" Canvas.Top="202" Height="23"17 Text="{Binding ElementName=scrollBar1, Path=Value, Mode=TwoWay}"18 Name="textBox3" Width="120" />19 <Label Canvas.Left="41" Canvas.Top="231" Content="OneTime" Height="28" Name="label4" />20 <TextBox Canvas.Left="165" Canvas.Top="231" Height="23" 21 Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneTime}"22 Name="textBox4" Width="120" />23 </Canvas>24 </Window>
最终的结果,还是大家自己拖拖滚动条吧,有图有真相。
二:.net对象与控件的绑定
这种绑定还是经常使用的,在WebForm中我们常用的Eval就是此种绑定,因为俺从数据库里好不容易捞了点数据总要呈现在UI上面吧,
好,不多说,上代码说话。
1 <Window x:Class="WpfApplication3.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:local="clr-namespace:WpfApplication3" 5 Title="MainWindow" Height="350" Width="525"> 6 <Grid> 7 <ListView Height="287" HorizontalAlignment="Left" Margin="62,12,0,0" Name="listView1" VerticalAlignment="Top" Width="331"> 8 <ListView.View> 9 <GridView>10 <GridView.Columns>11 <GridViewColumn Header="姓名" DisplayMemberBinding="{Binding Name}"/>12 <GridViewColumn Header="年龄" DisplayMemberBinding="{Binding Age}"/>13 </GridView.Columns>14 </GridView>15 </ListView.View>16 </ListView>17 </Grid>18 </Window>
首先谢天谢地,我们的数据出来了,好,现在我们有需求了,我现在需要给奇偶行填充不同底色,并且age=22的这行数据标红,那在wpf中该
怎么做呢?我们依稀的记得在webform中我们会在“行事件”上做手脚,在数据的绑定上wpf给我们提供了一个口子,也就是在绑定时可以插入自
己的”事件处理代码“,但必须要继承自IValueConverter。
1 <Window x:Class="WpfApplication3.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:local="clr-namespace:WpfApplication3" 5 Title="MainWindow" Height="350" Width="525"> 6 <Window.Resources> 7 <local:ColorConvert x:Key="myConvert"/> 8 <Style x:Key="item" TargetType="{x:Type ListViewItem}"> 9 <Setter Property="Background">10 <Setter.Value>11 <Binding RelativeSource="{RelativeSource Self}" 12 Converter="{StaticResource myConvert}"/>13 </Setter.Value>14 </Setter>15 </Style>16 </Window.Resources>17 <Grid>18 <ListView ItemContainerStyle="{StaticResource ResourceKey=item}" Height="287" HorizontalAlignment="Left" Margin="62,12,0,0" Name="listView1" VerticalAlignment="Top" Width="331">19 <ListView.View>20 <GridView>21 <GridView.Columns>22 <GridViewColumn Header="姓名" DisplayMemberBinding="{Binding Name}"/>23 <GridViewColumn Header="年龄" DisplayMemberBinding="{Binding Age}"/>24 </GridView.Columns>25 </GridView>26 </ListView.View>27 </ListView>28 </Grid>29 </Window>
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input;10 using System.Windows.Media;11 using System.Windows.Media.Imaging;12 using System.Windows.Navigation;13 using System.Windows.Shapes;14 15 namespace WpfApplication316 {17 /// <summary>18 /// MainWindow.xaml 的交互逻辑19 /// </summary>20 public partial class MainWindow : Window21 {22 public MainWindow()23 {24 InitializeComponent();25 26 List<Student> list = new List<Student>();27 28 for (int i = 20; i < 30; i++)29 {30 list.Add(new Student() { Name = "hxc" + i, Age = i });31 }32 33 listView1.ItemsSource = list;34 }35 }36 37 public class ColorConvert : IValueConverter38 {39 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)40 {41 //这里的value既为当前的行对象42 var item = value as ListViewItem;43 44 //获取当前的item在当前的Listview中的位置45 var view = ItemsControl.ItemsControlFromItemContainer(item) as ListView;46 47 var index = view.ItemContainerGenerator.IndexFromContainer(item);48 49 //当Age=22是红色标示50 if ((view.Items[index] as Student).Age ==22)51 return Brushes.Red;52 53 if (index % 2 == 0)54 return Brushes.Pink;55 else56 return Brushes.Blue;57 }58 59 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)60 {61 return null;62 }63 }64 65 66 public class Student67 {68 public string Name { get; set; }69 70 public int Age { get; set; }71 }72 }
快看,效果出来了,这里要稍微解释下IValueConverter的使用步骤:
①:自定义一个类继承自IValueConverter,其中Convert方法的value 为绑定参数,parameter参数为绑定参数的附带值。
1 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
②:我们需要在xaml中引用并写入资源。
1 <Window.Resources> 2 <local:ColorConvert x:Key="myConvert"/> 3 <Style x:Key="item" TargetType="{x:Type ListViewItem}"> 4 <Setter Property="Background"> 5 <Setter.Value> 6 <Binding RelativeSource="{RelativeSource Self}" 7 Converter="{StaticResource myConvert}"/> 8 </Setter.Value> 9 </Setter>10 </Style>11 </Window.Resources>
③:最后也就是在Binding中使用Convert,wpf在绑定数据的时候会自动调用我们自定义的myConvert方法。
1 <Window.Resources> 2 <local:ColorConvert x:Key="myConvert"/> 3 <Style x:Key="item" TargetType="{x:Type ListViewItem}"> 4 <Setter Property="Background"> 5 <Setter.Value> 6 <Binding RelativeSource="{RelativeSource Self}" 7 Converter="{StaticResource myConvert}"/> 8 </Setter.Value> 9 </Setter>10 </Style>11 </Window.Resources>
三: .net方法与控件的绑定
在做wpf时,有时我们需要在xaml中绑定.net中的方法,当然这在实际开发中也是很常用的,不过方法必要由ObjectDataProvider来封装。
1 <Window x:Class="WpfApplication5.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:local="clr-namespace:WpfApplication5" 5 xmlns:sys="clr-namespace:System;assembly=mscorlib" 6 Title="MainWindow" Height="350" Width="525"> 7 <Window.Resources> 8 <ObjectDataProvider x:Key="Test" ObjectType="{x:Type local:Student}" MethodName="GetName"> 9 </ObjectDataProvider>10 </Window.Resources>11 <Grid>12 <TextBlock Text="{Binding Source={StaticResource ResourceKey=Test}, Mode=OneWay}"/>13 </Grid>14 </Window>
1 namespace WpfApplication5 2 { 3 /// <summary> 4 /// MainWindow.xaml 的交互逻辑 5 /// </summary> 6 public partial class MainWindow : Window 7 { 8 public MainWindow() 9 {10 InitializeComponent();11 }12 }13 14 public class Student15 {16 //前台要引用的方法17 public string GetName()18 {19 return "一线码农";20 }21 }22 }
四:wpf中的验证
我们知道不管在什么体系架构中都有属于自己的一套验证体系,比如webform中的验证控件,mvc中的特性验证,当然wpf也是有的,为了
验证的灵活性,实际开发中我们用的比较多的还是”自定义验证“,其实只需要实现ValidationRule接口就行了,然后写上自定义的验证逻辑。
1 <Window x:Class="WpfApplication4.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:local="clr-namespace:WpfApplication4" 5 Title="MainWindow" Height="350" Width="525"> 6 <Window.Resources> 7 <local:Student x:Key="student"/> 8 </Window.Resources> 9 <Grid>10 <TextBlock Height="23" HorizontalAlignment="Left" Margin="97,54,0,0" Name="textBlock1" Text="姓名" VerticalAlignment="Top" />11 <TextBox DataContext="{StaticResource ResourceKey=student}" Height="23" HorizontalAlignment="Left" Margin="153,54,0,0" Name="textBox1" VerticalAlignment="Top" Width="120">12 <TextBox.Text>13 <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">14 <!-- 自定义的验证规格,当然可以是多个Check -->15 <Binding.ValidationRules>16 <local:NameCheck />17 </Binding.ValidationRules>18 </Binding>19 </TextBox.Text>20 <TextBox.ToolTip>21 <!--将当前的错误信息显示在tooltip上-->22 <Binding RelativeSource="{RelativeSource Self}" Path="(Validation.Errors)[0].ErrorContent"/>23 </TextBox.ToolTip>24 </TextBox>25 </Grid>26 </Window>
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input;10 using System.Windows.Media;11 using System.Windows.Media.Imaging;12 using System.Windows.Navigation;13 using System.Windows.Shapes;14 15 namespace WpfApplication416 {17 /// <summary>18 /// MainWindow.xaml 的交互逻辑19 /// </summary>20 public partial class MainWindow : Window21 {22 public MainWindow()23 {24 InitializeComponent();25 }26 }27 28 public class NameCheck : ValidationRule29 {30 public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)31 {32 var name = Convert.ToString(value);33 34 //如果名字长度大于4则是非法35 if (name.Length > 4)36 return new ValidationResult(false, "名字长度不能大于4个长度!");37 38 return ValidationResult.ValidResult;39 }40 }41 42 public class Student43 {44 public string Name { get; set; }45 46 public int Age { get; set; }47 }48 }
同样这里也需要注意的就是:
① 实现ValidationRule接口,重写Validate方法,其中的逻辑,你懂的。
1 public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
② 然后我们在需要验证的控件上追加Rule验证, 其中的UpdateSourceTrigger设定为字段改变时触发,当然可选值有很多...
1 <TextBox.Text>2 <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">3 <!-- 自定义的验证规格,当然可以是多个Check -->4 <Binding.ValidationRules>5 <local:NameCheck />6 </Binding.ValidationRules>7 </Binding>8 </TextBox.Text>
③ 最后要将实体写入到验证控件的DataContext上,最后大功告成。
1 <TextBox DataContext="{StaticResource ResourceKey=student}" Height="23" HorizontalAlignment="Left" Margin="153,54,0,0" Name="textBox1" VerticalAlignment="Top" Width="120">