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 标记拓展

<Slider x:Name="slider" Maximum="100" Minimum="0"/>
<TextBlock x:Name="textBlock" Text="{Binding ElementName=slider, Path=Value}"/>
<!--Binding 构造器本身接收 Path 作为参数,因此-->
<TextBlock x:Name="textBlock" Text="{Binding Value, ElementName=slider}"/> //等价于后台:
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 事件;可以记录。

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

1.3 Binding 的路径 Path

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

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

1.4 没有路径的 Binding

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

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

1.5 没有 Source 的 Binding

1.5.1 无 Source 的 Binding

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

<Window ..>
<StackPanel>
<StackPanel.DataContext>
<local:Student Id="6" Age="20"/>
</StackPanel.DataContext>
<Grid>
<StackPanel>
<TextBlock Text="{Binding Id}" />
<TextBlock Text="{Binding Age}" />
</StackPanel>
</Grid>
</StackPanel>
</Window

1.5.2 无 Path 无 Source 的 Binding

<Window ..>
<StackPanel>
<StackPanel.DataContext>
<sys:String>Hello~</sys:String>
</StackPanel.DataContext>
<Grid>
<StackPanel>
<TextBlock Text="{Binding}" />
</StackPanel>
</Grid>
</StackPanel>
</Window

1.5.3 测试 DataContext 往下传递

<Grid>
<Grid.DataContext>
<local:Student Id="1000" Age="100"></local:Student>
</Grid.DataContext>
<StackPanel>
<StackPanel.DataContext>
<local:Stu Id="6" Play="ball"></local:Stu>
</StackPanel.DataContext>
<TextBlock Text="{Binding Id}"/>
<TextBlock Text="{Binding Play}"/>
<TextBlock Text="{Binding Age}"/>
</StackPanel>
</Grid>
// 6
// ball
// (空) 把 StackPanel 的 DataContext 去掉
// 1000
// (空)
// 100

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

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

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

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

<ListBox x:Name="listbox" DisplayMemberPath="Id" ItemsSource={Binding dataView}></ListBox>

<ListView x:Name="listview" ItemsSource={Binding dataView}>
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}" Width="100"/>
<GridViewColumn Header="CameraEncode" DisplayMemberBinding="{Binding CameraEncode}" Width="100"/>
<GridViewColumn Header="Pan" DisplayMemberBinding="{Binding Pan}" Width="100"/>
</GridView>
</ListView.View>
</ListView> DataView dataView {get;set;}//再添加更新通知。
System.Data.DataTable dt = this.Load();
dataView = dt.DefaultView;

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

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

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

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

这次提供 C# 版;

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

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

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

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

1.9.1 LINQ from List

<ListView x:Name="listViewStrs" Height="100" Margin="100">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" Width="60" DisplayMemberBinding="{Binding Id}" />
<GridViewColumn Header="Name" Width="60" DisplayMemberBinding="{Binding Name}" />
</GridView>
</ListView.View>
</ListView> ... List<Student> listStr = new List<Student>()
{
new Student() { Id = "11", Name = "YaoMing"},
new Student() { Id = "24", Name = "Kobe"},
new Student() { Id = "8", Name = "Kobe-Young"},
};
listViewStrs.ItemsSource = from str in listStr where str.Name.StartsWith("K") select str;

1.9.2 LINQ + XML

listbox.ItemsSource =
from element in xdoc.Descendants("Student")
where element.Attribute("Name").Value.StartsWith("T")
select new Student()
{
Id = int.Parse(element.Attribute("Id").Value),
Name = element.Attribute("Name").Value
};

1.9.3 LINQ + DataTable

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

1.10 使用 ObjectDataProvider 对象作为 Binding 的 Source

1.10.1 介绍一波 ObjectDataProvider

class Calculator
{
public string Add(string arg1, string arg2)
{
double x = 0;
double y = 0;
double z = 0; if (double.TryParse(arg1, out x) && double.TryParse(arg2, out y))
{
z = x + y;
return z.ToString();
} return "Input Error";
}
} ObjectDataProvider dp = new ObjectDataProvider();
dp.ObjectInstance = new Calculator();
dp.MethodName = "Add";
dp.MethodParameters.Add("10");
dp.MethodParameters.Add("15");
MessageBox.Show(dp.Data.ToString()); // 25

1.10.2 使用 ObjectDataProvider 作为 Binding 的 Source

<StackPanel Grid.Row="10">
<TextBox x:Name="textBlockArg1"/>
<TextBox x:Name="textBlockArg2"/>
<TextBox x:Name="textBlockResult"/>
</StackPanel> ObjectDataProvider dp = new ObjectDataProvider();
dp.ObjectInstance = new Calculator();
dp.MethodName = "Add";
dp.MethodParameters.Add("0");
dp.MethodParameters.Add("0"); Binding bindingToArg1 = new Binding("MethodParameters[0]")
{
Source = dp,
BindsDirectlyToSource = true,//告诉Binding对象只负责把从UI得到的数据写入Source(odp)而不是写入odp对象包装的Calculator对象中,默认 false
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
}; Binding bindingToArg2 = new Binding("MethodParameters[1]")
{
Source = dp,
BindsDirectlyToSource = true,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
}; Binding bindingToResult = new Binding(".") { Source = dp }; this.textBlockArg1.SetBinding(TextBox.TextProperty, bindingToArg1);
this.textBlockArg2.SetBinding(TextBox.TextProperty, bindingToArg2);
this.textBlockResult.SetBinding(TextBox.TextProperty, bindingToResult);

1.11 使用 Binding 的 RelativeSource

<Grid x:Name="g3">
<Grid x:Name="g2">
<Grid x:Name="g1">
<StackPanel x:Name="s2">
<StackPanel x:Name="s1">
<TextBox x:Name="textBlock1"/>
<TextBox x:Name="textBlock2"/>
<TextBox x:Name="textBlock3"/>
<TextBox x:Name="textBlock4"/>
<TextBox x:Name="textBlock5" Text="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1,AncestorType={x:Type StackPanel}}}"/>
<TextBox x:Name="textBlock6" Text="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=2,AncestorType={x:Type StackPanel}}}"/>
<TextBox x:Name="textBlock7" Text="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=3,AncestorType={x:Type Grid}}}"/>
<TextBox x:Name="textBlock8" Text="{Binding Name, RelativeSource={RelativeSource Mode=Self}}"/>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
</Grid>
RelativeSource rs = new RelativeSource();
rs.AncestorLevel = 1;
rs.AncestorType = typeof(StackPanel);
Binding binding = new Binding("Name") { RelativeSource = rs }; this.textBlock1.SetBinding(TextBox.TextProperty, binding); RelativeSource rs2 = new RelativeSource();
rs2.AncestorLevel = 2;
rs2.AncestorType = typeof(StackPanel);
Binding binding2 = new Binding("Name") { RelativeSource = rs2 }; this.textBlock2.SetBinding(TextBox.TextProperty, binding2); RelativeSource rs3 = new RelativeSource();
rs3.AncestorLevel = 3;
rs3.AncestorType = typeof(Grid);
Binding binding3 = new Binding("Name") { RelativeSource = rs3 }; this.textBlock3.SetBinding(TextBox.TextProperty, binding3); RelativeSource rs4 = new RelativeSource();
rs4.Mode = RelativeSourceMode.Self;
Binding binding4 = new Binding("Name") { RelativeSource = rs4}; this.textBlock4.SetBinding(TextBox.TextProperty, binding4); // s1
// s2
// g3
// textblock4
// s1
// s2
// g3
// textblock8

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

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

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

public static RelativeSource TemplatedParent
{
get
{
if (s_templatedParent == null)
{
s_templatedParent = new RelativeSource(RelativeSourceMode.TemplatedParent);
}
return s_templatedParent;
}
}

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. ElasticSearch 集群 & 数据备份 & 优化

    ElasticSearch 集群相关概念 ES 集群颜色状态 ①. - 红色:数据都不完整 ②. - 黄色:数据完整,但是副本有问题 ③. - 绿色:数据和副本全都没有问题 ES 集群节点类型 ①. ...

  2. java-GUI编程学习总结

    狂神说java-GUI编程学习总结 1.简介 2.AWT 2.1.实现如图1-2 (1)面向过程写法 (2)内部类写法 (3)完全改造成面向对象 3.Swing 3.1.鼠标花点 3.2.弹窗 3.3 ...

  3. Java 并发机制底层实现 —— volatile 原理、synchronize 锁优化机制

    本书部分摘自<Java 并发编程的艺术> 概述 相信大家都很熟悉如何使用 Java 编写处理并发的代码,也知道 Java 代码在编译后变成 Class 字节码,字节码被类加载器加载到 JV ...

  4. ReactDOM API All In One

    ReactDOM API All In One React DOM API render() hydrate() unmountComponentAtNode() findDOMNode() crea ...

  5. HTML form All In One

    HTML form All In One action + method onsubmit, submit event action + method <form action="&q ...

  6. D3 tree map

    D3 tree map D3 矩形树图 https://www.zhihu.com/question/55529379 https://zhuanlan.zhihu.com/p/57873460 ht ...

  7. 封装 React Native 原生组件(iOS / Android)

    封装 React Native 原生组件(iOS / Android) 在 React Native中,有很多种丰富的组件了,例如 ScrollView.FlatList.SectionList.Bu ...

  8. USDN稳定币应用区块链旅游业

    比特币是区块链1.0时代的标志性产品,稳定币则是区块链2.0时代的标志性产品.在稳定币鼻祖USDT爆出"超发"新闻后曾引发市场的动荡,之后新兴稳定币如春笋般涌现.据不完全同济,目前 ...

  9. uniapp 自定义弹窗组件

    先上效果: 组件源码:slot-modal.vue <template> <view class="modal-container" v-if="sho ...

  10. Bitter.NotifyOpenPaltform : HTTP 异步消息接收调度中心&mdash;开源贡献 之 一:简介

    现在互联网的系统越来越趋向于复杂,从单体系统到现在的微服务体系演变.公司与公司的分工也越来越明确. 大数据公司提供了大数据服务 人脸识别公司提供了人脸识别服务 OCR 公司提供了专业的OCR 服务 车 ...