让我们假设我们有一个只有一个状态变量的简单UI。该状态表示为枚举值,例如。 Phase1,Phase2等。取决于UI处于哪个状态(阶段),不同的UI元素,窗口应该是可见的还是隐藏的。

这是代码:

public enum Phases { Phase1, Phase2, Phase3 }

public class UIStateModel : DependencyObject
{
    public static DependencyProperty CurrentStateProperty =
        DependencyProperty.Register("CurrentStateProperty",
                                    typeof(Phases),
                                    typeof(UIStateModel));
    public Phases CurrentState
    {
        get { return (Phases)GetValue(CurrentStateProperty); }
        set { SetValue(CurrentStateProperty, value); }
    }
    public Visibility Window1Visible // Databound to Window1.Visibility
    {
        get
        {
            if (this.CurrentState == Phases.Phase1) return Visibility.Visible;
            else return Visibility.Hidden;
        }
    }
    public Visibility Window2Visible // Databound to Window2.Visibility
    {
        get
        {
            if (this.CurrentState == Phases.Phase2) return Visibility.Visible;
            else return Visibility.Hidden;
        }
    }
    ...
}


问题在于,由于WindowXVisible属性不是DependencyProperty-s,因此无法使用上述代码进行数据绑定。如果我将所有属性都转换为DependencyProperty,则将冗余引入状态管理。除了使所有内容保持同步的额外负担外,它甚至可能变得不一致(如果我无法很好地同步)。

避免在UI状态管理中引入冗余但仍然利用DependencyProperty-s促进的数据绑定功能的正确方法是什么?

最佳答案

您可以使用INotifyPropertyChanged。当CurrentState更改时,只需发送给定WindowXVisible的更改通知(对此DP has a callback)。

绑定通常可以通过DependencyProperty或INotifyPropertyChanged通知(与DP不同,必须手动发送)来侦听更改。

您可以使用this tool自动生成通知调用(而不会稍微增加代码的复杂性)。它甚至可以很好地处理此类非平凡的案件。

编辑:

将其注册到CurrentStateProperty的PropertyMetadata中。

    private static void OnCurrentStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        this.OnPropertyChanged("CurrentState");
        this.OnPropertyChanged("Window1Visible");
        this.OnPropertyChanged("Window2Visible");
    }


OnPropertyChanged只需调用PropertyChanged事件,并将此作为发送方,并将字符串作为属性名称。

这将导致Window1Visible和Window2Visible绑定更新并获取新值。

顺便说一句,您应该尝试找出比Window1和WIndow2更好的名称。

10-07 19:01
查看更多