如何使用 StaticResources、DynamicResources 相互绑定属性,尽管您可以找到有关 RelativeSource 及其用例的信息,但即使在 Microsoft 文档中也没有更多详细信息。在本文中,我将公开 WPF 中 RelativeSources 的用例。

当我们尝试将给定对象的属性绑定到对象本身的另一个属性时,当我们尝试将对象的属性绑定到其相对父对象的另一个属性时,RelativeSource 是一种标记扩展,用于特定的绑定情况,在自定义控件开发的情况下以及最后在使用一系列绑定数据的差异的情况下将依赖属性值绑定到一段 XAML 时。所有这些情况都表示为相对源模式。我将一一揭露所有这些情况。

1. Mode Self:

想象一下这种情况,我们希望它的高度总是等于它的宽度的矩形,比如说一个正方形。我们可以使用元素名称

<Rectangle Fill="Red" Name="rectangle"Height="100" Stroke="Black"Canvas.Top="100" Canvas.Left="100"Width="{Binding ElementName=rectangle,Path=Height}"/>

但在上面的例子中,我们必须指出绑定对象的名称,即矩形。我们可以使用RelativeSource以不同的方式达到相同的目的

<Rectangle Fill="Red" Height="100"Stroke="Black"Width="{Binding RelativeSource={RelativeSource Self},Path=Height}"/>

在这种情况下,我们没有义务提及绑定对象的名称,并且当高度发生改变时,Width总是等于Height。如果希望将Width参数设置为高度的一半,则可以通过向Binding标记扩展添加转换器来实现。

现在让我们想象另一个例子:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},Path=Parent.ActualWidth}"/>

上面的例子用于将一个给定元素的一个给定属性绑定到它的一个直接父元素上,因为这个元素拥有一个名为parent的属性。这将我们引向另一个相对源模式,也就是find祖先模式。

2. Mode FindAncestor

在本例中,给定元素的一个属性将被绑定到它的父元素之一,当然。与上述情况的主要区别在于,由您决定祖先类型和祖先在层次结构中的等级来绑定属性。顺便说一下,试着玩一下这个XAML

<Canvas Name="Parent0"><Border Name="Parent1"Width="{Binding RelativeSource={RelativeSource Self},Path=Parent.ActualWidth}"Height="{Binding RelativeSource={RelativeSource Self},Path=Parent.ActualHeight}"><Canvas Name="Parent2"><Border Name="Parent3"Width="{Binding RelativeSource={RelativeSource Self},Path=Parent.ActualWidth}"Height="{Binding RelativeSource={RelativeSource Self},Path=Parent.ActualHeight}"><Canvas Name="Parent4"><TextBlock FontSize="16"Margin="5" Text="Display the name of the ancestor"/><TextBlock FontSize="16"Margin="50"Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Border},AncestorLevel=2},Path=Name}"Width="200"/></Canvas></Border></Canvas></Border></Canvas>

上面的情况是两个TextBlock元素,它们被嵌入在一系列的边框和画布元素中,这些元素代表它们的分层父元素。第二个TextBlock将在相对源级别显示给定父类的名称。

因此尝试将 AncestorLevel=2 更改为 AncestorLevel=1 看看会发生什么。然后尝试更改类型从 AncestorType=Border 到 AncestorType=Canvas 的祖先,看看会发生什么。

3. TemplatedParent

此模式允许将给定的 ControlTemplate 属性绑定到应用 ControlTemplate 的控件的属性。为了更好地理解这里的问题,下面是一个示例

<Window.Resources><ControlTemplate x:Key="template"><Canvas><Canvas.RenderTransform><RotateTransform Angle="20"/></Canvas.RenderTransform><Ellipse Height="100" Width="150"Fill="{BindingRelativeSource={RelativeSource TemplatedParent},Path=Background}"></Ellipse><ContentPresenter Margin="35"Content="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"/></Canvas></ControlTemplate></Window.Resources><Canvas Name="Parent0"><Button   Margin="50"Template="{StaticResource template}" Height="0"Canvas.Left="0" Canvas.Top="0" Width="0"><TextBlock FontSize="22">Click me</TextBlock></Button></Canvas>

如果我想应用给定控件的属性到它的控件模板,那么我可以使用TemplatedParent模式。也有类似的一个标记扩展的TemplateBinding是一种短手的第一个,但TemplateBinding是在编译时进行的对比TemplatedParent评估就是在第一次运行时。如下图所示,背景和内容从按钮内应用到控件模板。

4. PreviousData

这是RelativeSource中最模糊和使用较少的模式,我指的是PreviousData模式。PreviousData用于特定的情况。它的目的是通过一个特定的赋值将给定的属性绑定到另一个属性;我的意思是它把属性的前一个值赋给了有界值。换句话说,如果您有一个具有文本属性的TextBox和另一个具有保存数据的value属性的控件。假设这个值实际上是5,之前是3。3赋值给TextBox的text属性,而不是5。这导致了这样一种想法,即这种RelativeSource经常用于items控件。

为了理解RelativeSource现象,让我们公开这个示例。我将添加一个ItemsControl到场景中,我将从一个自定义集合中删除它

<Grid><ItemsControl></ItemsControl>
</Grid>

这个ItemsControl使用这个集合来填充:

public class Items : ObservableCollection<Item>{public Items(){Add(new Item { Value = 80.23 });Add(new Item { Value = 126.17 });Add(new Item { Value = 130.21 });Add(new Item { Value = 115.28 });Add(new Item { Value = 131.21 });Add(new Item { Value = 135.22 });Add(new Item { Value = 120.27 });Add(new Item { Value = 110.25 });Add(new Item { Value = 90.20 });}}

它是我开发的Item类型的ObservableCollection,它保存一个简单的属性Value,它的类型是double。

 public class Item :INotifyPropertyChanged{private double _value;public double Value{get { return _value; }set { _value = value; OnPropertyChanged("Value"); }}#region INotifyPropertyChanged Memberspublic event PropertyChangedEventHandler PropertyChanged;#endregionprotected void OnPropertyChanged(string PropertyName){if (null != PropertyChanged){PropertyChanged(this,new PropertyChangedEventArgs(PropertyName));}}}

现在,为了将ItemsControl绑定到集合数据,我将在window构造函数级别将整个窗口的DataContext属性设置为集合。

public Window1()
{
InitializeComponent();
this.DataContext = new Items();
}

然后我将指定ItemsControl的绑定

ItemsControlItemsSource="{Binding}"Margin="10"

结果是这样的。

因此,我们必须应用一些特性来增强该表示的视觉效果。

<ItemsControl ItemsSource="{Binding}" Margin="10"><ItemsControl.ItemsPanel><ItemsPanelTemplate><StackPanel Orientation="Horizontal"/></ItemsPanelTemplate></ItemsControl.ItemsPanel><ItemsControl.ItemTemplate><DataTemplate><StackPanel><Border CornerRadius="3" BorderThickness="3"Width="80" Height="{Binding Value}"Margin="0,0,35,0" BorderBrush="Violet" Background="BlueViolet"><TextBlock Text="{Binding Value}"FontWeight="bold"VerticalAlignment="Center"HorizontalAlignment="Center" Foreground="Wheat"><TextBlock.RenderTransform><TransformGroup><ScaleTransform ScaleY="-1"/></TransformGroup></TextBlock.RenderTransform></TextBlock></Border></StackPanel></DataTemplate></ItemsControl.ItemTemplate><ItemsControl.RenderTransform><TransformGroup><ScaleTransform ScaleY="-1"/><TranslateTransform Y="250"/></TransformGroup></ItemsControl.RenderTransform></ItemsControl>

简单地说,我将描述上面的XAML。首先,ItemsPanel将在水平StackPanel中安排项目,其次,使用DataTemplate将数据表示为边界;边框高度被绑定到项目类的Value,以反映集合保存的Value。同样的边框包括一个TextBlock,它显示Item对象的Value。

演示结果如下

现在,主要目的这个demo就是为了展示RelativeSource.PreviousData模式的特点。

这个想法包括添加一个 TextBox 并将 Text 属性绑定到项目列表中前一个边框的值。看起来像下面这样的东西

你可以注意到,每个 TextBlock 代表前一个项目所持有的前一个值。这其实就是RelativeSource模式的PreviousData的神奇之处。

想法是将 TextBlock 添加到 DataTemplate 为 Follow

<TextBlock FontSize="14" FontWeight="bold" Margin="20"Text="{Binding RelativeSource={RelativeSource PreviousData},Path=Value}"><TextBlock.RenderTransform><ScaleTransform ScaleY="-1"/></TextBlock.RenderTransform>
</TextBlock>

那么整个就会这样的

<Grid><ItemsControl ItemsSource="{Binding}" Margin="10"><ItemsControl.RenderTransform><TransformGroup><ScaleTransform ScaleY="-1"/><TranslateTransform Y="250"/></TransformGroup></ItemsControl.RenderTransform><ItemsControl.ItemsPanel><ItemsPanelTemplate><StackPanel Orientation="Horizontal"/></ItemsPanelTemplate></ItemsControl.ItemsPanel><ItemsControl.ItemTemplate><DataTemplate><StackPanel><TextBlock FontSize="14" FontWeight="bold"Margin="20"Text="{BindingRelativeSource={RelativeSource PreviousData},Path=Value}"><TextBlock.RenderTransform><ScaleTransform ScaleY="-1"/></TextBlock.RenderTransform>   </TextBlock><Border CornerRadius="3" BorderThickness="3"Width="80" Height="{Binding Value}"Margin="0,0,35,0" BorderBrush="Violet" Background="BlueViolet"><TextBlock Text="{Binding Value}"FontWeight="bold" VerticalAlignment="Center"HorizontalAlignment="Center"Foreground="Wheat"><TextBlock.RenderTransform><TransformGroup><ScaleTransform ScaleY="-1"/></TransformGroup></TextBlock.RenderTransform></TextBlock></Border></StackPanel></DataTemplate></ItemsControl.ItemTemplate></ItemsControl>
</Grid>

WPF 入门教程RelativeSources相关推荐

  1. WPF入门教程-转载

    最近为了做炫酷的UI,了解了WPF,之前一直是使用winform的,界面也是古老的不行. 在园里找到了一个大佬以前写的教程,备注一下.按照系列教程走下来,可以直接上手了. 备忘传送门>>& ...

  2. WPF入门教程(七)---依赖属性(3)(转)

    WPF入门教程(七)---依赖属性(3) 2018年08月24日 08:33:43 weixin_38029882 阅读数:50 四. 只读依赖属性 在以前在对于非WPF的功能来说,对于类的属性的封装 ...

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

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

  4. WPF入门教程系列四——Dispatcher介绍

    WPF入门教程系列四--Dispatcher介绍 一.Dispatcher介绍 微软在WPF引入了Dispatcher,那么这个Dispatcher的主要作用是什么呢? 不管是WinForm应用程序还 ...

  5. WPF 入门教程(一)

    WPF 入门教程(一) 1.布局规则 1.WPF 窗体中,一个窗体只能持有一个空间,当需要展示多个控件时,则需要首先设置一个容器控件(Container).控件的布局有容器来决定. 2.控件应避免明确 ...

  6. WPF入门教程教学(转载)

    WPF入门教程(1)-基础 https://blog.csdn.net/weixin_38029882/article/details/81867294 WPF入门教程(2)-基础篇 https:// ...

  7. WPF入门教程(八)--依赖属性(4)(转)

    WPF入门教程(八)--依赖属性(4) 2018年08月27日 11:35:55 weixin_38029882 阅读数:71 我们通过下面的这幅图,简单介绍一下WPF属性系统对依赖属性操作的基本步骤 ...

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

    同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProperty)只能拥有一个binding. 这一点可以通过设置bindi ...

  9. WPF入门教程系列(1)----基础

    一.前言 最近找了一个实习,需要学习WPF,由于之前对这门语言没有任何了解,所以就网上找大牛的博客作为入门基础,为了让自己更加熟悉,我选择了自己边学习边写博客,为了自己同时也为了方便以后他人的学习. ...

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

    WPF基础知识 快速学习绝不是从零学起的,良好的基础是快速入手的关键,下面先为大家摞列以下自己总结的学习WPF的几点基础知识: 1) C#基础语法知识(或者其他.NET支持的语言):这个是当然的了,虽 ...

最新文章

  1. ASP.NET Core集成Nacos配置中心之适配多格式配置
  2. 一些有关使用EF的错误用法展开的思考
  3. Android堆栈分析
  4. java stream Interface BiFunction<T,U,R>
  5. 语音识别软件_语音识别软件是什么_离线语音识别软件_企业服务汇
  6. tensorflow实现残差网络(mnist数据集)
  7. 换加密算法--python
  8. android10图片保存,android10分区存储照片选择,拍照处理
  9. Java EE 6权威指南:第4版.基础篇
  10. 对Gamma校正的理解
  11. 5款好用的项目管理软件推荐
  12. 游戏辅助原理与制作02-植物大战僵尸02-金币基址
  13. Python如何配置清华镜像源
  14. linux 禁用usb驱动程序,如何使用musb_hdrc Linux驱动程序断开特定的USB设备?
  15. c#延时函数,不止Sleep函数
  16. android fresco 圆角,圆角和圆圈
  17. html p首字母缩进,html里p标签里面如何让每一行首行缩进两格???
  18. 生成函数多项式操作合集
  19. 将字符串的一部分拷贝到另一个字符串
  20. [SVA]SystemVerilog Assertion(SVA)編寫經驗

热门文章

  1. 各地级市系列环境指标数据(2003-2017年)
  2. 嵌入式设备移植触摸屏驱动
  3. linux ospf 命令,Linux_防火墙入门22:常用路由协议(OSPF)配置实例
  4. 【WEB程序设计】web程序设计的一些基本知识
  5. 青花瓷Charles安装
  6. 工程测量计算机在线用,工程测量中的计算机编程新技术.doc
  7. 更改docker ip
  8. 电商直播系统源码该如何突破?
  9. 求职、跳槽中英文简历模板下载集合
  10. 信息系统项目管理师之选择题、案例分析题备考