如何最好地实现UI状态机?

5
在我的程序中,我有三个不同的UI状态(Normal、Success和Error),在每个状态下,控件是可见/隐藏的,启用/禁用的,颜色改变,标签说不同的事情...等等,在我的代码后台中,我基本上想能够说ChangeWindowState(UI.Normal)。
所以我的问题是如何最好地实现每个状态的控制更改?
当然,我可以手动更改代码后面的控件,但我想知道是否有更好的方法,比如使用wpf主题或样式。然后也许我只需要设置窗口使用预定义的“Error”主题。我现在不太理解它们,所以我可能使用术语不正确,但我会感激如果有人能指点我如何最好地做这样的事情。
谢谢!
3个回答

5

当然,有很多方法可以解决这个问题。如果你拥有一个程序状态的“对象模型”,那么你可以使用一些数据模板和数据触发器的组合方式。假设情况并非如此,这里提供另一种方法:你提到了一个窗口,所以假设你在窗口类中定义了一个“依赖属性”,如下所示:

public partial class Window1 : Window
{
    public Window1()
    {
        this.InitializeComponent();

        // Insert code required on object creation below this point.
    }

    public ProgramStatus ProgramStatus
    {
        get { return (ProgramStatus)GetValue(ProgramStatusProperty); }
        set { SetValue(ProgramStatusProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ProgramStatus.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ProgramStatusProperty =
        DependencyProperty.Register("ProgramStatus", typeof(ProgramStatus), typeof(Window1), new UIPropertyMetadata(null));
}

public enum ProgramStatus
{
    Normal,
    Success,
    Error
}

现在,您可以通过直接绑定或触发器更改窗口(包括窗口本身)的任何元素的任何属性。以下是通过属性触发器更改窗口背景颜色的示例:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:Test"
    x:Class="Test.Window1"
    x:Name="Window"
    Title="Window1"
    Width="640" Height="480">
    <Window.Style>
        <Style TargetType="{x:Type l:Window1}">
            <Style.Triggers>
                <Trigger Property="ProgramStatus">
                    <Trigger.Value>
                        <l:ProgramStatus>Error</l:ProgramStatus>
                    </Trigger.Value>
                    <Setter Property="Background" Value="Red" />
                </Trigger>
                <Trigger Property="ProgramStatus">
                    <Trigger.Value>
                        <l:ProgramStatus>Normal</l:ProgramStatus>
                    </Trigger.Value>
                    <Setter Property="Background" Value="Blue" />
                </Trigger>
                <Trigger Property="ProgramStatus">
                    <Trigger.Value>
                        <l:ProgramStatus>Success</l:ProgramStatus>
                    </Trigger.Value>
                    <Setter Property="Background" Value="Green" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Style>
    <Grid x:Name="LayoutRoot"/>
</Window>

3

1
对于这种情况,我通常会编写一个“UpdateUI()”函数。该函数查看模型/成员属性/状态的状态并启用/禁用、隐藏/显示等操作。试图将这些代码分散开始通常会导致问题(因此,“ChangeWindowsState(..)”实际上只设置属性,然后调用“UpdateUI()”)。
我已经看到了一些尝试以通用方式处理这个问题的方法……但没有一个真正让我满意(例如WTL的东西)。一般来说,它们实现得还不错……但很容易迅速超出其能力范围。而且通常状态逻辑非常重要,明确地使用简单的if/then/else风格逻辑进行编码可以减少混淆(维护、调试等方面)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接