Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: Can I define/set an attached property through a style?

Is there a way to set an attached property via a Style?

I have e.g. a button on which Interaction stuff is set (from System.Windows.Interactivity)

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

Now I would like to make a style in which that Interaction.Triggers property is set, thereby replacing redundancies by having to specify that property on every Button instance. Is this possible in WPF?

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

Somehow I cant see how, but I have seen other examples in the web where attached properties seem to be accessible from within a style...

Update

So basically this is rather an issue with Interaction.Triggers not having a way to "Set" something. How am I supposed to reuse a set of Interaction definitions?

like image 983
flq Avatar asked Feb 02 '11 14:02

flq


1 Answers

This is a known issue with read-only collection properties (the same thing with InputBindings collection). To solve this issue I've created an attached property:

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());
        }
    }
}

This property uses custom StyleTriggerCollection, because standard trigger collection has not public constructor:

public class StyleTriggerCollection : Collection<TriggerBase>
{
}

In the Style setter you can use it like this:

<Setter Property="my:ControlExtensions.Triggers">
    <Setter.Value>
        <my:StyleTriggerCollection>
            <!-- Put your triggers here -->
        </my:StyleTriggerCollection>
    </Setter.Value>
</Setter>
like image 157
Pavlo Glazkov Avatar answered Nov 03 '22 03:11

Pavlo Glazkov