2013-04-10 2 views
2

я нужен мой контроль, чтобы наследовать UIElement.IsEnabledProperty от Предок типа сетки (Факультативно окно или любого другого элемента я мог обернуть мою сетку с)Dependency Property Наследованию

CS: ниже я переопределить мета-данные UIElement .IsEnabledProperty и установите его с делегатами Change and 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 принудительно используют свойство IsEnabled в зависимости от их свойств CanExecute. В пользовательском элементе управления, вы можете переопределить свойство, как:

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 –

+0

, это замечательно, но есть еще одна вещь, мне все равно хотелось бы получить уведомление о том, что IsEnabledProperty от PipeControl изменится, и отмените значение оттуда. Могу ли я сделать это с помощью другого уведомления, такого как уведомление обратного вызова для IsMyPipe –

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 возвращает значение Обратного, поэтому Принуждение там происходит, и затем CallBack.

FYI, установка локального значения по умолчанию, кажется, чтобы переопределить унаследованным, так что если переопределение Наследуется метаданных свойства СДЕЛАЕТ гайка дает локальное значение по умолчанию, например, так:

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

Кроме того, если вам нужно только для добавления логики принуждения вы можете просто переопределить IsEnabledCore, и ничего не делать с метаданными IsEnabledProperty.

+0

. Вы говорите, что не следует указывать локальное значение по умолчанию, но тогда вы присваиваете 'false' значение по умолчанию в' new UIPropertyMetadata (false, ...). Разве я не понимаю перегрузки или недопонимания ваших слов? –

+0

Я не уверен, трудно запомнить все это время ... Логично, что значение по умолчанию, заданное в этом объекте зависимостей, будет тем, которое оно использует. и будет отменять значение по умолчанию. Возможно, мне не стоит обращать внимание на то, чтобы не использовать унаследованное значение. который я считаю «правдой», –

Смежные вопросы