原文:WPF入门:数据绑定

上一篇我们将XAML大概做了个了解 ,这篇将继续学习WPF数据绑定的相关内容

数据源与控件的Binding

Binding作为数据传送UI的通道,通过INotityPropertyChanged接口的PropertyChanged事件通知Binding数据属性发生改变

  public class Product : INotifyPropertyChanged{private string name;public string Name{get { return name; }set{name = value;if (PropertyChanged != null){this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));}}}public event PropertyChangedEventHandler PropertyChanged;}

通过Binding关联UI控件元素

   this.txtOfProduct.SetBinding(TextBox.TextProperty, new Binding() { Path = new PropertyPath("Name"), Source = p });

控件之间的Binding

 <TextBox x:Name="TextBox1" Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}"></TextBox><Slider x:Name="slider1" Margin="5"></Slider>


我们也可以通过后台C#代码实现

 TextBox1.SetBinding(TextBox.TextProperty, new Binding("Value") { ElementName = "slider1", Mode=BindingMode.OneWay });

统计文本字符长度

 <TextBox x:Name="TextBox1"  Margin="5"  TextWrapping="Wrap" ></TextBox><TextBlock Margin="5"  TextAlignment="Right" Text="{Binding ElementName=TextBox1, Path=Text.Length}"></TextBlock>

Binding的Path

Path的索引器方式

  <TextBox x:Name="TextBox1"  Margin="5"  TextWrapping="Wrap" ></TextBox><!--获取Text的第三个字符--><TextBlock Margin="5"  TextAlignment="Right" Text="{Binding ElementName=TextBox1, Path=Text.[2]}"></TextBlock><TextBlock Margin="5"  TextAlignment="Right" Text="{Binding ElementName=TextBox1, Path=Text[2]}"></TextBlock>

当使用一个集合或者DataView作为Binding源时,如果我们想把它的默认元素作为Path来使用

 List<string> names = new List<string>() { "张三", "李四", "王五" };//张三this.TextBox1.SetBinding(TextBox.TextProperty, new Binding("/") { Source = names });//“张三”字符串的长度this.TextBox2.SetBinding(TextBox.TextProperty, new Binding("/Length") { Source = names,Mode=BindingMode.OneWay});//获取“张三”字符串中的第1个字符this.TextBox3.SetBinding(TextBox.TextProperty, new Binding("/[0]") { Source = names, Mode = BindingMode.OneWay });

如果集合中嵌套集合,我们依然可以通过多级"/"语法把子集作为Path的元素

  class City{public string Name { get; set; }}class Province{public List<City> Citys { get; set; }public string Name { get; set; }}class Country{public List<Province> Provinces { get; set; }public string Name { get; set; }}
  TextBox1.SetBinding(TextBox.TextProperty, new Binding("/Name") { Source = countries });TextBox2.SetBinding(TextBox.TextProperty, new Binding("/Provinces/Name") { Source = countries });TextBox3.SetBinding(TextBox.TextProperty, new Binding("/Provinces/Citys/Name") { Source = countries });

省略Path

sys需要引用xmlns:sys="clr-namespace:System;assembly=mscorlib"

 <StackPanel.Resources><sys:String x:Key="text">WPF入门手册</sys:String></StackPanel.Resources><TextBox x:Name="TextBox1"  Margin="5" Text="{Binding .,Source={StaticResource ResourceKey=text}}" ></TextBox>
TextBox2.SetBinding(TextBox.TextProperty, new Binding(".") { Source = "WPF技术入门" });

没有Path和Source,Binding可以通过DataContext获取数据

 <StackPanel.DataContext><sys:String>WPF入门手册</sys:String></StackPanel.DataContext><TextBox x:Name="TextBox1"  Margin="5" Text="{Binding Mode=OneWay}" ></TextBox>

选中ListBox元素显示对应的属性的一个例子

 <TextBox x:Name="TextBox1"  Margin="5" ></TextBox><ListBox x:Name="ListBox1"></ListBox>
  List<City> cities = new List<City>() {new City() { Id=1,Name="北京" },new City() { Id=2,Name="昆明" },new City() { Id=3,Name="上海" },new City() { Id=4,Name="厦门" },new City() { Id=5,Name="广州" }};this.ListBox1.ItemsSource = cities;this.ListBox1.DisplayMemberPath = "Name";this.TextBox1.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = this.ListBox1 });

使用Binding的RelativeSource

Binding有明确的数据源的时,我们可以通过SoureElementName赋值办法关联Binding,但有事我们不知道Soure对象的名字是什么,却知道它与作为Binding目标对象的UI元素布局上的相对关系,通过RelativeSourceMode枚举设置关联的对象关系

<Grid x:Name="g1"><StackPanel x:Name="s1"><DockPanel x:Name="d1"><TextBox x:Name="TextBox1"  Margin="5" ></TextBox></DockPanel></StackPanel>
</Grid>

后台代码处理

 RelativeSource rs = new RelativeSource(RelativeSourceMode.FindAncestor){AncestorLevel = 1,AncestorType = typeof(StackPanel)};//将StackPanel的Name s1赋给了TextBox1的TextTextBox1.SetBinding(TextBox.TextProperty, new Binding("Name") { RelativeSource = rs });

也可以通过XAML的方式赋值

    <Grid x:Name="g1"><StackPanel x:Name="s1"><DockPanel x:Name="d1"><TextBox x:Name="TextBox1"  Margin="5" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type DockPanel},AncestorLevel=1,Mode=FindAncestor}, Path=Name}" ></TextBox></DockPanel></StackPanel></Grid>

Binding数据验证

BindingValidationRules属性的类型为Collection<ValidationRule>。通过实现Validate方法返回给ValidationResult对象,并设置IsVaild属性,ErrorContent属性可以接受一个字符串。

 public class RangValidationRule : ValidationRule{//验证数据public override ValidationResult Validate(object value, CultureInfo cultureInfo){double d = 0;if (double.TryParse(value.ToString(), out d)){if (d >= 1 && d <= 100){return new ValidationResult(true, null);}}return new ValidationResult(false, "数据错误");}}
 <TextBox x:Name="TextBox1" Margin="5"></TextBox><Slider x:Name="slider1" Minimum="1" Maximum="100" Margin="5"></Slider>
 Binding binding = new Binding("Value") {Source=slider1,UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged,};binding.ValidationRules.Add(new RangValidationRule());this.TextBox1.SetBinding(TextBox.TextProperty, binding);

显示错误提示

  public MainWindow(){InitializeComponent();Binding binding = new Binding("Value"){Source = slider1,UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,NotifyOnValidationError = true//开启错误通知};binding.ValidationRules.Add(new RangValidationRule());this.TextBox1.SetBinding(TextBox.TextProperty, binding);//注册验证错误事件this.TextBox1.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(ValidationErrorNotify));}private void ValidationErrorNotify(object sender, RoutedEventArgs e){var errors = Validation.GetErrors(this.TextBox1);if (errors.Count > 0){TextBlock1.Text = errors[0].ErrorContent.ToString();}}

多路Binding

一般我们在做注册用户功能的时候,输入密码的时候都需要再确认输入密码,比较两次输入是否一致,现在我们可以通过多路Binding来简单的实现这个功能
首先实现一个IMultiValueConverter接口功能,如果两次密码一致,提交按钮状态为可用

    public class SubmitMultiBindingConverter : IMultiValueConverter{public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture){return (!values.Cast<string>().Any(a => string.IsNullOrEmpty(a))/*验证所有元素非空*/ &&values[0].ToString() == values[1].ToString())/*值1=值2*/;}public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture){throw new NotImplementedException();}}

XAML代码

 <TextBox x:Name="Password" Margin="5"></TextBox><TextBox x:Name="Passworder" Margin="5"></TextBox><Button x:Name="Submit" Content="提交" Margin="10" Height="30" Width="100"></Button>

后台Binding

 Binding pwdBinding = new Binding("Text") { Source = Password };Binding pwderBinding = new Binding("Text") { Source = Passworder };MultiBinding multi = new MultiBinding() { Mode=BindingMode.OneWay};multi.Bindings.Add(pwdBinding);multi.Bindings.Add(pwderBinding);multi.Converter = new SubmitMultiBindingConverter();Submit.SetBinding(Button.IsEnabledProperty, multi);


以上就是Binding常用到的功能,下篇我将继续学习依赖属性和WPF路由事件的相关内容

WPF入门:数据绑定相关推荐

  1. WPF入门教程系列十五——WPF中的数据绑定(一)

    使用Windows Presentation Foundation (WPF) 可以很方便的设计出强大的用户界面,同时 WPF提供了数据绑定功能.WPF的数据绑定跟Winform与ASP.NET中的数 ...

  2. WPF入门教程系列四——Dispatcher介绍

    WPF入门教程系列四--Dispatcher介绍 一.Dispatcher介绍 微软在WPF引入了Dispatcher,那么这个Dispatcher的主要作用是什么呢? 不管是WinForm应用程序还 ...

  3. WPF入门0:WPF的基础知识

    WPF入门0:WPF的基础知识 WPF 可创建动态的数据驱动的呈现系统. 系统的每一部分均可通过驱动行为的属性集来创建对象. 数据绑定是系统的基础部分,在每一层中均进行了集成. 传统的应用程序创建一个 ...

  4. WPF入门学习----系列基础教程

    WPF入门教程系列目录 WPF入门教程系列二--Application介绍 WPF入门教程系列三--Application介绍(续) WPF入门教程系列四--Dispatcher介绍 WPF入门教程系 ...

  5. WPF入门(三)-几何图形之不规则图形(PathGeometry) (2)

    WPF入门(三)->几何图形之不规则图形(PathGeometry) (2) 原文:WPF入门(三)->几何图形之不规则图形(PathGeometry) (2) 上一节我们介绍了PathG ...

  6. WPF入门教程-转载

    最近为了做炫酷的UI,了解了WPF,之前一直是使用winform的,界面也是古老的不行. 在园里找到了一个大佬以前写的教程,备注一下.按照系列教程走下来,可以直接上手了. 备忘传送门>>& ...

  7. WPF入门(四)-线形区域Path内容填充之填充图(ImageBrush)

    WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush) 原文:WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush) 前面我们提到了Linear ...

  8. WPF入门教程(七)---依赖属性(3)(转)

    WPF入门教程(七)---依赖属性(3) 2018年08月24日 08:33:43 weixin_38029882 阅读数:50 四. 只读依赖属性 在以前在对于非WPF的功能来说,对于类的属性的封装 ...

  9. WPF入门教程系列三——Application介绍(续)

    接上文WPF入门教程系列二--Application介绍,我们继续来学习Application 三.WPF应用程序的关闭 WPF应用程序的关闭只有在应用程序的 Shutdown 方法被调用时,应用程序 ...

最新文章

  1. 互联网公司java面试题(一)
  2. 如何把两个域控同步_同步带噪音大,怎么办?
  3. Linux下遍历目录下的文件
  4. jquery-选择器
  5. PHP判断PHP版本是否及格
  6. Spring框架jar包分类(转)
  7. android 判断服务是否活动,Android:我如何获得当前的前台活动(从服务)?
  8. 天池NLP文本分类比赛如何轻松轻松获得Top K的秘诀!
  9. 尼尔森十大可用性原则
  10. fetch_lfw_people相关
  11. Shufflenet解读
  12. DoNet6新特性 Enumerable.Chunk()
  13. 谷歌关键字推广操作技巧
  14. Skype 8.34 Windows7-64bit Ubuntu 16.04安装试验
  15. word中如何插入制表符
  16. sklearn包使用Extra-Trees和GridSearchCV完成成人死亡率预测
  17. 算法题--字符串排列组合、n皇后、字符出现次数(C++)
  18. 机器学习笔记 - 单位矩阵和逆矩阵
  19. NUISTOJ/P1285 达朗贝尔的台阶
  20. 如何理解高内聚,低耦合

热门文章

  1. oracle 登录rman,Oracle 学习之RMAN(二)由此开始
  2. 自动驾驶技术的终局,可能将无限期推迟来到
  3. 性能堪比GPT-3,但参数量仅为0.1%,LMU团队推出NLP最强文本生成模型
  4. 五步构建AI应用实战框架
  5. 2020上半年收集到的优质AI文章 – AI+和+AI
  6. SAP S/4 HANA的物料编码40位设置
  7. 学界 | 和清华大学自然语言处理与社会人文计算实验室一起读机器翻译论文
  8. 干货丨一文介绍机器学习中基本的数学符号
  9. 干货丨不确定性原理——人工智能的哲学基础
  10. 演讲实录丨中科大陈小平教授《从封闭性到非封闭性:2020到2035年智能机器的机遇和挑战》...