基于 Ray 和 Orion,这是我的版本,目标是让您可以将 2 个触发器绑定到一个按钮,并在单击时翻转状态(或更多状态,如果您喜欢,并且它应该适用于所有控件)。当您绑定 ConditionProperty 时,有点棘手的是,您必须将 ConditionValue 写为 False 表示 True,True 表示 False。我猜这是因为按钮的事件处理程序在更新绑定之前执行。它的使用方式如下:
<Button x:Name="HoldButton" Content=""/>
<mut:ConditionalEventTrigger.ConditionTriggers>
<mut:ConditionalEventTriggers>
<mut:ConditionalEventTrigger RoutedEvent="ButtonBase.Click" ConditionProperty="" ConditionValue="False">
<BeginStoryboard x:Name="OnHold_BeginStoryboard" Storyboard=""/>
</mut:ConditionalEventTrigger>
<mut:ConditionalEventTrigger RoutedEvent="ButtonBase.Click" ConditionProperty="" ConditionValue="True">
<StopStoryboard BeginStoryboardName="OnHold_BeginStoryboard"/>
</mut:ConditionalEventTrigger>
</mut:ConditionalEventTriggers>
</mut:ConditionalEventTrigger.ConditionTriggers>
</Button>
这里是代码:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Markup;
namespace MyUtility.Trigger
{
[ContentProperty("Actions")]
public class ConditionalEventTrigger : FrameworkContentElement
{
public static readonly DependencyProperty ConditionTriggersProperty = DependencyProperty.RegisterAttached(
"ConditionTriggers",
typeof(ConditionalEventTriggers),
typeof(ConditionalEventTrigger),
new FrameworkPropertyMetadata(OnConditionalEventTriggersChanged));
public static ConditionalEventTriggers GetConditionTriggers(FrameworkElement element)
{
return (ConditionalEventTriggers)element.GetValue(ConditionTriggersProperty);
}
public static void SetConditionTriggers(FrameworkElement element, List<ConditionalEventTrigger> value)
{
element.SetValue(ConditionTriggersProperty, value);
}
public static readonly DependencyProperty ConditionPropertyProperty = DependencyProperty.Register(
"ConditionProperty",
typeof(bool),
typeof(ConditionalEventTrigger));
public bool ConditionProperty
{
get
{
return (bool)GetValue(ConditionPropertyProperty);
}
set
{
SetValue(ConditionPropertyProperty, value);
}
}
public static readonly DependencyProperty ConditionValueProperty = DependencyProperty.Register(
"ConditionValue",
typeof(bool),
typeof(ConditionalEventTrigger));
public bool ConditionValue
{
get
{
return (bool)GetValue(ConditionValueProperty);
}
set
{
SetValue(ConditionValueProperty, value);
}
}
private static readonly RoutedEvent m_DummyEvent = EventManager.RegisterRoutedEvent(
"ConditionalEventTriggerDummyEvent",
RoutingStrategy.Direct,
typeof(EventHandler),
typeof(ConditionalEventTrigger));
public RoutedEvent RoutedEvent { get; set; }
public List<TriggerAction> Actions { get; set; }
public ConditionalEventTrigger()
{
Actions = new List<TriggerAction>();
}
public static void OnConditionalEventTriggersChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var element = (FrameworkElement)obj;
var triggers = (ConditionalEventTriggers)e.NewValue;
foreach(ConditionalEventTrigger t in triggers)
{
element.RemoveHandler(t.RoutedEvent, new RoutedEventHandler((obj2, e2) => t.OnRoutedEvent(element)));
element.AddHandler(t.RoutedEvent, new RoutedEventHandler((obj2, e2) => t.OnRoutedEvent(element)));
}
}
public void OnRoutedEvent(FrameworkElement element)
{
this.DataContext = element.DataContext;
if (this.ConditionProperty == this.ConditionValue)
{
var dummyTrigger = new EventTrigger { RoutedEvent = m_DummyEvent };
foreach (TriggerAction action in this.Actions)
{
dummyTrigger.Actions.Add(action);
}
element.Triggers.Add(dummyTrigger);
try
{
element.RaiseEvent(new RoutedEventArgs(m_DummyEvent));
}
finally
{
element.Triggers.Remove(dummyTrigger);
}
}
}
}
public class ConditionalEventTriggers : List<ConditionalEventTrigger> {}
}