原文: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");
}
}
}

RelativeSource 简述的更多相关文章

  1. Windows Presentation Foundation (WPF)中的命令(Commands)简述

    原文:Windows Presentation Foundation (WPF)中的命令(Commands)简述 ------------------------------------------- ...

  2. 简述 OAuth 2.0 的运作流程

    本文将以用户使用 github 登录网站留言为例,简述 OAuth 2.0 的运作流程. 假如我有一个网站,你是我网站上的访客,看了文章想留言表示「朕已阅」,留言时发现有这个网站的帐号才能够留言,此时 ...

  3. JavaScript单线程和浏览器事件循环简述

    JavaScript单线程 在上篇博客<Promise的前世今生和妙用技巧>的开篇中,我们曾简述了JavaScript的单线程机制和浏览器的事件模型.应很多网友的回复,在这篇文章中将继续展 ...

  4. Design Patterns Simplified - Part 3 (Simple Factory)【设计模式简述--第三部分(简单工厂)】

    原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part3-factory/ Design ...

  5. Android网络定位服务定制简述

    Android 添加高德或百度网络定位服务 Android的网络定位服务以第三方的APK方式提供服务,由于在国内Android原生自带的com.google.android.gms服务几乎处于不可用状 ...

  6. 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述

    微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...

  7. 简述ASP.NET MVC原理

    1.为什么ASP.NET需要MVC? 因为随着网站的的数量级越来越大,原始的网站方式,这里指的是WebForm,在运行速度和维护性方面,以及代码量上面,越来越难以满足日益庞大的网站维护成本.代码的重构 ...

  8. Design Patterns Simplified - Part 2 (Singleton)【设计模式简述--第二部分(单例模式)】

    原文链接: http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part-2-singleton/ De ...

  9. 【翻译】设计模式学习系列1---【Design Patterns Simplified: Part 1【设计模式简述:第一部分】】

    原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part1/ Design Pattern ...

随机推荐

  1. Kinect小小玩偶游戏----小小潜水员

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接: http://blog.csdn.net/cartzhang/article/details/44939887 作者:ca ...

  2. 网络编程02---HTTP协议

    1.URL简单介绍 1.client怎样找到server 我们都知道网络中部署着各种各样的server.比方腾讯的server.百度的server.那么问题来了.client怎样找到想要连接的serv ...

  3. [Django] The models

    Create a new app: python manage.py startapp tictactoe Then add you app to INSTALLED_APP array in set ...

  4. [NPM] Pipe data from one npm script to another

    In an effort to bypass saving temporary build files you can leverage piping and output redirection t ...

  5. Jquery前端分页插件pagination使用

    插件描述:JqueryPagination是一个轻量级的jquery分页插件.只需几个简单的配置就可以生成分页控件.并且支持ajax获取数据,自定义请求参数,提供多种方法,事件和回调函数,功能全面的分 ...

  6. js进阶 9-6 js如何通过name访问指定指定表单控件

    js进阶 9-6 js如何通过name访问指定指定表单控件 一.总结 一句话总结:form中控件的三种访问方式:2formElement 1document 1.form中控件的三种访问方式? 1.f ...

  7. list数组归并去重

    C#两路list数组归并去重 个相同类型已排序数据进行合并,虽然list数组中有AddRange方法,但它只是把第二个数组从第一个数组末尾插入,假如两个数组有重复数据,保存进去.还有Union方法合并 ...

  8. System and method for dynamically adjusting to CPU performance changes

    FIELD OF THE INVENTION The present invention is related to computing systems, and more particularly ...

  9. spark action之saveastextfile

    java /** *saveastextfile 把rdd中的数据保存到文件中,只能指定文件夹 *@author Tele * */ public class SaveasTextFileDemo1 ...

  10. MySQL分区表使用方法

    原文:MySQL分区表使用方法 1. 确认MySQL服务器是否支持分区表 命令: show plugins; 2. MySQL分区表的特点 在逻辑上为一个表,在物理上存储在多个文件中 HASH分区(H ...