WPF: Могу ли я определить / установить прикрепленное свойство через стиль? - PullRequest
5 голосов
/ 02 февраля 2011

Есть ли способ установить присоединенное свойство с помощью стиля?

У меня есть, например, кнопка, на которой установлен компонент взаимодействия (из System.Windows.Interactivity)

<Button>
  <i:Interaction.Triggers>
    ...
  </i:Interaction.Triggers>
</Button>

Теперь я хотел бы создать стиль, в котором будет установлено это свойство Interaction.Triggers, и тем самым заменит избыточность, указав это свойство в каждом экземпляре Button.Возможно ли это в WPF?

<Style Target={x:Type Button}>
  <!-- ??? -->
  <Setter PropertyName="i.Interaction.Triggers">
  ...

Каким-то образом я не вижу, как, но я видел другие примеры в Интернете, где прикрепленные свойства, кажется, доступны изнутри стиля ...

Обновление

Таким образом, в основном это скорее проблема с Interaction.Triggers, не имеющие возможности «установить» что-то.Как я должен повторно использовать набор определений взаимодействия?

1 Ответ

8 голосов
/ 02 февраля 2011

Это известная проблема со свойствами коллекции только для чтения (то же самое с коллекцией InputBindings).Чтобы решить эту проблему, я создал прикрепленное свойство:

public static StyleTriggerCollection GetTriggers(DependencyObject obj) {
    return (StyleTriggerCollection)obj.GetValue(TriggersProperty);
}

public static void SetTriggers(DependencyObject obj, StyleTriggerCollection value) {
    obj.SetValue(TriggersProperty, value);
}

public static readonly DependencyProperty TriggersProperty =
    DependencyProperty.RegisterAttached("Triggers", typeof(StyleTriggerCollection), typeof(ControlExtensions), new UIPropertyMetadata(null, OnTriggersChanged));

static void OnTriggersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
    var triggers = (StyleTriggerCollection) e.NewValue;

    if (triggers != null) {
        var existingTriggers = Interaction.GetTriggers(d);

        foreach (var trigger in triggers) {
            existingTriggers.Add((TriggerBase)trigger.Clone());
        }
    }
}

Это свойство использует пользовательский стиль StyleTriggerCollection, поскольку стандартная коллекция триггеров не имеет открытого конструктора:

public class StyleTriggerCollection : Collection<TriggerBase>
{
}

В установщике стиля выможно использовать это так:

<Setter Property="my:ControlExtensions.Triggers">
    <Setter.Value>
        <my:StyleTriggerCollection>
            <!-- Put your triggers here -->
        </my:StyleTriggerCollection>
    </Setter.Value>
</Setter>
...