实现行为的更好方法
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)) { ... }
我对 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)) { ... }