Voici ma version modifiée de Ray's answer, qui crée et attache des événements fictifs uniquement lorsque les déclencheurs source sont définis, plutôt que de le faire à chaque fois. Je pensais que ce serait mieux pour mon scénario que je soulève un événement sur des centaines d'articles, pas seulement un ou deux:
[ContentProperty("Actions")]
public class ConditionalEventTrigger : FrameworkContentElement
{
static readonly RoutedEvent DummyEvent = EventManager.RegisterRoutedEvent(
"", RoutingStrategy.Direct, typeof(EventHandler), typeof(ConditionalEventTrigger));
public static readonly DependencyProperty TriggersProperty = DependencyProperty.RegisterAttached(
"Triggers", typeof(ConditionalEventTriggers), typeof(ConditionalEventTrigger),
new FrameworkPropertyMetadata(RefreshTriggers));
public static readonly DependencyProperty ConditionProperty = DependencyProperty.Register(
"Condition", typeof(bool), typeof(ConditionalEventTrigger)); // the Condition is evaluated whenever an event fires
public ConditionalEventTrigger()
{
Actions = new List<TriggerAction>();
}
public static ConditionalEventTriggers GetTriggers(DependencyObject obj)
{ return (ConditionalEventTriggers)obj.GetValue(TriggersProperty); }
public static void SetTriggers(DependencyObject obj, ConditionalEventTriggers value)
{ obj.SetValue(TriggersProperty, value); }
public bool Condition
{
get { return (bool)GetValue(ConditionProperty); }
set { SetValue(ConditionProperty, value); }
}
public RoutedEvent RoutedEvent { get; set; }
public List<TriggerAction> Actions { get; set; }
// --- impl ----
// we can't actually fire triggers because WPF won't let us (stupid sealed internal methods)
// so, for each trigger, make a dummy trigger (on a dummy event) with the same actions as the real trigger,
// then attach handlers for the dummy event
public static void RefreshTriggers(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var targetObj = (FrameworkElement)obj;
// start by clearing away the old triggers
foreach (var t in targetObj.Triggers.OfType<DummyEventTrigger>().ToArray())
targetObj.Triggers.Remove(t);
// create and add dummy triggers
foreach (var t in ConditionalEventTrigger.GetTriggers(targetObj))
{
t.DataContext = targetObj.DataContext; // set and Track DataContext so binding works
// targetObj.GetDataContextChanged().WeakSubscribe(dc => t.DataContext = targetObj.DataContext);
var dummyTrigger = new DummyEventTrigger { RoutedEvent = DummyEvent };
foreach (var action in t.Actions)
dummyTrigger.Actions.Add(action);
targetObj.Triggers.Add(dummyTrigger);
targetObj.AddHandler(t.RoutedEvent, new RoutedEventHandler((o, args) => {
if (t.Condition) // evaluate condition when the event gets fired
targetObj.RaiseEvent(new RoutedEventArgs(DummyEvent));
}));
}
}
class DummyEventTrigger : EventTrigger { }
}
public class ConditionalEventTriggers : List<ConditionalEventTrigger> { }
Il est utilisé comme ceci:
<Border>
<local:ConditionalEventTrigger.Triggers>
<local:ConditionalEventTriggers>
<local:ConditionalEventTrigger RoutedEvent="local:ClientEvents.Flash" Condition="{Binding IsFlashing}">
<BeginStoryboard Name="FlashAnimation">...
La ligne
utilise le cadre réactif et certaines méthodes d'extension que j'ai écrites, fondamentalement, nous devons nous abonner à l'événement .DataContextChanged
de l'objet cible, mais nous devons le faire avec un faible référenc e. Si vos objets ne jamais changer leur datacontext, alors vous aurez pas besoin de ce code à tous
Merci pour la réponse. Ma requête actuelle est, l'animation devrait se produire pour tous les éléments lorsque Mouse est quitté du contrôle. Mais cela ne devrait pas arriver quand il est en état Checed. – Prabu
J'ai mis à jour ma réponse initiale. Vous devez utiliser un déclencheur multidata et définir des conditions supplémentaires. –
Le problème avec MultiDataTrigger est que l'un ou l'autre changement de condition peut provoquer l'animation. Par exemple, dans ce cas, si la souris de l'utilisateur est ailleurs dans l'interface utilisateur et qu'elle change de données, la case à cocher est vérifiée, l'animation est lue même si la souris n'est pas proche. (Notez également que vous avez omis la deuxième condition dans votre MultiDataTrigger, que je suppose être ' ') –