实现行为的更好方法

时间:2018-03-14 13:15:05

标签: c# wpf 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
        }

    }

1 个答案:

答案 0 :(得分:0)

  

每次我需要触发DoSomething时,我需要更改属性的值,这是令人困惑的(如果true =&gt;设置为false,如果false =&gt;将其设置为true)

问题是你正在使用绑定。绑定所需的目标是依赖属性。这些是特殊的,它们的setter不会被调用,所以当你的值通过绑定改变时,你必须使用回调来获取信息。

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

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

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);

     ...
}

现在,您可以在视图中订阅/取消订阅此事件,并在事件处理程序中执行某些操作。如果您是纯粹主义者,则将视图中的代码重构为可重用行为。

更短吗?不。它更清楚了吗?是的,与使用bool“精彩”代码相比:

IsRedundant = false;
IsRedundant = true; // lol

我过去使用bool属性来通知视图。

然后我使用了活动。

现在我使用两者的组合。每个视图模型都已实现INotifyPropertyChanged,为什么不使用它?

IsRedundant视为。它不仅可用于触发某些方法,还可用于视图通过数据触发器运行动画,控制动态布局的可见性等。因此,您需要在视图模型中使用普通bool属性。

然后视图可以订阅/取消订阅PropertyChanged,只需检查:

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