1

I am trying to keep track of state in a WPF application using MVVM. I just want there to be one state active at a time, but the way I'm currently doing it seems unreliable and not very DRY.

Here's an abstracted version of my code:

public class ApplicationStates
{
    public void SetStateOne()
    {
        IsThisStateOne = true;
        IsThisStateTwo = false;
        IsThisStateThree = false;
    }

    public void SetStateTwo()
    {
        IsThisStateOne = false;
        IsThisStateTwo = true;
        IsThisStateThree = false;
    }

    public void SetStateThree()
    {
        IsThisStateOne = false;
        IsThisStateTwo = false;
        IsThisStateThree = true;
    }

    public bool IsThisStateOne { get; set; }
    public bool IsThisStateTwo { get; set; }
    public bool IsThisStateThree { get; set; }
}

My plan is to bind my view's appropriate XAML objects to the boolean properties to maintain the view's state. I would like to continue having objects that I can bind to where they can do things depending on whether they are set to true or false.

Any ideas on making this more DRY, or is there a completely different, better way to architect this?

EDIT 1

I would like my XAML to look somewhat like this:

<Button Visibility="{Binding IsThisStateOne, Converter={StaticResource boolToVisibilityConverter}}"/>

<Button Visibility="{Binding IsThisStateTwo, Converter={StaticResource boolToVisibilityConverter}"/>

That way I can have what I need visible or not based on the state. And the state would change based on changes in the ViewModel.

Conceptually, since there are more than two states, I could make a converter that checks the name of a string converter parameter ("IsThisStateOne", "IsThisStateTwo") against the string of the enum, but that gets back into magic strings and duplication of non-type-safe code which I would like to avoid.

I understand databinding to the enum directly, I guess I just don't understand how to change the state of that enum (I can have a description string, but I don't think I can change it).

EDIT 2

Removed the enum. I don't really care if there is an enum involved or not, I just thought it would make things a little more strongly typed.

I guess I just want to know if there is a better, established design pattern for this type of requirement.

jporcenaluk
  • 966
  • 10
  • 25
  • 1
    This almost sounds like you want to just have the `AvailableStates` property, and then use a [Trigger](http://wpftutorial.net/Triggers.html) to accomplish what you want, so that when the state is equal to some value, it sets dependency properties on various elements in your view. – Tejs Feb 05 '14 at 19:51
  • possible duplicate of [Databinding an enum property to a ComboBox in WPF](http://stackoverflow.com/questions/58743/databinding-an-enum-property-to-a-combobox-in-wpf) – Justin Pihony Feb 05 '14 at 20:21
  • @JustinPihony If I were to just databind to an enum, where do I define the state for each enum? I'll edit my question so it is more specific. – jporcenaluk Feb 05 '14 at 20:44
  • @JustinPihony I updated my question to get rid of the distracting enum. If enums should be involved, then I will use them, but I think they were distracting from the real requirement - I want one state to be active all the time, and only one, and I want to be able to bind to XAML. I want to be able to choose which one is active using methods. I can do it the way I have it here, but it isn't very strongly typed (though it is quite simple)... – jporcenaluk Feb 05 '14 at 21:04
  • @Tejs I'm reading about dependency properties right now via [codeproject.com](http://www.codeproject.com/Articles/140620/WPF-Tutorial-Dependency-Property) – jporcenaluk Feb 05 '14 at 21:07

2 Answers2

4

Since only one state can be active at any given time, I would model it as follows:

public enum AppState { StateOne, StateTwo, StateThree }

public class MyApplication
{
    public AppState CurrentState { get; set; }

    // helper properties for UI binding
    public bool IsThisStateOne { get { return CurrentState == AppState.StateOne; }
    public bool IsThisStateTwo { get { return CurrentState == AppState.StateTwo; }
    public bool IsThisStateThree { get { return CurrentState == AppState.StateThree; }
}

This keeps repetition to a minimum and still allows simple Boolean binding from XAML.

If you want the UI to update automatically after a state change, you'd need to call PropertyChanged on the helper properties in the setter of CurrentState.

Heinzi
  • 167,459
  • 57
  • 363
  • 519
3

I would keep the properties for simplicity of binding. But make them read-only, and keep a common variable (enum, string, int, whatever's easiest):

public void SetState(int stateNum)
{
    _state = stateNum;
}
private int _state = 1;

public bool IsThisStateOne { get { return _state == 1; } }
public bool IsThisStateTwo { get { return _state == 2; } }
public bool IsThisStateThree { get { return _state == 3; } }
McGarnagle
  • 101,349
  • 31
  • 229
  • 260
  • Nice work. @Heinzi answered very similarly (and I like his use of enums), but you were first. Thanks for the help! – jporcenaluk Feb 05 '14 at 21:13