tags:

views:

304

answers:

2

I have a task management program with a "Urgency" field. Valid values are Int16 currently mapped to 1 (High), 2 (Medium), 3 (Low), 4 (None) and 99 (Closed). The urgency field is used to rank tasks as well as alter the look of the items in the list and detail view.

When a user is editing or adding a new task they select or view the urgency in a ComboBox. A Converter passes Strings to replace the Ints. The urgency collection is so simple I did not make it a table in the database, instead it is a, ObservableCollection(Int16) that is populated by a method.

Since the same screen may be used to view a closed task the "Closed" urgency must be in the ItemsSource but I do not want the user to be able to select it. In order to prevent the user from being able to select that item in the ComboBox but still be able to see it if the item in the database has that value should I...

  1. Manually disable the item in the ComboBox in code or Xaml (I doubt it)
  2. Change the Urgency collection from an Int16 to an Object with a Selectable Property that the isEnabled property of the ComboBoxItem Binds to.
  3. Do as in 2 but also separate the urgency information into its own table in the database with a foreign key in the Tasks table
  4. None of the above (I suspect this is the correct answer)

I ask this because this is a learning project (My first real WPF and first ever MVVM project). I know there is rarely one Right way to do something but I want to make sure I am learning in a reasonable manner since it if far harder to Unlearn bad habits

Thanks

Mike

+1  A: 

I would favor option 2. Sounds very MVVM-stylish to me.

Option 3 would be favorable, when there are other applications or when you have reports accessing the "Urgency" field. Reason: Otherwise you will need to duplicate the knowledge of mapping between Int16 and their meaning. Move the knowledge to the database to keep it in one place.

Maybe consider Enums to make the code more expressive:

enum Urgency { High=1, Medium=2, Low=3, Closed=99 };

This way you will have something nice looking for evaluating the IsEnabled property like this:

if (urgency == Urgency.Closed) return false;

When you need to store the numeric value of the enum, you will need to make a cast to Int16 beforehand.

Theo Lenndorff
Thanks for the feedback. I should look at the enum option again. I tried to do that originally but I was having a lot of challenges getting the enum collection to populate the combobox. I am a lot more comfortable with the ComboBox now so I suspect it would work fine. I had not thought about the reporting issue, IIRC in my print code I am using the same converter the xaml uses to get the strings.
Mike B
Just a note: Option 3 would make the Enum solution less attractive, since you would again duplicate this knowledge.
Theo Lenndorff
+1  A: 

I think that I'd first fix this in the view. Have a TextBlock that displays "Closed", and a ComboBox that displays the other values, and then use a data trigger to set IsVisible on both depending on whether or not Urgency is 99.

I'd do this not because it's the best technical solution (it's probably not) but because it's (possibly) the best UI solution. If the user can't ever modify a closed item, it's a little misleading to display "Closed" even in a disabled ComboBox, since the ComboBox means, visually, "Here's something you can change." That it's disabled just prompts the user to wonder what he has to do to enable it. Using a TextBlock is an unambiguous way of saying "this is just how it is."

Robert Rossney
Hey, I like that idea, I am a fan of UI first programming but, unfortunately I am the worst kind of person to design a UI (A programmer). I was already planning on binding the IsEnabled property on all the fields in the Add/Edit window but I will change all the ComboBoxes to TextBlocks as well... Man does Xaml get a bit long or what?
Mike B
It never gets concise, exactly, but as you learn to work with templates and styles and the view model pattern it gets a *lot* more manageable.
Robert Rossney