Как я могу изменить значение по умолчанию унаследованного свойства зависимости?

#wpf #subclass #dependency-properties #default-value

#wpf #подкласс #зависимость-свойства #значение по умолчанию

Вопрос:

Как я могу изменить значение по умолчанию для унаследованного свойства зависимости? В нашем случае мы создали подкласс Control, для которого по умолчанию Focusable установлено значение ‘true’. Мы хотим, чтобы наш подкласс имел значение по умолчанию ‘false’.

То, что мы делали, это просто устанавливали для него значение ‘false’ в конструкторе, но если кто-то использует ClearValue, оно возвращается к значению по умолчанию, а не к значению, установленному в конструкторе.

Вот что я в настоящее время делаю для достижения этой цели (это тестовый элемент управления с DP ‘Foo’ для примера.) Я не поклонник ‘new’ для скрытия свойства, хотя благодаря AddOwner оно указывает на тот же общий экземпляр, так что, думаю, все в порядке. Похоже, что оно также наследует все остальные значения метаданных, так что это хорошо. Просто интересно, правильно ли это?

 public class TestControlBase : Control
{

    public static readonly DependencyProperty FooProperty = DependencyProperty.Register(
        "Foo",
        typeof(int),
        typeof(TestControlBase),
        new FrameworkPropertyMetadata(4) // Original default value
    );

    public int Foo
    {
        get { return (int)GetValue(FooProperty); }
        set { SetValue(FooProperty, value); }
    }

}

public class TestControl : TestControlBase
{

    public static readonly new DependencyProperty FooProperty = TestControlBase.FooProperty.AddOwner(
        typeof(TestControl),
        new FrameworkPropertyMetadata(67) // New default for this subclass
    );

}
  

Отметить

Обновить…

Я думаю, что это даже лучше, поскольку устраняет вызов ‘new’. Вы по-прежнему получаете к нему доступ через свойство FooProperty в базовом классе, поскольку при этом используется AddOwner . Как таковое, технически это одно и то же.

 public class TestControl : TestControlBase
{
    // Note this is private
    private static readonly DependencyProperty AltFooProperty = TestControlBase.FooProperty.AddOwner(
        typeof(TestControl),
        new FrameworkPropertyMetadata(67) // New default for this subclass
    );

}
  

Комментарии:

1. Статическое поле типа DependencyProperty всегда должно быть общедоступным, иначе оно не будет работать корректно.

2. На самом деле, как я уже сказал, поскольку я на самом деле просто создаю AddOwner, вам никогда не нужно обращаться к закрытому, поскольку это общий из базового класса, который вы используете. Тем не менее, приведенный ниже ответ является правильным способом сделать это… Переопределите параметры. Это билет!

Ответ №1:

Правильный способ переопределить свойство базового класса — это:

 static TestControl() {

    FooProperty.OverrideMetadata(
        typeof(TestControl),
        new FrameworkPropertyMetadata(67)
    );
}
  

Редактировать:

AddOwner предназначен для совместного использования одного и того же DependencyProperty между типами, которые не связаны (т.Е. TextProperty of TextBox и TextBlock ).

Комментарии:

1. Однако мне было интересно… не нужно ли вам также явно указать все другие свойства в FrameworkPropertyMetadata или только то, что изменилось? В данном случае это немного, но в случаях, когда флаги AffectsMeasure или AffectsRender могут отличаться от значений по умолчанию, должен ли я также указывать их, или они просто унаследуют свои значения, если я не задам их явно? (Если вы знаете ответ, отлично, но я также поработаю над некоторым тестовым кодом именно для этого.)

2. @MarqueIV — Глядя на код в reflector, вам не нужно устанавливать их заново. Несколько настроек устанавливаются вместе (т. Е. если базовые наборы влияют на renderили вы устанавливаете AffectsRender, то это влияет на рендеринг), другие могут быть переопределены (например, Inherits).

3. Я потерял свою копию Reflector, когда получил новый MBP. Пришло время найти его снова! И поэтому я предполагаю, что само по себе это на самом деле не является «переопределяющим», если у него все еще есть доступ к исходным метаданным (к «или» против.) Полезно знать! И, как бы то ни было, вы лично ответили или внесли свой вклад во многие мои вопросы. Спасибо за то, что вы такой замечательный ресурс для этого сайта! Действительно ценится.

4. Просто позаботьтесь, если вам нужно установить, null затем выполните new FrameworkPropertyMetadata((object)null) приведение типов. В противном случае вызывается конструктор FrameworkPropertyMetadata(PropertyChangedCallback) .