AttachedProperty

03.09.2014 at 05:17

Это подвид DependencyProperty, которые объявляются в одном классе, а значения устанавливаются для экземпляров другого класса. Один из самых распространенных примеров – Grid.Row и Grid.Column, которые устанавливаются для контролей, вложенных в грид.

Особенности

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

Создание AttachedProperty

Создаем класс, в нем пишем propa и два раза нажимаем tab. Студия сгенерирует заготовку, в ней меняем имя свойства, его тип и значение по умолчанию.

public static class BackgroundManager
{
  public static bool GetNeedGrayBackground(DependencyObject obj)
  {
    return (bool)obj.GetValue(NeedGrayBackgroundProperty);
  }

  public static void SetNeedGrayBackground(DependencyObject obj, bool value)
  {
    obj.SetValue(NeedGrayBackgroundProperty, value);
  }

  public static readonly DependencyProperty NeedGrayBackgroundProperty =
    DependencyProperty.RegisterAttached("NeedGrayBackground", typeof(bool),
      typeof(BackgroundManager), new PropertyMetadata(false));
}

Видим два отличия от DependencyProperty:

  • Свойство регистрируется с помощью метода RegisterAttached, а не Register.
  • Враппер генерируется в виде парных методов, а не в виде свойства.

Враппер так же не вызывается при установке значения в XAML, он нужен для доступа к свойству из кода.
По аналогии с DependencyProperty добавим обработчик изменения значения:

  public static readonly DependencyProperty NeedGrayBackgroundProperty =
    DependencyProperty.RegisterAttached("NeedGrayBackground", typeof(bool),
      typeof(BackgroundManager), new PropertyMetadata(false, NeedGrayBackground));

  public static void NeedGrayBackground(DependencyObject d, 
    DependencyPropertyChangedEventArgs e)
  {
    if (!(bool)e.NewValue)
      return;
    var control = d as Control;
    if (control != null)
      control.Background = Brushes.Gray;
  }

Если новое значение свойства true и переданный объект является контролом – устанавливаем его Background в серый цвет.
Теперь соберем окно для проверки:

< Window x:Class="WpfApplication36.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication36"
        Title="MainWindow"
        Width="525"
        Height="350">
  < StackPanel>
    < Label local:BackgroundManager.NeedGrayBackground="True">Button1< /Label>
    < Label>Button2< /Label>
    < Label>Button3< /Label>
  < /StackPanel>
< /Window>

Запускаем
1
У обработчиков изменения значения DependencyProperty есть одна особенность – они не вызываются, если новое значение свойства совпадает со старым.