1. 源与路径

  1. 把控件作为 binding 源与 binding 标记拓展;
  2. 控制 Binding 的方向及数据更新;
  3. Binding 的路径 Path;
  4. 没有路径的 Binding;
  5. 为 Binding 指定源的几种方法;
  6. 没有 Source 的 Binding;
  7. 使用集合对象作为列表控件的 ItemsSource;
  8. 使用 ADO.NET 对象作为 Binding 的源;
  9. 使用 XML 的数据作为 Binding 的源;
  10. 使用 LINQ 的检索结果作为 Binding 的源:
  11. 使用 ObjectDataProvider 对象作为 Binding 的 Source;
  12. 使用 Binding 的 RelativeSource;

Binding 作为数据的桥梁,两端分别是源 (Source) 和目标 (Target),同时 Target 作为对象可能会有多个属性值,通过 路径 (Path) 指定通过 Binding 送达 UI 元素的属性;

source:可以为集合对象、ADO.NET 对象、XML 数据、LINQ 检索结果、ObjectDataProvider 对象等;

1.1 把控件作为 binding 源与 binding 标记拓展

  1. <Slider x:Name="slider" Maximum="100" Minimum="0"/>
  2. <TextBlock x:Name="textBlock" Text="{Binding ElementName=slider, Path=Value}"/>
  3. <!--Binding 构造器本身接收 Path 作为参数,因此-->
  4. <TextBlock x:Name="textBlock" Text="{Binding Value, ElementName=slider}"/>
  5. //等价于后台:
  6. this.textBlock.SetBinding(TextBlock.TextProperty, new Binding("Value") { ElementName = "slider" });

1.2 控制 Binding 的方向及数据更新

Binding 的属性 Mode 的枚举值决定 Binding 的更新方向:

  • OneWay
  • OneWayToSource
  • OneTime
  • TwoWay
  • Default :不同控件的默认值不一样,比如文本框和复选框默认双向绑定,TextBlock 单向

Binding 的属性 UpdateSourceTrigger 的枚举值决定 Binding 的触发数据更新的条件:

  • Explicit :调用 System.Windows.Data.BindingExpression.UpdateSource 方法时才更新
  • PropertyChanged
  • LostFocus
  • Default : 大多数默认值是 PropertyChanged,而 System.Windows.Controls.TextBox.Text 是 LostFocus

NotifyOnSourceUpdated、NotifyOnTargetUpdated bool值

当值从绑定目标传输到绑定源时是否引发 System.Windows.Data.Binding.SourceUpdated 事件;

当值从绑定源传输到绑定目标时是否引发 System.Windows.Data.Binding.TargetUpdated 事件。

如下面例子:修改 slider 的值,引发 TargetUpdated 事件;

修改 textBox 的值,引发 SourceUpdated 事件;可以记录。

  1. <TextBox x:Name="textBlox"
  2. TargetUpdated="textBlock_TargetUpdated"
  3. SourceUpdated="textBlock_SourceUpdated"
  4. Text="{Binding Path=Value, ElementName=slider, UpdateSourceTrigger=PropertyChanged,
  5. NotifyOnSourceUpdated=True,
  6. NotifyOnTargetUpdated=True}"/>

1.3 Binding 的路径 Path

除了上面所说,还支持多级路径

  1. <TextBox x:Name="textBox2" Text="{Binding Path=Text.Length, ElementName=textBox, Mode=OneWay}"/>
  2. //等价于:
  3. this.textBox2.SetBinding(TextBox.TextProperty, new Binding("Text.Length") { Source = this.textBox, Mode = BindingMode.OneWay });
  4. <TextBox x:Name="textBox2" Text="{Binding Path=Text.[3], ElementName=textBox, Mode=OneWay}"/>
  5. List<string> stringList = new List<string>() { "Bob", "Long" };
  6. this.xx1.SetBinding(TextBox.TextProperty, new Binding("/") { Source = stringList });//Bob
  7. this.xx2.SetBinding(TextBox.TextProperty, new Binding("/Length") { Source = stringList, Mode = BindingMode.OneWay });//3
  8. this.xx3.SetBinding(TextBox.TextProperty, new Binding("/[2]") { Source = stringList, Mode = BindingMode.OneWay });//b

1.4 没有路径的 Binding

比如 int,string 等本身就是数据,因此用 Path=. 来表示,在 xaml 中可以省略,在 C# 中不能省略

  1. <Window.Resources>
  2. <sys:String x:Key="myString">悟空的小脾气</sys:String>
  3. </Window.Resources>
  4. <TextBlock Text="{Binding Path=., Source={StaticResource myString}}"/>
  5. <TextBlock Text="{Binding ., Source={StaticResource myString}}"/>
  6. <TextBlock Text="{Binding Source={StaticResource myString}}"/>
  7. <TextBlock x:Name="knowNull"/>
  8. this.knowNull.SetBinding(TextBlock.TextProperty, new Binding(".") { Source = this.FindResource("myString")});
  9. // 4 个 TextBlock 都展示 "悟空的小脾气"

1.5 没有 Source 的 Binding

1.5.1 无 Source 的 Binding

当一个 Binding 只知道自己的 Path,而不知自己的 Source 时,会沿着 UI 元素树一层一层树的根部找过去,直到找到有设置 DataContext 的元素。

  1. <Window ..>
  2. <StackPanel>
  3. <StackPanel.DataContext>
  4. <local:Student Id="6" Age="20"/>
  5. </StackPanel.DataContext>
  6. <Grid>
  7. <StackPanel>
  8. <TextBlock Text="{Binding Id}" />
  9. <TextBlock Text="{Binding Age}" />
  10. </StackPanel>
  11. </Grid>
  12. </StackPanel>
  13. </Window

1.5.2 无 Path 无 Source 的 Binding

  1. <Window ..>
  2. <StackPanel>
  3. <StackPanel.DataContext>
  4. <sys:String>Hello~</sys:String>
  5. </StackPanel.DataContext>
  6. <Grid>
  7. <StackPanel>
  8. <TextBlock Text="{Binding}" />
  9. </StackPanel>
  10. </Grid>
  11. </StackPanel>
  12. </Window

1.5.3 测试 DataContext 往下传递

  1. <Grid>
  2. <Grid.DataContext>
  3. <local:Student Id="1000" Age="100"></local:Student>
  4. </Grid.DataContext>
  5. <StackPanel>
  6. <StackPanel.DataContext>
  7. <local:Stu Id="6" Play="ball"></local:Stu>
  8. </StackPanel.DataContext>
  9. <TextBlock Text="{Binding Id}"/>
  10. <TextBlock Text="{Binding Play}"/>
  11. <TextBlock Text="{Binding Age}"/>
  12. </StackPanel>
  13. </Grid>
  14. // 6
  15. // ball
  16. // (空)
  17. 把 StackPanel 的 DataContext 去掉
  18. // 1000
  19. // (空)
  20. // 100

1.6 使用集合对象作为列表控件的 ItemsSource

  • 当我们没有为 ListBox 的 ItemTemplate 指定 DataTemplate 时,

    ListBox 在获得 ItemsSource 后会创建等量的 ListBoxItem 并自动设置 DataTemplate。
  • 在获取 DataTemplate 的过程中会以 DisplayMemberPath 属性值作为 Path 创建 Binding。
  • Binding 的目标是 ListBoxItem 的内容插件(TextBox)

1.7 使用 ADO.NET 对象作为 Binding 的源

  1. <ListBox x:Name="listbox" DisplayMemberPath="Id" ItemsSource={Binding dataView}></ListBox>
  2. <ListView x:Name="listview" ItemsSource={Binding dataView}>
  3. <ListView.View>
  4. <GridView>
  5. <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}" Width="100"/>
  6. <GridViewColumn Header="CameraEncode" DisplayMemberBinding="{Binding CameraEncode}" Width="100"/>
  7. <GridViewColumn Header="Pan" DisplayMemberBinding="{Binding Pan}" Width="100"/>
  8. </GridView>
  9. </ListView.View>
  10. </ListView>
  11. DataView dataView {get;set;}//再添加更新通知。
  12. System.Data.DataTable dt = this.Load();
  13. dataView = dt.DefaultView;

并不能展示数据,但行数是正确的。

1.8 使用 XML 的数据作为 Binding 的源

前面提 x:XData 时有实现过一次 ListBox 绑定到 XmlDataProvider 的方式;

  1. <ListBox x:Name="listbox" Grid.Row="5" I
  2. temsSource="{Binding Source={StaticResource XMlData}, XPath=/Super/Colors/Color}"/>

这次提供 C# 版;

  1. XmlDataProvider xdp = new XmlDataProvider();
  2. xdp.Source = new Uri(@"D:\RawData.xml");
  3. xdp.XPath = @"/StudentList/Student";
  4. this.listbox.DataContext = xdp;
  5. this.listbox.SetBinding(ListView.ItemsSourceProperty, new Binding());

设置 XmlDataProvider.Source 的效果等同于 XmlDataProvider.Document:

  1. xdp.Source = new Uri(@"D:\RawData.xml");
  2. =
  3. System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
  4. doc.Load(@"D:\RawData.xml");
  5. xdp.Document = doc;

1.9 使用 LINQ 的检索结果作为 Binding 的源

1.9.1 LINQ from List

  1. <ListView x:Name="listViewStrs" Height="100" Margin="100">
  2. <ListView.View>
  3. <GridView>
  4. <GridViewColumn Header="Id" Width="60" DisplayMemberBinding="{Binding Id}" />
  5. <GridViewColumn Header="Name" Width="60" DisplayMemberBinding="{Binding Name}" />
  6. </GridView>
  7. </ListView.View>
  8. </ListView>
  9. ...
  10. List<Student> listStr = new List<Student>()
  11. {
  12. new Student() { Id = "11", Name = "YaoMing"},
  13. new Student() { Id = "24", Name = "Kobe"},
  14. new Student() { Id = "8", Name = "Kobe-Young"},
  15. };
  16. listViewStrs.ItemsSource = from str in listStr where str.Name.StartsWith("K") select str;

1.9.2 LINQ + XML

  1. listbox.ItemsSource =
  2. from element in xdoc.Descendants("Student")
  3. where element.Attribute("Name").Value.StartsWith("T")
  4. select new Student()
  5. {
  6. Id = int.Parse(element.Attribute("Id").Value),
  7. Name = element.Attribute("Name").Value
  8. };

1.9.3 LINQ + DataTable

  1. listbox.ItemsSource =
  2. from row in dt.Row.Cast<DataRow>()
  3. where Convert.ToString(row["Name"]).StartsWith("T")
  4. select new Student()
  5. {
  6. Id = int.Parse(row["Id"].ToString()),
  7. Name = row["Name"].ToString()
  8. };

1.10 使用 ObjectDataProvider 对象作为 Binding 的 Source

1.10.1 介绍一波 ObjectDataProvider

  1. class Calculator
  2. {
  3. public string Add(string arg1, string arg2)
  4. {
  5. double x = 0;
  6. double y = 0;
  7. double z = 0;
  8. if (double.TryParse(arg1, out x) && double.TryParse(arg2, out y))
  9. {
  10. z = x + y;
  11. return z.ToString();
  12. }
  13. return "Input Error";
  14. }
  15. }
  16. ObjectDataProvider dp = new ObjectDataProvider();
  17. dp.ObjectInstance = new Calculator();
  18. dp.MethodName = "Add";
  19. dp.MethodParameters.Add("10");
  20. dp.MethodParameters.Add("15");
  21. MessageBox.Show(dp.Data.ToString()); // 25

1.10.2 使用 ObjectDataProvider 作为 Binding 的 Source

  1. <StackPanel Grid.Row="10">
  2. <TextBox x:Name="textBlockArg1"/>
  3. <TextBox x:Name="textBlockArg2"/>
  4. <TextBox x:Name="textBlockResult"/>
  5. </StackPanel>
  6. ObjectDataProvider dp = new ObjectDataProvider();
  7. dp.ObjectInstance = new Calculator();
  8. dp.MethodName = "Add";
  9. dp.MethodParameters.Add("0");
  10. dp.MethodParameters.Add("0");
  11. Binding bindingToArg1 = new Binding("MethodParameters[0]")
  12. {
  13. Source = dp,
  14. BindsDirectlyToSource = true,//告诉Binding对象只负责把从UI得到的数据写入Source(odp)而不是写入odp对象包装的Calculator对象中,默认 false
  15. UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
  16. };
  17. Binding bindingToArg2 = new Binding("MethodParameters[1]")
  18. {
  19. Source = dp,
  20. BindsDirectlyToSource = true,
  21. UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
  22. };
  23. Binding bindingToResult = new Binding(".") { Source = dp };
  24. this.textBlockArg1.SetBinding(TextBox.TextProperty, bindingToArg1);
  25. this.textBlockArg2.SetBinding(TextBox.TextProperty, bindingToArg2);
  26. this.textBlockResult.SetBinding(TextBox.TextProperty, bindingToResult);

1.11 使用 Binding 的 RelativeSource

  1. <Grid x:Name="g3">
  2. <Grid x:Name="g2">
  3. <Grid x:Name="g1">
  4. <StackPanel x:Name="s2">
  5. <StackPanel x:Name="s1">
  6. <TextBox x:Name="textBlock1"/>
  7. <TextBox x:Name="textBlock2"/>
  8. <TextBox x:Name="textBlock3"/>
  9. <TextBox x:Name="textBlock4"/>
  10. <TextBox x:Name="textBlock5" Text="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1,AncestorType={x:Type StackPanel}}}"/>
  11. <TextBox x:Name="textBlock6" Text="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=2,AncestorType={x:Type StackPanel}}}"/>
  12. <TextBox x:Name="textBlock7" Text="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=3,AncestorType={x:Type Grid}}}"/>
  13. <TextBox x:Name="textBlock8" Text="{Binding Name, RelativeSource={RelativeSource Mode=Self}}"/>
  14. </StackPanel>
  15. </StackPanel>
  16. </Grid>
  17. </Grid>
  18. </Grid>
  1. RelativeSource rs = new RelativeSource();
  2. rs.AncestorLevel = 1;
  3. rs.AncestorType = typeof(StackPanel);
  4. Binding binding = new Binding("Name") { RelativeSource = rs };
  5. this.textBlock1.SetBinding(TextBox.TextProperty, binding);
  6. RelativeSource rs2 = new RelativeSource();
  7. rs2.AncestorLevel = 2;
  8. rs2.AncestorType = typeof(StackPanel);
  9. Binding binding2 = new Binding("Name") { RelativeSource = rs2 };
  10. this.textBlock2.SetBinding(TextBox.TextProperty, binding2);
  11. RelativeSource rs3 = new RelativeSource();
  12. rs3.AncestorLevel = 3;
  13. rs3.AncestorType = typeof(Grid);
  14. Binding binding3 = new Binding("Name") { RelativeSource = rs3 };
  15. this.textBlock3.SetBinding(TextBox.TextProperty, binding3);
  16. RelativeSource rs4 = new RelativeSource();
  17. rs4.Mode = RelativeSourceMode.Self;
  18. Binding binding4 = new Binding("Name") { RelativeSource = rs4};
  19. this.textBlock4.SetBinding(TextBox.TextProperty, binding4);
  20. // s1
  21. // s2
  22. // g3
  23. // textblock4
  24. // s1
  25. // s2
  26. // g3
  27. // textblock8

从 textBlock3.Text 展示的是 "g3",可以看出 RelativeSource.AncestorLevel 表示从自身开始,往根结点方向找父节点,找第 x 个 AncestorType 的元素;

如果是找自身,就用 RelativeSource.Mode = RelativeSourceMode.Self;

RelativeSource 有三个静态属性:PreviousData、Self、TemplateParent,分别对应 RelativeSourceMode 的三个同名称的枚举值,在 DataTemplate 中常用到,通过 ILSpy 可以看到源代码:

  1. public static RelativeSource TemplatedParent
  2. {
  3. get
  4. {
  5. if (s_templatedParent == null)
  6. {
  7. s_templatedParent = new RelativeSource(RelativeSourceMode.TemplatedParent);
  8. }
  9. return s_templatedParent;
  10. }
  11. }

WPF 基础 - Binding 的源与路径的更多相关文章

  1. 深入浅出-Binding的源与路径

    1.把控件作为Binding源与Binding标记扩展<TextBox x:Name="textBox1" Text="{Binding Path=Value, E ...

  2. Binding的源与路径

    1.把控件作为Binding的源 例子:拖动Slider,输入框中的值也会跟着改变,或在输入框中输入数值,滑动条也会自动移动 <Window x:Class="把控件作为Binding ...

  3. WPF基础篇之资源文件路径

    WPF资源文件的路径 关于WPF资源文件的路径 这几天在WPF中调用资源文件的Uri时,因为是在代码里调用Uri写的Uri总是不对,要么运行直接报异常,要么说找不到资源文件.下面是我解决的整个经过和碰 ...

  4. WPF 基础 - Binding 对数据的转换和校验

    1. Binding 对数据的转换和校验 Binding 中,有检验和转换关卡. 1.1 数据校验 源码: namespace System.Windows.Data { public class B ...

  5. WPF 基础 - Binding 的 数据更新提醒

    WPF 作为一个专门的展示层技术,让程序员专注于逻辑层,让展示层永远处于逻辑层的从属地位: 这主要因为有 DataBinding 和配套的 Dependency Property 和 DataTemp ...

  6. WPF之Binding深入探讨

    原文:http://blog.csdn.net/fwj380891124/article/details/8107646 1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在 ...

  7. WPF的Binding功能解析

    1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...

  8. WPF之Binding深入探讨--Darren

    1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...

  9. WPF之Binding【转】

    WPF之Binding[转] 看到WPF如此之炫,也想用用,可是一点也不会呀. 从需求谈起吧: 首先可能要做一个很炫的界面.见MaterialDesignInXAMLToolKit. 那,最主要的呢, ...

随机推荐

  1. kubernetes实战-配置中心(四)分环境使用apollo配置中心

    要进行分环境,需要将现有实验环境进行拆分 portal服务,可以各个环境共用,但是apollo-adminservice和apollo-configservice必须要分开. 1.zk环境拆分为tes ...

  2. Leetcode(15)-三数之和

    给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...

  3. 可重入锁ReentrantLock解析

    说到可重入锁,先从AQS的ConditionObject说起,AQS的内部类ConditionObject是构建显示锁条件队列的基础.之前AQS的解析没有说这个内部类,这里和ReentrantLock ...

  4. CNN可视化技术总结(四)--可视化工具与项目

    CNN可视化技术总结(一)-特征图可视化 CNN可视化技术总结(二)--卷积核可视化 CNN可视化技术总结(三)--类可视化 导言: 前面介绍了可视化的三种方法--特征图可视化,卷积核可视化,类可视化 ...

  5. Apple 产品反人类的设计 All In One

    Apple 产品反人类的设计 All In One 用户体验 shit rank WTF rank iPhone 更换铃声 WTF, 这么简单的一个功能搞得太复杂了 使用要下载 1.6 G的库乐队 A ...

  6. js 十大排序算法 All In One

    js 十大排序算法 All In One 快速排序 归并排序 选择排序 插入排序 冒泡排序 希尔排序 桶排序 堆排序(二叉树排序) 基数排序 计数排序 堆排序(二叉树排序) https://www.c ...

  7. 在线可视化设计网站 & 在线编辑器

    在线可视化设计网站 在线编辑器:海报编辑器.H5 编辑器.视频编辑器.音频编辑器.抠图编辑器 在线 拖拽 可视化 编辑器 Canvas WebGL Canva With Canva, anyone c ...

  8. JavaScript 设计模式: 发布者-订阅者模式

    JavaScript 设计模式: 发布者-订阅者模式 发布者-订阅者模式 https://github.com/Kelichao/javascript.basics/issues/22 https:/ ...

  9. 十三香 & 香料

    十三香 & 香料 十三香原料组成不完全一致, 但有一些香料却是大家都会采用的: 草蔻.砂仁.肉豆蔻.肉桂.丁香. 花椒.大料.小茴香.木香.白芷. 山萘.良姜和姜 王守义十三香 http:// ...

  10. GitHub Actions & GitHub Secrets

    GitHub Actions & GitHub Secrets tokens & private variable GitHub Secrets https://github.com/ ...