RelativeSource 简述

原文: 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 = 0,
        //
        // 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 = 1,
        //
        // 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 = 2,
        //
        // 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 = 3,
    }

 

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 = -1; 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 = 1; } 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 != 0) { throw new InvalidOperationException(SR.Get("RelativeSourceNotInFindAncestorMode")); } } else { if (value < 1) { throw new ArgumentOutOfRangeException(SR.Get("RelativeSourceInvalidAncestorLevel")); } this._ancestorLevel = value; } } } private bool IsUninitialized { get { return this._ancestorLevel == -1; } } /// <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 = 1; this._mode = mode; return; } if (mode == RelativeSourceMode.PreviousData || mode == RelativeSourceMode.Self || mode == RelativeSourceMode.TemplatedParent) { this._ancestorLevel = 0; this._mode = mode; return; } throw new ArgumentException(SR.Get("RelativeSourceModeInvalid"), "mode"); } } }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值