2013-04-10 195 views
2

我需要控制從類型網格的祖先繼承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被調用。

回答

4

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

2

阿德南的回答以上,而這樣的回答:

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