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

发布于 2024-07-16 08:15:40 字数 327 浏览 5 评论 0原文

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

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

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

谢谢!

In my program I have three distinct UI states (Normal, Success, and Error) and in each one the controls are visible/hidden, enabled/disabled, the colors change, labels say different things...etc. and in my code-behind I basically want to be able to say ChangeWindowState(UI.Normal);

So my question is how best to implement the control changes for each state?

Of course I could manually change the controls in the code-behind, but I wonder if maybe there is a better way by using wpf themes or styles. Then maybe I could just set the window to use the "Error" theme, which I have pre-defined. I don't really understand them at the moment so I may be using the terminology wrong, but I would appreciate if someone could point me in the right direction how best to do something like this.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风苍溪 2024-07-23 08:15:40

当然,有很多方法可以解决这个问题。 如果您有程序状态“对象模型”,您可以使用 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>

There are many ways to approach this, of course. If you had a program-state "object model" you could use some combination of DataTemplates and DataTriggers. Assuming this is not the case, here's another approach: You referred to a window, so suppose you define a "dependency property" in your window class like this:

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
}

Now you can change pretty much any property of any element of the window (including the window itself), by either direct binding or a trigger. Here's an example of changing the window's background color via a property trigger:

<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>
爱她像谁 2024-07-23 08:15:40

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

更多信息请访问以下链接:

祝你好运。

Another option for you possibly is the VisualStateManager which was released as part of the WPFToolkit.

More info is through these links:

Good luck.

抠脚大汉 2024-07-23 08:15:40

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

我见过一些以通用方式处理这个问题的尝试......但没有一个是我真正喜欢的(例如 WTL 的东西)。 一般来说,这些实施得不错……但很容易很快超出它们的能力。 一般来说,状态逻辑非常重要,使用简单的 if/then/else 风格逻辑显式编码可以减少混乱(维护、调试等)。

For this sort of thing I've pretty much always done a "UpdateUI()" function. This function looks at the state of the model/member properties/state and enables/disables, hides/shows, whatever. Trying to spread this code out always leads to a problem (so "ChangeWindowsState(..)" really just sets a property and then calls "UpdateUI()").

I've seen a few attempts to handle this in a generic way... but none that I really liked (for example the WTL stuff). Generally these are not badly implemented... but just easy to quickly exceed what they can do. And generally the state logic is important enough that having it explicitly coded with simple if/then/else style logic leads to less confusion (maintenance, debugging, etc).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文