实现UI状态机的最佳方法是什么?

时间:2009-04-05 22:00:11

标签: wpf user-interface state-machine

在我的程序中,我有三种不同的UI状态(正常,成功和错误),每一种控件都是可见/隐藏,启用/禁用,颜色改变,标签说不同的东西......等等。在我的代码隐藏中,我基本上希望能够说出ChangeWindowState(UI.Normal);

所以我的问题是如何最好地为每个州实施控制变更?

当然我可以手动更改代码隐藏中的控件,但我想知道是否有更好的方法可以使用wpf主题或样式。那么也许我可以设置窗口使用我预先定义的“错误”主题。我现在对它们并不是很了解,所以我可能会使用错误的术语,但如果有人能指出我正确的方向,那么我会很感激。如何最好地做这样的事情。

谢谢!

3 个答案:

答案 0 :(得分:5)

当然,有很多方法可以解决这个问题。如果你有程序状态“对象模型”,你可以使用DataTemplates和DataTriggers的某种组合。假设情况并非如此,这是另一种方法:你引用了一个窗口,所以假设你在窗口类中定义了一个“依赖属性”,如下所示:

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>

答案 1 :(得分:3)

另一个选项可能是VisualStateManager,它是作为WPFToolkit的一部分发布的。

通过以下链接获取更多信息:

祝你好运。

答案 2 :(得分:1)

对于这类事情,我几乎总是做一个“UpdateUI()”函数。此函数查看模型/成员属性/状态的状态,并启用/禁用,隐藏/显示等等。试图传播此代码总是会导致问题(因此“ChangeWindowsState(..)”实际上只是设置一个属性,然后调用“UpdateUI()”)。

我已经看到了一些尝试以一般方式处理这个...但没有我真正喜欢的(例如WTL的东西)。一般来说,这些都没有得到很好的实施......但很容易快速超出他们的能力。通常情况下,状态逻辑非常重要,只需使用简单的if / then / else样式逻辑进行显式编码,就可以减少混淆(维护,调试等)。