原文:RelativeSource 简述

RelativeSource实现标记扩展,以描述绑定源相对于绑定目标的位置。

<Binding>
<Binding.RelativeSource>
<RelativeSource Mode="modeEnumValue"/>
</Binding.RelativeSource>
</Binding>
- or
<Binding>
<Binding.RelativeSource>
<RelativeSource
Mode="FindAncestor"
AncestorType="{x:Type typeName}"
AncestorLevel="intLevel"
/>
</Binding.RelativeSource>
</Binding>
    // Summary:
// Describes the location of the binding source relative to the position of
// the binding target.
public enum RelativeSourceMode
{
// Summary:
// Allows you to bind the previous data item (not that control that contains
// the data item) in the list of data items being displayed.
PreviousData = ,
//
// Summary:
// Refers to the element to which the template (in which the data-bound element
// exists) is applied. This is similar to setting a System.Windows.TemplateBindingExtension
// and is only applicable if the System.Windows.Data.Binding is within a template.
TemplatedParent = ,
//
// Summary:
// Refers to the element on which you are setting the binding and allows you
// to bind one property of that element to another property on the same element.
Self = ,
//
// Summary:
// Refers to the ancestor in the parent chain of the data-bound element. You
// can use this to bind to an ancestor of a specific type or its subclasses.
// This is the mode you use if you want to specify System.Windows.Data.RelativeSource.AncestorType
// and/or System.Windows.Data.RelativeSource.AncestorLevel.
FindAncestor = ,
}

Xaml 示例

     <Window.Resources>
<ControlTemplate x:Key="template">
<Canvas>
<Canvas.RenderTransform>
<RotateTransform Angle="20"/>
</Canvas.RenderTransform>
<Ellipse Height="100" Width="150" Fill="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Background}"></Ellipse>
<ContentPresenter Margin="35" Content="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"/>
</Canvas>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<TextBlock>
<TextBlock.Text>
<Binding Path="Title">
<Binding.RelativeSource>
<RelativeSource Mode="FindAncestor" AncestorType="{x:Type Window}" />
</Binding.RelativeSource>
</Binding>
</TextBlock.Text>
</TextBlock>
<TextBlock Text="{Binding Path=Title,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}} }"></TextBlock>

<Button Template="{StaticResource template}" Background="AliceBlue">
<TextBlock FontSize="22">Click me</TextBlock>
</Button>
</StackPanel>

RelativeSource内部实现

using System;
using System.ComponentModel;
using System.Windows.Markup; namespace System.Windows.Data
{
public class RelativeSource : MarkupExtension, ISupportInitialize
{
public RelativeSource(); public RelativeSource(RelativeSourceMode mode); public RelativeSource(RelativeSourceMode mode, Type ancestorType, int ancestorLevel); public Type AncestorType { get; set; }

public RelativeSourceMode Mode { get; set; } public static RelativeSource PreviousData { get; } public static RelativeSource Self { get; } public static RelativeSource TemplatedParent { get; } public override object ProvideValue(IServiceProvider serviceProvider); ...
}
}
using System;
using System.ComponentModel;
using System.Windows.Markup;

namespace System.Windows.Data
{
/// <summary>Implements a markup extension that describes the location of the binding source relative to the position of the binding target.</summary>
[MarkupExtensionReturnType(typeof(RelativeSource))]
public class RelativeSource : MarkupExtension, ISupportInitialize
{
private RelativeSourceMode _mode;
private Type _ancestorType;
private int _ancestorLevel = -;
private static RelativeSource s_previousData;
private static RelativeSource s_templatedParent;
private static RelativeSource s_self;
/// <summary>Gets a static value that is used to return a <see cref="T:System.Windows.Data.RelativeSource" /> constructed for the <see cref="F:System.Windows.Data.RelativeSourceMode.PreviousData" /> mode.</summary>
/// <returns>A static <see cref="T:System.Windows.Data.RelativeSource" />.</returns>
public static RelativeSource PreviousData
{
get
{
if (RelativeSource.s_previousData == null)
{
RelativeSource.s_previousData = new RelativeSource(RelativeSourceMode.PreviousData);
}
return RelativeSource.s_previousData;
}
}
/// <summary>Gets a static value that is used to return a <see cref="T:System.Windows.Data.RelativeSource" /> constructed for the <see cref="F:System.Windows.Data.RelativeSourceMode.TemplatedParent" /> mode.</summary>
/// <returns>A static <see cref="T:System.Windows.Data.RelativeSource" />.</returns>
public static RelativeSource TemplatedParent
{
get
{
if (RelativeSource.s_templatedParent == null)
{
RelativeSource.s_templatedParent = new RelativeSource(RelativeSourceMode.TemplatedParent);
}
return RelativeSource.s_templatedParent;
}
}
/// <summary>Gets a static value that is used to return a <see cref="T:System.Windows.Data.RelativeSource" /> constructed for the <see cref="F:System.Windows.Data.RelativeSourceMode.Self" /> mode.</summary>
/// <returns>A static <see cref="T:System.Windows.Data.RelativeSource" />.</returns>
public static RelativeSource Self
{
get
{
if (RelativeSource.s_self == null)
{
RelativeSource.s_self = new RelativeSource(RelativeSourceMode.Self);
}
return RelativeSource.s_self;
}
}
/// <summary>Gets or sets a <see cref="T:System.Windows.Data.RelativeSourceMode" /> value that describes the location of the binding source relative to the position of the binding target.</summary>
/// <returns>One of the <see cref="T:System.Windows.Data.RelativeSourceMode" /> values. The default value is null.</returns>
/// <exception cref="T:System.InvalidOperationException">This property is immutable after initialization. Instead of changing the <see cref="P:System.Windows.Data.RelativeSource.Mode" /> on this instance, create a new <see cref="T:System.Windows.Data.RelativeSource" /> or use a different static instance.</exception>
[ConstructorArgument("mode")]
public RelativeSourceMode Mode
{
get
{
return this._mode;
}
set
{
if (this.IsUninitialized)
{
this.InitializeMode(value);
return;
}
if (value != this._mode)
{
throw new InvalidOperationException(SR.Get("RelativeSourceModeIsImmutable"));
}
}
}
/// <summary>Gets or sets the type of ancestor to look for.</summary>
/// <returns>The type of ancestor. The default value is null.</returns>
/// <exception cref="T:System.InvalidOperationException">The <see cref="T:System.Windows.Data.RelativeSource" /> is not in the <see cref="F:System.Windows.Data.RelativeSourceMode.FindAncestor" /> mode.</exception>
public Type AncestorType
{
get
{
return this._ancestorType;
}
set
{
if (this.IsUninitialized)
{
this.AncestorLevel = ;
}
if (this._mode != RelativeSourceMode.FindAncestor)
{
if (value != null)
{
throw new InvalidOperationException(SR.Get("RelativeSourceNotInFindAncestorMode"));
}
}
else
{
this._ancestorType = value;
}
}
}
/// <summary>Gets or sets the level of ancestor to look for, in <see cref="F:System.Windows.Data.RelativeSourceMode.FindAncestor" /> mode. Use 1 to indicate the one nearest to the binding target element.</summary>
/// <returns>The ancestor level. Use 1 to indicate the one nearest to the binding target element.</returns>
public int AncestorLevel
{
get
{
return this._ancestorLevel;
}
set
{
if (this._mode != RelativeSourceMode.FindAncestor)
{
if (value != )
{
throw new InvalidOperationException(SR.Get("RelativeSourceNotInFindAncestorMode"));
}
}
else
{
if (value < )
{
throw new ArgumentOutOfRangeException(SR.Get("RelativeSourceInvalidAncestorLevel"));
}
this._ancestorLevel = value;
}
}
}
private bool IsUninitialized
{
get
{
return this._ancestorLevel == -;
}
}
/// <summary>Initializes a new instance of the <see cref="T:System.Windows.Data.RelativeSource" /> class.</summary>
public RelativeSource()
{
this._mode = RelativeSourceMode.FindAncestor;
}
/// <summary>Initializes a new instance of the <see cref="T:System.Windows.Data.RelativeSource" /> class with an initial mode.</summary>
/// <param name="mode">One of the <see cref="T:System.Windows.Data.RelativeSourceMode" /> values.</param>
public RelativeSource(RelativeSourceMode mode)
{
this.InitializeMode(mode);
}
/// <summary>Initializes a new instance of the <see cref="T:System.Windows.Data.RelativeSource" /> class with an initial mode and additional tree-walking qualifiers for finding the desired relative source.</summary>
/// <param name="mode">One of the <see cref="T:System.Windows.Data.RelativeSourceMode" /> values. For this signature to be relevant, this should be <see cref="F:System.Windows.Data.RelativeSourceMode.FindAncestor" />.</param>
/// <param name="ancestorType">The <see cref="T:System.Type" /> of ancestor to look for.</param>
/// <param name="ancestorLevel">The ordinal position of the desired ancestor among all ancestors of the given type. </param>
public RelativeSource(RelativeSourceMode mode, Type ancestorType, int ancestorLevel)
{
this.InitializeMode(mode);
this.AncestorType = ancestorType;
this.AncestorLevel = ancestorLevel;
}
/// <summary>This member supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used directly from your code.</summary>
void ISupportInitialize.BeginInit()
{
}

///<summary>This member supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used directly from your code.</summary>
void ISupportInitialize.EndInit()
{
if (this.IsUninitialized)
{
throw new InvalidOperationException(SR.Get("RelativeSourceNeedsMode"));
}
if (this._mode == RelativeSourceMode.FindAncestor && this.AncestorType == null)
{
throw new InvalidOperationException(SR.Get("RelativeSourceNeedsAncestorType"));
}
}

/// <summary>Indicates whether the <see cref="P:System.Windows.Data.RelativeSource.AncestorType" /> property should be persisted.</summary>
/// <returns>true if the property value has changed from its default; otherwise, false.</returns>
public bool ShouldSerializeAncestorType()
{
return this._mode == RelativeSourceMode.FindAncestor;
}

/// <summary>Indicates whether the <see cref="P:System.Windows.Data.RelativeSource.AncestorLevel" /> property should be persisted.</summary>
/// <returns>true if the property value has changed from its default; otherwise, false.</returns>
public bool ShouldSerializeAncestorLevel()
{
return this._mode == RelativeSourceMode.FindAncestor;
}

/// <summary>Returns an object that should be set as the value on the target object's property for this markup extension. For <see cref="T:System.Windows.Data.RelativeSource" />, this is another <see cref="T:System.Windows.Data.RelativeSource" />, using the appropriate source for the specified mode. </summary>
/// <returns>Another <see cref="T:System.Windows.Data.RelativeSource" />.</returns>
/// <param name="serviceProvider">An object that can provide services for the markup extension. In this implementation, this parameter can be null.</param>
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (this._mode == RelativeSourceMode.PreviousData)
{
return RelativeSource.PreviousData;
}
if (this._mode == RelativeSourceMode.Self)
{
return RelativeSource.Self;
}
if (this._mode == RelativeSourceMode.TemplatedParent)
{
return RelativeSource.TemplatedParent;
}
return this;
}
private void InitializeMode(RelativeSourceMode mode)
{
if (mode == RelativeSourceMode.FindAncestor)
{
this._ancestorLevel = ;
this._mode = mode;
return;
}
if (mode == RelativeSourceMode.PreviousData || mode == RelativeSourceMode.Self || mode == RelativeSourceMode.TemplatedParent)
{
this._ancestorLevel = ;
this._mode = mode;
return;
}
throw new ArgumentException(SR.Get("RelativeSourceModeInvalid"), "mode");
}
}
}

最新文章

  1. 如何理解MySQL中auto_increment?
  2. &lt;&lt;&lt; Oracle表创建、修改、删除基础操作
  3. Inside Flask - flask.__init__.py 和核心组件
  4. 在linux上使用&quot;scp&quot;命令拷贝一个目录到另一台服务器的时候报&quot;not a regular file&quot;错误的解决办法
  5. 微软职位内部推荐-Senior Development Lead
  6. https 方式使用git@osc设置密码的方式
  7. Nosql_笔记
  8. php自学笔记1
  9. sql 将Null 值转化成空字符串
  10. c3p0数据源定义
  11. 用Total Commander替换windos默认资源管理器
  12. 《pigcms v6.2最新完美至尊版无任何限制,小猪微信源码多用户微信营销服务平台系统》
  13. php 学习笔记 数组2
  14. Redis和Spring整合
  15. python机器学习实战(二)
  16. vue中$refs、$slot、$nextTick相关的语法
  17. SQL 自定义存储过程报错
  18. Docker启动mysql的坑2
  19. grep简单用法
  20. Centos7下安装apache2.4 php5.6 pdo_oci oci8

热门文章

  1. 小强的HTML5移动开发之路(46)——汇率计算器【2】
  2. poj2151之概率DP
  3. Linux网络编程——原始套接字实例:MAC 头部报文分析
  4. 前端切图:手机端自适应布局demo
  5. Weblogic中可以使用的脚本
  6. 任务调度平台Cuckoo-Schedule
  7. 学习鸟哥的Linux私房菜笔记(1)——Linux系统入门
  8. NOIP模拟 拆网线 - 贪心策略+dp
  9. WPF入门(三)-&gt;几何图形之不规则图形(PathGeometry) (2)
  10. QT5.8.0+MSVC2015安装以及环境配置(不需要安装VS2015)