views:

37

answers:

1

Hi,

I have a problem with WPF triggers. In my application i used a multitrigger but would like to achieve that changes made when a trigger's conditions become true to persist and NOT to be invalidated when the trigger's conditions become false AGAIN. Is it possible to realize what I want ?

Thanks in advance.

+1  A: 

Triggers don't have any memory: As soon as the trigger becomes inapplicable the trigger's setters are unapplied. You want a condition that "locks on" once it has been set. This can be done with a very simple and generic piece of code.

First you need an attached property that you can "lock on". Here's a simple class with a "IsLocked" attached property that becomes true whenever the "DoLock" property is set and stays that way from then on:

public class LockingProperty : DependencyObject
{
  // IsLocked
  public static bool GetIsLocked(DependencyObject obj) { return (bool)obj.GetValue(IsLockedProperty); }
  public static void SetIsLocked(DependencyObject obj, bool value) { obj.SetValue(IsLockedProperty, value); }
  public static readonly DependencyProperty IsLockedProperty = DependencyProperty.RegisterAttached("IsLocked", typeof(bool), typeof(LockingProperty));

  // DoLock
  public static bool GetDoLock(DependencyObject obj) { return (bool)obj.GetValue(DoLockProperty); }
  public static void SetDoLock(DependencyObject obj, bool value) { obj.SetValue(DoLockProperty, value); }
  public static readonly DependencyProperty DoLockProperty = DependencyProperty.RegisterAttached("DoLock", typeof(bool), typeof(LockingProperty), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, e) => { SetIsLocked(obj, true); }
  });
}

Now you can emulate a locking trigger using two separate triggers:

<Triggers>
  <Trigger ... your trigger conditions here ...>
    <Setter Property="my:LockingProperty.DoLock" Value="true" />
  </Trigger>
  <Trigger Property="my:LockingProperty.IsLocked" Value="true" />
    ... your setters here ...
  </Trigger>
</Triggers>

Note that the first trigger in this example can be a Trigger, DataTrigger, MultiTrigger or MultiDataTrigger - whatever you need to express your triggering condition.

Ray Burns
Hi Ray and thanks for your answer. I really like it and it seems to me that it really does what I wanted however I realized that for my needs it is better to implement the logic what has to be done in a ViewModel class instead of in XAML and bind to it. Anyway, thanks for the answer, it might be helpful in the future.
Zoliq
Yes, implemeting such behavior in the ViewModel is often better than doing it with triggers. The thing I like about WPF is that it has so much flexibility. Very few other technologies have the power to create such a "locking trigger" feature, or to really handle ViewModels for that matter. So no matter how you implement your solution you win.
Ray Burns