Style Setter中的行为无法正常工作

在我的Windows-Runtime应用程序中,我有一个主题,其样式具有为DoubleTapped操作定义的行为:

这些是XML命名空间:

 xmlns:i="using:Microsoft.Xaml.Interactivity" xmlns:core="using:Microsoft.Xaml.Interactions.Core" 

这就是风格:

               

这是我的Behavior

 [DefaultEvent(typeof(ScrollViewer),"DoubleTapped")] public class ScrollViewerDoubleTap : DependencyObject, IAction { public object Execute(object sender, object parameter) { ScrollViewer sv = (ScrollViewer)sender; if (sv.HorizontalScrollBarVisibility == ScrollBarVisibility.Disabled) { sv.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; } else { sv.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled; } return sender; } } 

这就是我使用它的方式:

      

当我在具有此样式的页面上双击第一个图像时,它完美地工作; 但是,当我双击页面上的其他图像时,行为代码永远不会运行。 我知道它永远不会运行,因为我用断点运行它,当我双击第一个图像时它会破坏,但不是第二个。 我会很感激为什么会这样。

这不起作用,因为行为,动作或触发器被设计为附加到单个元素。 当你在一个样式的setter中定义它时,就像你试图将它与多个元素关联起来一样,正如你已经看到的那样,只有当你用这个样式与第一个元素交互时才会调用触发器。

有一种简单的方法可以解决这个问题。 基本上,您需要确保与此样式关联的每个元素都具有您创建的触发器的新实例。 您可以将所有这些逻辑包含在附加属性中,然后您的样式只需要引用此属性。

  

这是附加属性的实现方式。

 public static class FrameworkElementEx { public static bool GetAttachBehaviors(DependencyObject obj) { return (bool)obj.GetValue(AttachBehaviorsProperty); } public static void SetAttachBehaviors(DependencyObject obj, bool value) { obj.SetValue(AttachBehaviorsProperty, value); } public static readonly DependencyProperty AttachBehaviorsProperty = DependencyProperty.RegisterAttached("AttachBehaviors", typeof(bool), typeof(FrameworkElementEx), new PropertyMetadata(false, Callback)); private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var behaviors = Interaction.GetBehaviors(d); var eventTriggerBehavior = new EventTriggerBehavior { EventName = "DoubleTapped" }; eventTriggerBehavior.Actions.Add(new ScrollViewerDoubleTap()); behaviors.Add(eventTriggerBehavior); } } 

我们可以使用纯XAML来做到这一点

…和一个可重用的附加属性,它接收带有BehaviorCollection (或单个Behavior )的DataTemplate

您无需更改代码隐藏。

  

或者,如果您一次只需要一些Behaviors

              

附属物

你甚至不需要改变它。

 using Microsoft.Xaml.Interactivity; using Windows.UI.Xaml; using System; namespace MyBehaviors { public static class AttachedBehaviorsEx { public static DataTemplate GetAttachedBehaviors(DependencyObject obj) { return (DataTemplate)obj.GetValue(AttachedBehaviorsProperty); } public static void SetAttachedBehaviors(DependencyObject obj, DataTemplate value) { obj.SetValue(AttachedBehaviorsProperty, value); } public static readonly DependencyProperty AttachedBehaviorsProperty = DependencyProperty.RegisterAttached("AttachedBehaviors", typeof(DataTemplate), typeof(AttachedBehaviorsEx), new PropertyMetadata(null, Callback)); private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e) { BehaviorCollection collection = null; var template = (DataTemplate)e.NewValue; if (template != null) { var value = template.LoadContent(); if (value is BehaviorCollection) collection = (BehaviorCollection)value; else if (value is IBehavior) collection = new BehaviorCollection { value }; else throw new Exception($"AttachedBehaviors should be a BehaviorCollection or an IBehavior."); } // collection may be null here, if e.NewValue is null Interaction.SetBehaviors(d, collection); } } } 

为什么更好?

与Justin XL建议相比,这是一种更灵活的方式。

他的代码需要修改代码隐藏以便重用它。 每次要重新使用它时,都需要设置EventName (在此行中EventName = "DoubleTapped" )和Behavior (此行eventTriggerBehavior.Actions.Add(new ScrollViewerDoubleTap()); )。