上一篇我们将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的Text
 TextBox1.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入门教程系列二十三——DataGrid示例(三)

    DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...

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

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

  4. WPF入门教程系列二——Application介绍

    一.Application介绍 WPF和WinForm 很相似, WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只 ...

  5. WPF入门教程系列(二) 深入剖析WPF Binding的使用方法

    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...

  6. WPF入门教程系列(一) 创建你的第一个WPF项目

    WPF入门教程系列(一) 创建你的第一个WPF项目 WPF基础知识 快速学习绝不是从零学起的,良好的基础是快速入手的关键,下面先为大家摞列以下自己总结的学习WPF的几点基础知识: 1) C#基础语法知 ...

  7. WPF入门教程系列一

    WPF入门教程 一.  前言  公司项目基于WPF开发,最近项目上线有点空闲时间写一篇基于wpf的基础教材,WPF也是近期才接触,学习WPF也是在网上查资料与微软的MSDN进行学习,写本博客的目为了温 ...

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

    原文:WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush) 前面我们提到了LinearGradientBrush可以用来画渐变填充图,那么我们同时也可以使用ImageBr ...

  9. WPF入门(四)->线形区域Path内容填充之渐变色(LinearGradientBrush)

    原文:WPF入门(四)->线形区域Path内容填充之渐变色(LinearGradientBrush) 前面我们介绍到,Path对象表示一个用直线或者曲线连接的图形,我们可以使用Path.Data ...

随机推荐

  1. 15个关于Chrome的开发必备小技巧[译]

    谷歌Chrome,是当前最流行且被众多web开发人员使用的浏览器.最快六周就更新发布一次以及伴随着它不断强大的开发组件,使得Chrome成为你必备的开发工具.例如,在线编辑CSS,console以及d ...

  2. GJM : C#设计模式汇总整理——导航 【原创】

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  3. 我的屌丝giser成长记-工作篇之B公司

    从A公司跳槽到B公司,岗位还是webgis开发方向,但是具体实现的技术完全变了,从flex转换js,这也是我要离开A公司的最重要的原意之一:A公司的arcgis for flex框架采用了flexvi ...

  4. Android 微信第三方登录(个人笔记)

    今天在写微信登录,花了半天时间搞定.然后写下自己的笔记,希望帮助更多的人...欢迎各位指教. 微信授权登录,官方说的不是很清楚.所以导致有一部分的坑. 微信注册应用平台的应用签名,下载 微信签名生成工 ...

  5. Git 学习看这篇就够了!

    Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理. 可能新手会问"git和github有什么关系啊?" git是一个版本控制工具: githu ...

  6. HA 高可用软件系统保养指南

    又过了一年 618,六月是公司一年一度的大促月,一般提前一个月各系统就会减少需求和功能的开发,转而更多去关注系统可用性.稳定性和管控性等方面的非功能需求.大促前的准备工作一般叫作「备战」,可以把线上运 ...

  7. FineReport关于tomcat集群部署的方案

    多台服务器集群后,配置权限.数据连接.模板.定时调度等,只能每台服务器一个个配置,不会自动同步到所有服务器. 针对上述情况,在FineReport中提供新集群部署插件,将xml配置文件.finedb/ ...

  8. 写个Fragment方便的抽象基类 BaseFragment

    package com.zb.zhihuianyang.base; import android.app.Activity; import android.os.Bundle; import andr ...

  9. C#中一些常用的加密和哈希处理

    URL编码,默认UTF8编码方式 /// <summary> /// URL编码,默认UTF8编码方式 /// </summary> /// <param name=&q ...

  10. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...