Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to give the condition for EventTrigger?

Tags:

Is it possible to give the condition within the EventTrigger?? I have written a following EventTrigger (Mouse.MouseLeave) for Radio button. I want this should not be trigged for an item which is in Checked condition (IsChecked=True).

<EventTrigger RoutedEvent="Mouse.MouseLeave" SourceName="border">                                        <BeginStoryboard Name="out_BeginStoryboard" Storyboard="{StaticResource out}" />       <RemoveStoryboard BeginStoryboardName="over_BeginStoryboard" /> </EventTrigger> 

Please let me know how can I achieve this?

Thanks in advance.

like image 969
Prabu Avatar asked May 04 '10 10:05

Prabu


2 Answers

You can't use EventTrigger in this way. WPF's RoutedEventHandler that invokes EventTriggers doesn't provide any mechanism for making the trigger conditional, and you can't fix this by subclassing TriggerAction because there is no protected Invoke() or Execute() action to override.

However this can be done quite easily using a custom class. Here's how it would be used:

<Border>   <my:ConditionalEventTrigger.Triggers>     <my:ConditionalEventTriggerCollection>       <my:ConditionalEventTrigger RoutedEvent="Mouse.MouseLeave"                                   Condition="{Binding IsChecked, ElementName=checkbox}">         <BeginStoryboard Name="out_BeginStoryboard" Storyboard="{StaticResource out}" />                        <RemoveStoryboard BeginStoryboardName="over_BeginStoryboard" />                      </my:ConditionalEventTrigger>                    </my:ConditionalEventTriggerCollection>   </my:ConditionalEventTrigger.Triggers>   ... 

And here's how it would be implemented:

[ContentProperty("Actions")]  public class ConditionalEventTrigger : FrameworkContentElement {    public RoutedEvent RoutedEvent { get; set; }    public List<TriggerAction> Actions { get; set; }    // Condition   public bool Condition { get { return (bool)GetValue(ConditionProperty); } set { SetValue(ConditionProperty, value); } }   public static readonly DependencyProperty ConditionProperty = DependencyProperty.Register("Condition", typeof(bool), typeof(ConditionalEventTrigger));    // "Triggers" attached property   public static ConditionalEventTriggerCollection GetTriggers(DependencyObject obj) { return (ConditionalEventTriggerCollection)obj.GetValue(TriggersProperty); }   public static void SetTriggers(DependencyObject obj, ConditionalEventTriggerCollection value) { obj.SetValue(TriggersProperty, value); }   public static readonly DependencyProperty TriggersProperty = DependencyProperty.RegisterAttached("Triggers", typeof(ConditionalEventTriggerCollection), typeof(ConditionalEventTrigger), new PropertyMetadata    {      PropertyChangedCallback = (obj, e) =>      {        // When "Triggers" is set, register handlers for each trigger in the list        var element = (FrameworkElement)obj;        var triggers = (List<ConditionalEventTrigger>)e.NewValue;       foreach(var trigger in triggers)         element.AddHandler(trigger.RoutedEvent, new RoutedEventHandler((obj2, e2) =>           trigger.OnRoutedEvent(element)));     }    });    public ConditionalEventTrigger()   {     Actions = new List<TriggerAction>();   }    // When an event fires, check the condition and if it is true fire the actions    void OnRoutedEvent(FrameworkElement element)    {      DataContext = element.DataContext;  // Allow data binding to access element properties     if(Condition)      {        // Construct an EventTrigger containing the actions, then trigger it        var dummyTrigger = new EventTrigger { RoutedEvent = _triggerActionsEvent };        foreach(var action in Actions)          dummyTrigger.Actions.Add(action);         element.Triggers.Add(dummyTrigger);        try        {          element.RaiseEvent(new RoutedEventArgs(_triggerActionsEvent));        }        finally        {          element.Triggers.Remove(dummyTrigger);        }      }    }     static RoutedEvent _triggerActionsEvent = EventManager.RegisterRoutedEvent("", RoutingStrategy.Direct, typeof(EventHandler), typeof(ConditionalEventTrigger));   }   // Create collection type visible to XAML - since it is attached we cannot construct it in code  public class ConditionalEventTriggerCollection : List<ConditionalEventTrigger> {}  

Enjoy!

like image 80
Ray Burns Avatar answered Oct 12 '22 14:10

Ray Burns


This is what worked for me...

I wanted to execute an animation based on the mouse hovering over a UI element and the UI element's associated owner being active (i.e. enabled to make a player move).

To support these requirements, I used relative source binding to overcome the lack of support for event trigger conditions.

Example:

<MultiDataTrigger>     <MultiDataTrigger.Conditions>         <Condition Binding="{Binding RelativeSource={RelativeSource self}, Path=IsMouseOver}" Value="True" />         <Condition Binding="{Binding Path=IsPlayer1Active}" Value="True" />     </MultiDataTrigger.Conditions>     <MultiDataTrigger.EnterActions>         <BeginStoryboard>             <Storyboard>                 <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[0].Color" To="#FF585454" Duration="0:0:.25"/>                 <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[1].Color" To="Black" Duration="0:0:2"/>             </Storyboard>         </BeginStoryboard>     </MultiDataTrigger.EnterActions> </MultiDataTrigger> 
like image 37
Scott Nimrod Avatar answered Oct 12 '22 15:10

Scott Nimrod