依赖项属性继承

问题描述:

我需要控制从类型网格的祖先继承UIElement.IsEnabledProperty(可选窗口或任何其他元素i可以包装我的网格)依赖项属性继承

CS:下面我重写UIElement的元数据.IsEnabledProperty并使用Change和Coerce代表进行设置。

static PipeControl() 
    { 
     PipeControl.IsEnabledProperty.OverrideMetadata(typeof(PipeControl), new FrameworkPropertyMetadata(false, OnIsEnabledPropertyChanged, OnIsEnabledPropertyCoerce)); 
    } 

    private static void OnIsEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var isEnabled = (bool)e.NewValue; 
    } 

    private static object OnIsEnabledPropertyCoerce(DependencyObject d, object baseValue) 
    { 
     var valueSource = DependencyPropertyHelper.GetValueSource(d, PipeControl.IsEnabledProperty); 

     var pipeContorl = d as PipeControl; 
     if (pipeContorl == null) return baseValue; 

     return (bool)baseValue && pipeContorl.IsMyPipe; 
    } 

XAML:

<Grid IsEnabled="{Binding IsMyCondition , Mode=OneWay}">   
     <game:PipeControl Grid.Row="2" />    
     <game:PipeControl Grid.Row="2" Grid.Column="1" /> 
    </Grid> 

每个IsMyCondition改变OnIsEnabledPropertyCoerce被称为在每个PipeContorl时间, OnIsEnabledPropertyChanged不会被调用, 的ValueSource在OnIsEnabledProerty迫使是 “默认”(显示强迫总是得到默认的假值)。

我必须在其中我需要使用继承, 我预计值来源是“继承”的方式错过了一些 和OnIsEnabledPropertyChanged被调用。

UIElement有一个虚拟属性IsEnabledCore,它应该(?)用于强制IsEnabled属性。例如,Button或MenuItem根据CanExecute属性强制使用IsEnabled属性。 在您的自定义控制,您可以重写属性为:

protected override bool IsEnabledCore 
    { 
     get 
     { 
      return (base.IsEnabledCore && IsMyPipe); 
     } 
    } 

最重要的事情就是打电话CoerceValue当任何属性(例如IsMyPipe)对其中的IsEnabled依赖的变化。

所以自定义控件的实现将是:

static PipeControl() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(PipeControl), new FrameworkPropertyMetadata(typeof(PipeControl))); 
    } 

    public bool IsMyPipe 
    { 
     get { return (bool)GetValue(IsMyPipeProperty); } 
     set { SetValue(IsMyPipeProperty, value); } 
    } 

    public static readonly DependencyProperty IsMyPipeProperty = 
      DependencyProperty.Register(
        "IsMyPipe", 
        typeof(bool), 
        typeof(UIElement), 
        new PropertyMetadata(
          true, 
          new PropertyChangedCallback(OnIsMyPipeChanged))); 

    private static void OnIsMyPipeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     d.CoerceValue(UIElement.IsEnabledProperty); 
    } 

希望这会有所帮助,并在解决方案的任何意见都欢迎。

+0

我会稍后再检查一下,10x – 2013-04-10 15:38:08

+0

这很棒,但还有一件事,我仍然希望在PipeControl的IsEnabledProperty更改时得到通知,并从那里强制值。 我可以做到这一点与出一个不同的通知,如IsMyPipe的回调通知 – 2013-04-10 18:05:04

阿德南的回答以上,而这样的回答:

How can I add logic to an existing dependency-property callback?

我由一个完整的答案。

CS:

static PipeControl() 
    { 
     PipeControl.IsEnabledProperty.OverrideMetadata(typeof(PipeControl), new UIPropertyMetadata(new PropertyChangedCallback(OnIsEnabledPropertyChanged))); 
    } 



    private static void OnIsEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    {   
     var isEnabled = (bool)e.NewValue; 
    } 


    protected override bool IsEnabledCore 
    { 
     get 
     { 
      return (base.IsEnabledCore && IsMyPipe); 
     } 
    } 

IsEnabledCore返回值的回调,所以强制那里发生, 然后回调。

仅供参考,设置本地默认值似乎覆盖继承的,因此如果超驰继承 属性的元数据做螺母给一个默认的本地值,就像这样:

PipeControl.IsEnabledProperty.OverrideMetadata(typeof(PipeControl), new UIPropertyMetadata(false,new PropertyChangedCallback(OnIsEnabledPropertyChanged))); 
除了

,如果你只需要要添加强制逻辑,您可以重写IsEnabledCore, ,而对IsEnabledProperty的元数据不做任何其他操作。

+0

你说你不应该给一个默认的本地值,但是然后你在'new UIPropertyMetadata中设置'false'作为默认值(false, ...)'。我不理解超载或误解你的话吗? – 2016-10-05 01:32:01

+0

我不确定,这段时间很难记住...... 在此依赖项对象中设置的默认值将成为它使用的默认值。并会覆盖默认值。 也许我不应该注意不要使用继承的值。我相信这是'真' – 2016-10-05 10:52:06