上一篇我们将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. [原创]java使用JDBC向MySQL数据库批次插入10W条数据测试效率

    使用JDBC连接MySQL数据库进行数据插入的时候,特别是大批量数据连续插入(100000),如何提高效率呢?在JDBC编程接口中Statement 有两个方法特别值得注意:通过使用addBatch( ...

  2. PHP设计模式(二)工厂方法模式(Factory Method For PHP)

    简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...

  3. atitit.管理学三大定律:彼得原理、墨菲定律、帕金森定律

    atitit.管理学三大定律:彼得原理.墨菲定律.帕金森定律 彼得原理(The Peter Principle) 1 彼得原理解决方案1 帕金森定律 2 如何理解墨菲定律2 彼得原理(The Pete ...

  4. 图解Spark API

    初识spark,需要对其API有熟悉的了解才能方便开发上层应用.本文用图形的方式直观表达相关API的工作特点,并提供了解新的API接口使用的方法.例子代码全部使用python实现. 1. 数据源准备 ...

  5. Linux基础介绍【第三篇】

    更改SSH服务端远程登录的配置 windows服务端的默认远程管理端口是3389,管理员用户是administrator,普通用户是guest.Linux的管理用户是root,普通用户默认有很多个,远 ...

  6. ERROR 1300 (HY000): Invalid utf8 character string: ''

    在load csv 进mysql的时候,报这个错,苦恼了很长时间,网上搜索不到答案. mysql>    load data infile '/home/hdh/8_sr/8_45.csv'   ...

  7. Openstack Periodic Task

    Openstack Periodic Task 周期性任务在各个模块的manager.py(computer,scheduler,cell,network)中添加. 添加方法:在模块manager类实 ...

  8. osi(open system interconnection)模型的通俗理解

    OSI模型的理解: 以你和你女朋友以书信的方式进行通信为例. 1.物理层:运输工具,比如火车.汽车. 2.数据链路层:相当于货物核对单,表明里面有些什么东西,接受的时候确认一下是否正确(CRC检验). ...

  9. D3.js学习(六)

    上节我们学习了如何绘制多条曲线, 以及给不同的曲线指定不同的坐标系.在这节当中,我们会对坐标轴标签相关的处理进行学习.首先,我们来想一个问题, 如何我们的x轴上的各个标签的距离比较近,但是标签名又比较 ...

  10. Linux下部署ASP.NET服务连接oracle遇到的问题记录

    一.如何卸载MONO Q:mono是linux系统上跨平台软件,卸载它有两种方式: 1.知道mono安装路径,安装原来的路径直接覆盖安装(最为简单): 2.不知道mono安装路径,首先通过sudo f ...