【问题标题】:Switching State (C#/Windows Forms)切换状态(C#/Windows 窗体)
【发布时间】:2011-06-10 10:31:45
【问题描述】:

所以我认为枚举可以帮助我处理状态。基本上,我有一个小侧边栏应用程序,它有 3 种状态:

最小化 - 您可以在其中看到一个小的彩色矩形面板,指示应用程序已在桌面上打开。

预览 - 表示应用已打开,您可以看到徽标。

正常 - 可以看到整个侧边栏。

现在,我已经设置了一个这样的枚举:

public enum CurrentState
{
    Minimized = 0,
    Preview,
    Normal
};

当用户单击始终可见的面板时,我正在尝试检查 CurrentState 并像这样切换到另一个:

    // If Min=Set(Preview). If Preview=Set(Normal). If Normal=Set(Min).
    if (State.HasFlag(CurrentState.Minimized))
    {
        State = CurrentState.Preview;
        this.Location = new Point(
            Screen.PrimaryScreen.WorkingArea.Right - _minimize.Size.Width - _logo.Size.Width,
            this.Location.Y
        );
    }
    else if (State.HasFlag(CurrentState.Preview))
    {
        State = CurrentState.Normal;
        this.Location = new Point(
            Screen.PrimaryScreen.WorkingArea.Right - this.Size.Width,
            this.Location.Y
        );
    }
    else
    {
        State = CurrentState.Minimized;
        this.Location = new Point(
            Screen.PrimaryScreen.WorkingArea.Right - _minimize.Size.Width,
            this.Location.Y
        );
    }

当应用程序加载时,我将初始值设置为:

CurrentState.Minimized;,像这样:

CurrentState State = CurrentState.Preview;

所以,这是预期的行为:

如果表单被最小化,移动它一点使其处于预览模式。如果它处于预览状态,请将其移动一点,使其处于正常模式。如果它处于正常模式,请再次将其设置为最小化。

但是,第一次单击始终可见的面板时,它会按预期工作。它将其设置为预览模式并稍微移动了表单。

但是,仅此而已。一旦进入预览模式,第二次点击面板就不会进入普通模式,这意味着目前无法进入普通模式。

我在这里做错了吗?

虽然这可能不常见,但这是合乎逻辑的,我不知道哪里出了问题。

这里有一点视觉效果,可以帮助更好地阐明我的意思:

【问题讨论】:

  • 无论HasFlag 是什么,它都是多余的或者完全是错误的。您应该只比较单个枚举值。除非你想同时支持多个状态,我不认为你想要。
  • 我只想在任何给定时间支持 1 个状态。在执行此操作之前,我在 Google 中查找了 enum c#,并且 HasFlag() 在枚举部分中遍布 MSDN。而且我似乎不能再只比较值了 - 告诉我我正在像变量一样使用它(但它是一种类型)。
  • @Piotr - 是的。行得通。没有错误/异常,断点什么都不显示,现在不知道该怎么做:$

标签: c# .net winforms enums


【解决方案1】:

你拥有的代码总是进入 if/else 结构的最小化分支。

下面的代码不使用标志而是比较枚举正常工作并根据需要在状态中前进:

if (State == CurrentState.Minimized)    
{        
    State = CurrentState.Preview;                        
}    
else if (State == CurrentState.Preview)    
{        
    State = CurrentState.Normal;                        
}    
else    
{        
    State = CurrentState.Minimized;                        
}

一个想法是实现State pattern,这可能会使这个设计更容易使用。

顾名思义,这种设计模式正好可以解决您要解决的问题。

基本上,您的三个状态的逻辑将被拆分为三个单独的对象,这些对象实现类似IWindowState 的东西,其中 IWindow 状态包含一个名为 MoveState 的方法。当调用MoveState 时,Minimized 窗口的状态对象知道下一个状态是 Preview,Preview 对象知道进入 Normal。

对于您的情况,这可能是设计过度,但只要您想要任何更复杂的逻辑,例如“从最小化移动到预览,除非用户有直接移动到正常的设置”,那么该模式在正确管理方面会为自己付出代价复杂性。

【讨论】:

  • 哦,谢谢!我以前就是这样做的。我试图通过查看 MSDN 来弄清楚,但枚举上的整个页面现在只使用 HasFlag。谢谢
  • 嗯,完美。 :-) 当计时器用完时,我会接受作为答案。 :)
【解决方案2】:

您的问题是HasFlag。您永远不会到达 else 子句,因为您的枚举总是具有最小化标志,即 0。

if 语句中测试相等性:if (State == CurrentState.Minimized) ...

【讨论】:

    【解决方案3】:

    您错误地使用了 has 标志。 (或者你的枚举是错误的)

    如果你使用标志,枚举应该是

    [Flags]
    public enum CurrentState
    {
        Unknown = 0,
        Minimized = 1,
        Preview = 2,
        Normal = 4
    };
    

    更多关于标志的文章可以在herehere 找到

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多