1.1绑定到对象

1.1.1、前台绑定

前台代码

  1. 5: </Grid>
  1. 1: <Grid x:Name=”GridProductDetails”>
  1. 2:  
  1. 3: <TextBox Grid.Column="1" x:Name="txtModelNum" Text="{ Binding Path=ModelNumber}"/>
  1. 4:  

对应后台代码

  1. 1: Model_Product BP = new BLL_Product().GetProduct(123);
  1. 2: GridProductDetails.DataContext = BP;

1.1.2、后台绑定

前台代码

  1. 1: <Grid x:Name=”GridProductDetails”>
  1. 2: <TextBox Grid.Column="1" x:Name="txtModelNum" />
  1. 3: </Grid>

对应后台代码

  1. 1: Binding B = new Binding();
  1. 2: B.Source=BP;
  1. 3: B.Path = new PropertyPath("ModelNumber");
  1. 4: txtModelNum.SetBinding(TextBox.TextProperty, B);

1.2 绑定到控件

有一列表框控件ListBox绑定到一个List<Product> 数据源,显示项为Product对象的ModelName属性,前台代码如下

  1. 1: <ListBox Name="lstProducts" Margin="5" DisplayMemberPath="ModelName"
  1. 2: SelectionChanged="lstProducts_SelectionChanged">
  1. 3: </ListBox>

对应后台代码为

  1. 1: private ICollection<Product> products;
  1. 2: products = App.StoreDb.GetProducts();
  1. 3: lstProducts.ItemsSource = products;

现在将一个Grid里面的一系列控件绑定到ListBox所选择的数据项上,用于构建“主--详细信息”的显示结构,代码如下

  1. 1: <Grid DataContext="{Binding ElementName=lstProducts, Path=SelectedItem}" TextBox.TextChanged="txt_TextChanged">
  1. 2: <TextBox Margin="5" Text="{Binding Path=ModelNumber}"></TextBox>
  1. 3: </Grid>

1.3 绑定的双向更新

1.3.1 对象和控件的双向更新

双向更新:即修改对象的属性值后,对应的前台控件自动更新为修改后的值。

前台无需做任何修改,只需在对象类Model定义的时候实现INotifyPropertyChanged接口即可:

  1. 1: public class Model_Product : INotifyPropertyChanged
  1. 2: {
  1. 3: string modelNumber;
  1. 4:  
  1. 5: public string ModelNumber
  1. 6: {
  1. 7: get { return modelNumber; }
  1. 8: set
  1. 9: {
  1. 10: modelNumber = value;
  1. 11: OnPropertyChanged(new PropertyChangedEventArgs("ModelNumber"));
  1. 12: }
  1. 13: }
  1. 14:  
  1. 15: int _ID;
  1. 16: public int ID
  1. 17: {
  1. 18: get { return _ID; }
  1. 19: set { _ID = value; }
  1. 20: }
  1. 21: /// <summary>
  1. 22: /// 实现INotifyPropertyChanged接口 可以实现控件值和对象属性值的自动绑定 当修改对象值后 控件的值自动刷新
  1. 23: /// </summary>
  1. 24: public event PropertyChangedEventHandler PropertyChanged;
  1. 25: public void OnPropertyChanged(PropertyChangedEventArgs e)
  1. 26: {
  1. 27: if (PropertyChanged != null)
  1. 28: PropertyChanged(this, e);
  1. 29: }
  1. 30: }
  1. 31:  
  1.  

1.3.2 绑定到对象集合(类似于List<T>)的双向更新

  1.  

双向更新:即修改对象的属性值后,对应的前台控件自动更新为修改后的值

无需些多少代码,只需把数据集合申明为实现了INotifyPropertyChanged接口的集合类型就可以了,在WPF中这个常用的有ObservableCollection<T>这个泛型集合类,如果是WindosForm编程,有个BindingList集合(实现了IBingdingList接口)

  1. 1: public ICollection<Product> GetProducts()
  1. 2: {
  1. 3: DataSet ds = StoreDbDataSet.ReadDataSet();
  1. 4:  
  1. 5: ObservableCollection<Product> products = new ObservableCollection<Product>();
  1. 6: foreach (DataRow productRow in ds.Tables["Products"].Rows)
  1. 7: {
  1. 8: products.Add(new Product((string)productRow["ModelNumber"],
  1. 9: (string)productRow["ModelName"], (decimal)productRow["UnitCost"],
  1. 10: (string)productRow["Description"], (int)productRow["CategoryID"],
  1. 11: (string)productRow["CategoryName"], (string)productRow["ProductImage"]));
  1. 12: }
  1. 13: return products;
  1. 14: }

1.4 绑定到ADO.NET数据集 DataSet

Controls.ItemsSource=DateSetObject.Tables[n].DefaultView;

需要注明Controls的DisplayMemberPath属性

删除数据集行建议采取的方法

((DataRowView)lstProducts.SelectedItem).Row.Delete();

1.5 绑定到LINQ集合

  1. 1: public ICollection<Product> GetProductsFilteredWithLinq(decimal minimumCost)
  1. 2: {
  1. 3: // Get the full list of products.
  1. 4: ICollection<Product> products = GetProducts();
  1. 5:  
  1. 6: // Create a second collection with matching products.
  1. 7: IEnumerable<Product> matches = from product in products
  1. 8: where product.UnitCost >= minimumCost
  1. 9: select product;
  1. 10:  
  1. 11: return new ObservableCollection<Product>(matches.ToList());
  1. 12: }

此处采用public ObservableCollection(List<T> list)实现对LINQ结果集的转换以实现双向更新:即修改对象的属性值后,对应的前台控件自动更新为修改后的值。

1.6 绑定验证

前台代码:

  1. 1: <Window x:Class="WPFGameTest.DataBinding.TestOfValidationRules"
  1. 2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  1. 3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  1. 4: Title="TestOfValidationRules" Height="300" Width="300">
  1. 5: <StackPanel >
  1. 6:
  1. 7: <TextBox x:Name="textBox1" Margin="5" />
  1. 8:
  1. 9: <Slider x:Name="slider1" Minimum="-10" Maximum="110" Margin="5" />
  1. 10:
  1. 11:  
  1. 12: </StackPanel>
  1. 13:  
  1. 14: </Window>

后台代码

  1. 1: using System;
  1. 2: using System.Collections.Generic;
  1. 3: using System.Linq;
  1. 4: using System.Text;
  1. 5: using System.Threading.Tasks;
  1. 6: using System.Windows;
  1. 7: using System.Windows.Controls;
  1. 8: using System.Windows.Data;
  1. 9: using System.Windows.Documents;
  1. 10: using System.Windows.Input;
  1. 11: using System.Windows.Media;
  1. 12: using System.Windows.Media.Imaging;
  1. 13: using System.Windows.Shapes;
  1. 14:  
  1. 15: namespace WPFGameTest.DataBinding
  1. 16: {
  1. 17: /// <summary>
  1. 18: /// TestOfValidationRules.xaml 的交互逻辑
  1. 19: /// </summary>
  1. 20: public partial class TestOfValidationRules : Window
  1. 21: {
  1. 22: public TestOfValidationRules()
  1. 23: {
  1. 24: InitializeComponent();
  1. 25:  
  1. 26: Binding binding = new Binding("Value")
  1. 27: {
  1. 28: Source = this.slider1
  1. 29: };
  1. 30:  
  1. 31: binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
  1. 32:
  1. 33: RangeValidateRule rvr = new RangeValidateRule();
  1. 34: rvr.ValidatesOnTargetUpdated = true;
  1. 35: binding.ValidationRules.Add(rvr);
  1. 36:  
  1. 37: binding.NotifyOnValidationError = true;
  1. 38: this.textBox1.SetBinding(TextBox.TextProperty, binding);
  1. 39:

this.textBox1.AddHandler(Validation.ErrorEvent,new RoutedEventHandler(this.ValidationError));

  1. 40:  
  1. 41: }
  1. 42: void ValidationError(object sender, RoutedEventArgs e)
  1. 43: {
  1. 44: Control C = sender as Control;
  1. 45:  
  1. 46: if (Validation.GetErrors(C).Count > 0)
  1. 47: {
  1. 48: (C).Background = new SolidColorBrush(Colors.Red);
  1. 49: C.ToolTip = Validation.GetErrors(C)[0].ErrorContent.ToString();
  1. 50: }
  1. 51: else
  1. 52: {
  1. 53: (C).Background = new SolidColorBrush(Colors.White);
  1. 54: C.ToolTip = null;
  1. 55: }
  1. 56:  
  1. 57: }
  1. 58:  
  1. 59: }
  1. 60: public class RangeValidateRule:ValidationRule
  1. 61: {
  1. 62: public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
  1. 63: {
  1. 64: double d = 0;
  1. 65: if (double.TryParse(value.ToString(),out d))
  1. 66: {
  1. 67: if(d >= 0 && d <= 100)
  1. 68: {
  1. 69: return new ValidationResult(true,null);
  1. 70: }
  1. 71: }
  1. 72:
  1. 73: return new ValidationResult(false,"Validation Failed !!!");
  1. 74: }
  1. 75: }
  1. 76:  
  1. 77: }

要点在第39行,为一个附加事件,关于附加事件可以参考http://msdn.microsoft.com/zh-cn/library/ms598899(v=VS.95).aspx

另外还有个衍生知识要点是“扩展方法”,这两个应该属于高级一点的编程特性,扩展方法请参照http://msdn.microsoft.com/zh-cn/library/vstudio/bb383977.aspx

1.6.1 注意e.Action == ValidationErrorEventAction.Removed

注意:在值一改变就验证的模式中,不可以用下面的代码方式来处理验证信息。因为当发生一个验证错误时,此时的xe.Action 值为 ValidationErrorEventAction.Added, 代码执行到第10行后跳出ValidationError方法。

此时系统会认为错误验证已经被处理,就会自动再次执行ValidationError,而此时的xe.Action 值为 ValidationErrorEventAction.Removed。

所以使用此方法用于验证,会出现看不到红色背景的效果。

MSDN是这样解释的:

如果发生验证错误,绑定引擎将引发 BindingValidationError 事件。 ValidationError  传递到包含一个新 Exception 的事件处理程序,且 Action 值为 Added。

如果该验证错误得到解决(极有可能是用户通过使用验证信息对项进行更新来解决的),则相同的 ValidationError 将传递到包含原始异常的事件处理程序,且 Action 值为 Removed。

http://msdn.microsoft.com/zh-cn/library/system.windows.controls.validationerroreventaction(v=vs.95).aspx

次验证方法适合于有提交按钮的情况,当点击提交按钮后执行下面的验证。

  1. 1: void ValidationError(object sender, RoutedEventArgs e)
  1. 2: {
  1. 3: Control C = sender as Control;
  1. 4: ValidationErrorEventArgs xe = e as ValidationErrorEventArgs;
  1. 5: if (xe.Action == ValidationErrorEventAction.Added )
  1. 6: {
  1. 7: if (Validation.GetErrors(C).Count > 0)
  1. 8: {
  1. 9: (C).Background = new SolidColorBrush(Colors.Red);
  1. 10: C.ToolTip = Validation.GetErrors(C)[0].ErrorContent.ToString();
  1. 11: }
  1. 12: }
  1. 13: if (xe.Action == ValidationErrorEventAction.Removed)
  1. 14: {
  1. 15: (C).Background = new SolidColorBrush(Colors.White);
  1. 16: }
  1. 17:  
  1. 18: }

1.6.2 使用绑定组来验证

  1. 1: GridProductDetails.DataContext = BP;
  1. 2: BindingGroup bin = new System.Windows.Data.BindingGroup();
  1. 3: bin.Name = "bb";
  1. 4: GridProductDetails.BindingGroup = bin;
  1. 5: GridProductDetails.BindingGroup.BeginEdit();
  1. 6:  
  1. 7:  
  1. 8: PositivePriceRule rule = new PositivePriceRule();
  1. 9: rule.Max = 300;
  1. 10:  
  1. 11:  
  1. 12: Binding B = new Binding();
  1. 13: B.Source = BP;
  1. 14: B.Path = new PropertyPath("ID");//
  1. 15: B.NotifyOnValidationError = true;
  1. 16: B.ValidatesOnExceptions = true;
  1. 17: B.Mode = BindingMode.TwoWay;
  1. 18: B.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
  1. 19: B.ValidationRules.Add(rule);
  1. 20:

B.BindingGroupName = bin.Name;

  1. 21:  
  1. 22: txtModelNum.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));
  1. 23: txtModelNum.SetBinding(TextBox.TextProperty, B);

关键的代码在第20行,通过指定Binding对象的BindingGroupName 属性来关联Binding对象到BindingGroup组里面。

此番修改以后,如果出现错误,使用BindingGroup的控件(第4行GridProductDetails.BindingGroup = bin)的边框就会变为红色。

WPF 数据绑定的更多相关文章

  1. WPF 数据绑定Binding

    什么是数据绑定? Windows Presentation Foundation (WPF) 数据绑定为应用程序提供了一种简单而一致的方法来显示数据以及与数据交互. 通过数据绑定,您可以对两个不同对象 ...

  2. WPF数据绑定Binding(二)

    WPF数据绑定Binding(二) 1.UI控件直接的数据绑定 UI对象间的绑定,也是最基本的形式,通常是将源对象Source的某个属性值绑定 (拷贝) 到目标对象Destination的某个属性上. ...

  3. WPF——数据绑定(一)什么是数据绑定

    注意:本人初学WPF,文中可能有表达或者技术性问题,欢迎指正!谢谢! 一:什么是数据绑定? “Windows Presentation Foundation (WPF) 数据绑定为应用程序提供了一种简 ...

  4. 剖析WPF数据绑定机制

    引言 WPF框架采取的是MVVM模式,也就是数据驱动UI,UI控件(Controls)被严格地限制在表示层内,不会参与业务逻辑的处理,只是通过数据绑定(Data Binding)简单忠实地表达与之绑定 ...

  5. WPF 10天修炼 第十天- WPF数据绑定

    WPF数据绑定 数据绑定到元素属性是将源对象指定为一个WPF元素,并且源属性是一个依赖属性,依赖属性内置了变更通知.当改变源对象依赖属性值之后,绑定目标可以立即得到更新,开发人员不需要手动编写响应事件 ...

  6. 微软原文翻译:适用于.Net Core的WPF数据绑定概述

    原文链接,大部分是机器翻译,仅做了小部分修改.英.中文对照,看不懂的看英文. Data binding overview in WPF 2019/09/19 Data binding in Windo ...

  7. C#-WPF数据绑定基础(一)

    前言:WPF数据绑定技术有效的提高了程序的容错率,可以最大程度的保持程序的健壮性,从而降低程序在使用过程中崩掉的可能性. 接下来,我将分享一下我在写测量程序过程中所用到的数据绑定方面的知识 首先,我所 ...

  8. C#WPF数据绑定模板化操作四步走

    前言:WPF数据绑定对于WPF应用程序来说尤为重要,本文将讲述使用MVVM模式进行数据绑定的四步走用法: 具体实例代码如下: 以下代码仅供参考,如有问题请在评论区留言,谢谢 1 第一步:声明一个类用来 ...

  9. WPF 数据绑定 1_1 基础知识&绑定到元素属性

    A.数据绑定基础: 数据源对象:WPF将从该对象中提取信息,交由目标对象进行显示. 目标对象:从数据源中提取信息,并赋给该对象的属性. B.绑定到元素属性 最简单的绑定情形则是将一个源对象指定为一个W ...

  10. WPF 数据绑定基础

    纯理论,可能会枯燥. .net 技术群: 199281001 ,欢迎加入. 1.目标对象一定是派生自DependencyObject的对象,并且目标属性必须是依赖属性,否则数据绑定操作将会失   败. ...

随机推荐

  1. Git工作常用

    工作时,最好每次都创建一个本地分支,这样就会减少错误修改远程代码的机会. 基于远程dev分支创建分支并切到本地分支: git checkout -b <local_dev> -t orig ...

  2. CSS 实现:文字水平垂直居中

    ☊ [实现要求]: <div class="demo1"> 标题1111 </div> √ [实现]: 方案一:普通布局 .demo1 { text-ali ...

  3. dede文章摘要字数的设置方法

    本文转自:http://blog.csdn.net/yxwmzouzou/article/details/17491991 在织梦系统中(针对5.7版本),文章摘要(可以通过以下四种相关标签调用)被设 ...

  4. 如何用cufflinks 拼出一个理想的注释文件

    后记: cufflinks安装: 下载安装包, 不要下载source code ,直接下载binary.    Source code    Linux x86_64 binary http://cu ...

  5. 关于C中scanf()函数读取字符串的问题

    #include <stdio.h> int main(void) { ]; scanf("%s", s_name); printf("Hello, %s!\ ...

  6. SQL注入测试平台 SQLol -6.CHALLENGES挑战

    SQLol上面的挑战共有14关,接下来我们一关一关来突破. Challenge 0 目的是让查询返回所有的用户名,而不是只有一个. SELECT username FROM users WHERE u ...

  7. Jquery_笔记

    1.请确保在 <body> 元素的onload事件中没有注册函数,否则不会触发+$(document).ready()事件.

  8. 什么是html5

    HTML5是用于取代1999年所制定的 HTML 4.01 和 XHTML 1.0 标准的 HTML 标准版本,现在仍处于发展阶段,但大部分浏览器已经支持某些 HTML5 技术.HTML 5有两大特点 ...

  9. Activity——思维导图

  10. NOI 银河英雄传说

    并查集水题,记录祖先,大小和深度即可,每次用祖先的大小和深度更新后代的深度. #include <cstdio> #include <iostream> #include &l ...