Поиск…


Вступление

Свойства зависимостей - это тип свойства, который расширяет свойство CLR. Если свойство CLR считывается непосредственно из члена вашего класса, свойство Dependency будет динамически разрешаться при вызове метода GetValue (), который ваш объект получает через наследование из базового класса DependencyObject.

Этот раздел разрушит свойства зависимостей и объяснит их использование как концептуально, так и с помощью примеров кода.

Синтаксис

  • DependencyProperty.Register (имя строки, тип propertyType, тип ownerType)
  • DependencyProperty.Register (имя строки, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.Register (имя строки, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterAttached (имя строки, тип propertyType, тип ownerType)
  • DependencyProperty.RegisterAttached (имя строки, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.RegisterAttached (имя строки, тип propertyType, тип ownerType, тип PropertyMetadataMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterReadOnly (имя строки, тип typeType, тип ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.RegisterReadOnly (имя строки, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterAttachedReadOnly (имя строки, тип typeType, тип ownerType, свойствоMetadata typeMetadata)
  • DependencyProperty.RegisterAttachedReadOnly (имя строки, тип propertyType, тип ownerType, тип PropertyMetadataMetadata, ValidateValueCallback validateValueCallback)

параметры

параметр подробности
название String представление имени свойства
PropertyType Type свойства, например typeof(int)
ownerType Type класса, в котором определяется свойство, например typeof(MyControl) или typeof(MyAttachedProperties) .
typeMetadata Экземпляр System.Windows.PropertyMetadata (или один из его подклассов), который определяет значения по умолчанию, свойство изменяет обратные вызовы, FrameworkPropertyMetadata позволяет определять параметры привязки, такие как System.Windows.Data.BindingMode.TwoWay .
validateValueCallback Пользовательский обратный вызов, который возвращает значение true, если новое значение свойства является допустимым, иначе false.

Стандартные свойства зависимостей

Когда использовать

Практически все элементы управления WPF сильно используют свойства зависимостей. Свойство зависимостей позволяет использовать многие функции WPF, которые невозможны при использовании стандартных свойств CLR, включая, помимо прочего, поддержку стилей, анимаций, привязки данных, наследования значений и уведомлений об изменениях.

Свойство TextBox.Text - простой пример того, где требуется стандартное свойство зависимостей. Здесь привязка данных невозможна, если Text является стандартным свойством CLR.

<TextBox Text="{Binding FirstName}" />

Как определить

Свойства зависимостей могут быть определены только в классах, полученных из DependencyObject , таких как FrameworkElement , Control и т. Д.

Одним из самых быстрых способов создания стандартного свойства зависимостей без необходимости запоминания синтаксиса является использование фрагмента «propdp», набрав propdp и нажав Tab . Будет добавлен фрагмент кода, который затем может быть изменен в соответствии с вашими потребностями:

public class MyControl : Control
{
    public int MyProperty
    {
        get { return (int)GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.
    // This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
            new PropertyMetadata(0));
}

Чтобы внести необходимые изменения, необходимо внести вкладку в разные части фрагмента кода, включая обновление имени свойства, типа свойства, содержащего тип класса, и значения по умолчанию.

Важные соглашения

Существует несколько важных конвенций / правил:

  1. Создайте свойство CLR свойства dependency. Это свойство используется в коде для вашего объекта или для других пользователей. Он должен вызывать GetValue и SetValue поэтому потребителям это не нужно.

  2. Назовите свойство зависимостей правильно. Поле DependencyProperty должно быть public static readonly . Он должен иметь имя, соответствующее имени свойства CLR, и заканчивается «Свойством», например Text и TextProperty .

  3. Не добавляйте дополнительную логику в средство настройки свойств CLR. Система свойств зависимостей (и специально XAML) не использует свойство CLR. Если вы хотите выполнить действие при изменении значения свойства, вы должны предоставить обратный вызов через PropertyMetadata :

    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
            new PropertyMetadata(0, MyPropertyChangedHandler));
    
    private static void MyPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        // Use args.OldValue and args.NewValue here as needed.
        // sender is the object whose property changed.
        // Some unboxing required.
    }
    

Режим привязки

Чтобы устранить необходимость указания Mode=TwoWay в привязках (аналогично поведению TextBox.Text ), обновите код, чтобы использовать FrameworkPropertyMetadata вместо PropertyMetadata и указать соответствующий флаг:

public static readonly DependencyProperty MyPropertyProperty =
    DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl), 
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

Прикрепленные свойства зависимостей

Когда использовать

Привязанное свойство - это свойство зависимостей, которое может быть применено к любому DependencyObject для улучшения поведения различных элементов управления или служб, которые знают о существовании свойства.

Некоторые примеры использования прикрепленных свойств включают:

  1. Наличие родительского элемента итерации через своих детей и определенное действие на детей. Например, элемент управления Grid использует привязанные свойства Grid.Row , Grid.Column , Grid.RowSpan и Grid.ColumnSpan для размещения элементов в строках и столбцах.
  2. Добавление визуальных эффектов к существующим элементам управления с помощью настраиваемых шаблонов, например добавление водяных знаков для пустых текстовых полей в приложении, без подкласса TextBox .
  3. Предоставление общего сервиса или функции для некоторых или всех существующих элементов управления, например ToolTipService или FocusManager . Они обычно называются прикрепленными поведением .
  4. Когда требуется наследование вниз по визуальному дереву, например, похоже на поведение DataContext .

Это еще раз показывает, что происходит в случае использования Grid :

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <Label Grid.Column="0" Content="Your Name:" />
    <TextBox Grid.Column="1" Text="{Binding FirstName}" />
</Grid>

Grid.Column не является свойством, которое существует в Label или TextBox . Скорее, Grid управления просматривает его дочерние элементы и размещает их по значениям вложенных свойств.

Как определить

Мы продолжим использовать Grid для этого примера. Определение Grid.Column показано ниже, но DependencyPropertyChangedEventHandler исключается для краткости.

public static readonly DependencyProperty RowProperty =
    DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
        new FrameworkPropertyMetadata(0, ...));

public static void SetRow(UIElement element, int value)
{
    if (element == null)
        throw new ArgumentNullException("element");

    element.SetValue(RowProperty, value);
}

public static int GetRow(UIElement element)
{
    if (element == null)
        throw new ArgumentNullException("element");

    return ((int)element.GetValue(RowProperty));
}

Поскольку присоединенные свойства могут быть прикреплены к широкому спектру элементов, они не могут быть реализованы как свойства CLR. Вместо этого вводится пара статических методов.

Следовательно, в отличие от стандартных свойств зависимостей, прикрепленные свойства также могут быть определены в классах, которые не получены из DependencyObject .

Здесь также применяются те же соглашения об именах, которые применяются к обычным свойствам зависимостей: свойство зависимостей RowProperty имеет соответствующие методы GetRow и SetRow .

Предостережения

Как указано в MSDN :

Хотя наследование значений свойств может работать для непривязанных свойств зависимостей, поведение наследования для неприсоединенного свойства через определенные границы элементов в дереве времени выполнения не определено. Всегда используйте RegisterAttached для регистрации свойств, где вы указываете Inherits в метаданных.

Свойства зависимостей только для чтения

Когда использовать

Свойство зависимости только для чтения похоже на свойство нормальной зависимости, но оно структурировано, чтобы не допустить, чтобы его значение было установлено вне контроля. Это хорошо работает, если у вас есть свойство, которое является исключительно информационным для потребителей, например IsMouseOver или IsKeyboardFocusWithin .

Как определить

Как и стандартные свойства зависимостей, свойство зависимостей только для чтения должно быть определено в классе, который происходит из DependencyObject .

public class MyControl : Control
{
    private static readonly DependencyPropertyKey MyPropertyPropertyKey = 
        DependencyProperty.RegisterReadOnly("MyProperty", typeof(int), typeof(MyControl),
            new FrameworkPropertyMetadata(0));

    public static readonly DependencyProperty MyPropertyProperty = MyPropertyPropertyKey.DependencyProperty;

    public int MyProperty
    {
        get { return (int)GetValue(MyPropertyProperty); }
        private set { SetValue(MyPropertyPropertyKey, value); }
    }
}

Здесь применимы те же самые соглашения, которые применяются к обычным свойствам зависимостей, но с двумя ключевыми отличиями:

  1. DependencyProperty поступает из private DependencyPropertyKey .
  2. Свойство свойств CLR является protected или private а не public .

Обратите внимание, что сеттер передает MyPropertyPropertyKey а не MyPropertyProperty в метод SetValue . Поскольку свойство было определено только для чтения, любая попытка использовать SetValue для свойства должна использоваться с перегрузкой, которая получает DependencyPropertyKey ; в противном случае будет InvalidOperationException .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow