WPF:我能通过样式定义/设置附加属性吗?

6
有没有通过样式设置附加属性的方法?
例如,我有一个按钮,上面设置了 Interaction 功能(来自 System.Windows.Interactivity)。
<Button>
  <i:Interaction.Triggers>
    ...
  </i:Interaction.Triggers>
</Button>

现在我想创建一个样式,在该样式中设置Interaction.Triggers属性,从而通过不必在每个按钮实例上指定该属性来替换冗余。在WPF中是否可能实现这一点?
<Style Target={x:Type Button}>
  <!-- ??? -->
  <Setter PropertyName="i.Interaction.Triggers">
  ...

一些我在网上看到的例子显示,似乎可以从样式内访问附加属性,但我不太理解其实现方式。
更新:实际上这更像是Interaction.Triggers没有“设置”某个东西的问题。我该如何重复使用一组Interaction定义呢?

可能是重复问题:http://stackoverflow.com/questions/4067876/set-hidden-attachedproperty-through-style - flq
1个回答

8

这是一个已知的问题,涉及只读集合属性(与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>

看起来非常有前途,我一回到代码就会看看! - flq
1
这似乎可以工作,但我对在触发器中使用DataContext感到困惑。我似乎无法让RelativeSource AncestorType等等起作用... - flq
你需要了解相对源是如何工作的。它适用于在可视化树中的元素。在这种情况下,触发器不在可视化树中 - 触发器集合只是可视化树中元素的属性。数据上下文继承之所以在这种情况下有效是因为触发器继承了Freezable。你可以在这里阅读相关内容:http://drwpf.com/blog/category/freezables/ - Pavlo Glazkov
我走了一条稍微不同的路线,因为我认为我已经完成了支持Freezable功能所需的所有步骤,但它并没有起作用。无论如何,再多的努力应该会揭示这个问题,并且这对我来说是一个答案 :) - flq
那对我来说完美地解决了问题,Pavlo。优雅的解决方案,解决了一个烦人的问题。+1 - Barracoder
我正在尝试让这个工作,我认为我正在经历你所说的相对源的问题...但我不确定如何解决...如果我在样式之外绑定同一个InvokeCommandAction,RelativeSource就可以正常工作...你能提供一些建议吗?谢谢。 - Jeff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接