Свойства зависимости WPF: зачем мне указывать тип владельца? - PullRequest
4 голосов
/ 15 мая 2009

Вот так я регистрирую DependencyProperty:

    public static readonly DependencyProperty UserProperty = 
        DependencyProperty.Register("User", typeof (User), 
             typeof (NewOnlineUserNotifier));                                                                                                                 


    public User User
    {
        get
        {
            return (User)GetValue(UserProperty);
        }
        set
        {
            SetValue(UserProperty, value);
        }
    }

Третий параметр метода DependencyProperty.Register требует, чтобы вы указали тип элемента управления, в котором находится свойство зависимости (в этом случае мой элемент управления называется NewOnlineUserNotifier).

Мой вопрос: Почему вы на самом деле указываете тип владельца и что происходит, если вы указываете тип, отличный от фактического владельца?

Ответы [ 3 ]

8 голосов
/ 15 мая 2009

Тип, из которого вы вызываете метод Register, не является фактическим владельцем свойства, поэтому вы не можете указать тип, отличный от фактического владельца, поскольку указанный вами тип равен фактическим владельцем .

Пример, в котором это может быть полезно, - это когда вы создаете пользовательский элемент управления, содержащий другие элементы управления. Ранее с WinForms, если у вас была какая-то дополнительная информация, которая была бы полезна только для этого контейнера, но семантически принадлежала дочернему элементу, то лучшее, что вы могли сделать, - это поместить эту информацию в свойство «все теги». Это и удалило безопасность типов, и вы никогда не были уверены, что другой класс не попытается сохранить что-то еще в теге. Теперь свойства зависимостей WPF позволяют привязывать значения к объектам, при этом сам объект не должен содержать значение. Тривиальный пример:

public class ButtonContainer : Control
{
    public Button ChildButton { get; set; }

    public static readonly DependencyProperty FirstOwnerProperty =
    DependencyProperty.Register("FirstOwner", typeof(ButtonContainer),
         typeof(Button));

    public ButtonContainer()
    {
        ChildButton = new Button();
        ChildButton.SetValue(FirstOwnerProperty, this);
    }

}

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

Используя новый класс следующим образом:

ButtonContainer container1 = new ButtonContainer();

ButtonContainer container2 = new ButtonContainer();
container2.ChildButton = container1.ChildButton;

Когда ChildButton перемещается из одного контейнера в другой, значение его FirstOwnerProperty перемещается вместе с ним, как если бы он был реальным членом класса Button. Контейнер2 может вызвать ChildButton.GetValue (FirstOwnerProperty) и выяснить, какой ButtonContainer изначально создал кнопку (почему он может захотеть это сделать, оставлено в качестве упражнения для читателя ...). Все это возможно без необходимости подкласса кнопки для узкой специальности.

1 голос
/ 15 мая 2009

В двух словах, когда вы регистрируете DP, вы добавляете объект (DP) в список, прикрепленный к классу (владельцу). Эта операция «живет» только в классе, где она объявлена, и часто не связана с ней.

1 голос
/ 15 мая 2009

Это потому, что один и тот же DependencyProperty может быть определен по-разному (с разными метаданными) для нескольких типов

...