views:

398

answers:

3

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!

A: 

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).

+4  A: 

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>
Daniel Pratt
+2  A: 

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

More info is through these links:

Good luck.