实现行为的更好方法

Better way to implement a behavior

我对 WPF 和行为比较陌生。

我有这种行为,每次在 ViewModel 中设置 IsRedundant 时都需要执行 DoSomething()。

每次我需要触发 DoSomething 时,我都需要更改 属性 的值,这很令人困惑(如果 ture => 将其设置为 false,如果 false => 将其设置为 true) . IsRedundant 仅用于引发 属性 已更改事件,除此之外别无他用。

有没有更好的方法来实现这个目标?

有什么想法吗?

wpf

  <i:Interaction.Behaviors>
                    <local:UIElementBehavior  Redundant="{Binding IsRedundant, Mode=TwoWay}"/ >
   </i:Interaction.Behaviors>

C#

class UIElementBehavior : Behavior<UIElement>
    {
        public static readonly DependencyProperty RedundantProperty = DependencyProperty.Register(
                "Redundant",
                typeof(bool),
                typeof(UIElementBehavior),
                new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, DoSomething));

        public bool Redundant
        {
            get { return (bool)GetValue(RedundantProperty); }
            set { SetValue(RedundantProperty, value); }
        }

        private static void DoSomething(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            //Do something on the AssociatedObject
        }

    }

Each time I need to trigger DoSomething, I would need to change the value of the property and this is confusing (if true => set it to false, If false => set it to true)

问题是您正在使用绑定。绑定所需的目标是依赖项 属性。那些是特殊的,它们的设置器不会被调用,因此当它们的值通过绑定更改时,您必须使用回调来获得通知。

此外,内部会检查值是否不同,出于性能原因,如果值相同则不会调用回调,因此您必须像您已经做的那样更改它。


另一种解决方案是在视图模型中简单地添加事件:

public class ViewModel: INotifyPropertyChanged
{
     public EventHandler SomethingHappens;
     // call this to tell something to listener if any (can be view or another view model)
     public OnSomethingHappens() => SomethingHappens?.Invoke(this, EventArgs.Empty);

     ...
}

现在您可以subscribe/unsubscribe在视图中to/from这个事件并在事件处理程序中做一些事情。如果您是纯粹主义者,请将视图中的代码重构为可重用的行为。

短吗?没有。是不是更清楚了?是的,与使用 bool 和这样的 "wonderful" 代码相比:

IsRedundant = false;
IsRedundant = true; // lol

我过去像您一样使用 bool 属性来通知视图。

然后我用到了事件

现在我结合使用两者。每个视图模型都已经实现了 INotifyPropertyChanged 那么为什么不使用它呢?

IsRedundant 视为 状态 。它不仅可以用来触发一些方法,还可以被视图用来通过数据触发器运行动画,控制动态布局的可见性等。所以你需要一个普通的bool属性 在视图模型中。

然后视图可以从 PropertyChanged 订阅 to/unsubscribe 并且只需要检查:

if(e.PropertyName == nameof(ViewModel.IsRedudant)) { ... }