I have used ValueConverters
in some cases and put the logic in the ViewModel
in others. My feeling is that a ValueConverter
becomes part of the View
layer, so if the logic is really part of the View
then put it there, otherwise put it in the ViewModel
.
Personally I don't see a problem with a ViewModel
dealing with View
-specific concepts like Brush
es because in my applications a ViewModel
only exists as a testable and bindable surface for the View
. However, some people put a lot of business logic in the ViewModel
(I do not) and in that case the ViewModel
is more like a part of their business layer, so in that case I wouldn't want WPF-specific stuff in there.
I prefer a different separation:
View
- WPF stuff, sometimes untestable (like XAML and code-behind) but also ValueConverter
s
ViewModel
- testable and bindable class that is also WPF-specific
EditModel
- part of the business layer that represents my model during manipulation
EntityModel
- part of the business layer that represents my model as persisted
Repository
- responsible for persistence of the EntityModel
to the database
So, the way I do it, I have little use for ValueConverter
s
The way I got away from some of your "Con's" is to make my ViewModel
's very generic. For instance, one ViewModel
I have, called ChangeValueViewModel
implements a Label property and a Value property. On the View
there's a Label
that binds to the Label property and a TextBox
that binds to the Value property.
I then have a ChangeValueView
which is a DataTemplate
keyed off of the ChangeValueViewModel
type. Whenever WPF sees that ViewModel
it applies that View
. The constructor of my ChangeValueViewModel
takes the interaction logic it needs to refresh its state from the EditModel
(usually just passing in a Func<string>
) and the action it needs to take when the user edits the Value (just an Action
that executes some logic in the EditModel
).
The parent ViewModel
(for the screen) takes an EditModel
in its constructor and just instantiates the appropriate elementary ViewModel
s such as ChangeValueViewModel
. Since the parent ViewModel
is injecting the action to take when the user makes any change, it can intercept all of these actions and take other actions. Therefore, the injected edit action for a ChangeValueViewModel
might look like:
(string newValue) =>
{
editModel.SomeField = newValue;
foreach(var childViewModel in this.childViewModels)
{
childViewModel.RefreshStateFromEditModel();
}
}
Obviously the foreach
loop can be refactored elsewhere, but what this does is take the action, apply it to the model, then (assuming the model has updated its state in some unknown way), tells all the child ViewModel
s to go and get their state from the model again. If the state has changed, they are responsible for executing their PropertyChanged
events, as necessary.
That handles the interaction between, say, a list box and a details panel quite nicely. When the user selects a new choice, it updates the EditModel
with the choice, and the EditModel
changes the values of the properties exposed for the detail panel. The ViewModel
children that are responsible for displaying the detail panel information automatically get notified that they need to check for new values, and if they've changed, they fire their PropertyChanged
events.
The only compelling reason to use XML is to establish an open data standard. XAML is the same display language used in both Silverlight and WPF; any vendor can use the same markup standard to create a display definition for their own platform, and it can be reused in Silverlight or WPF.
In the aerospace industry, we have control rooms that, thanks to the advances of computer technology, are now reasonably flexible. In the past, all the hardware was custom, unique, and very expensive; today it is all run with inexpensive, commonly-available, off-the-shelf PC's. This greatly reduces vendor lock in. However, display widgets are still written using ActiveX, because that's how it's always been done.
ActiveX requires access to Microsoft tools that are, well, obsolete. So the Air Force and the Inter-Range Instrumentation Group is coming up with a Data Display Markup Language, which is XML based. This will allow practitioners to design displays using XML markup, in the editor of their choice. Sound familiar?
Nobody argues that XML is not without its faults. But it's the best thing available for what it was designed to do, until something better comes along.
See Also
Why XML Doesn't Suck
Best Answer
There is no "official" best practice rules. There is however a Google Group that wants to establish these best practices: https://groups.google.com/group/wpf-disciples/web/wpf-and-xaml-coding-guidelines?hl=en. There even are some propositions on how to organize these files for bigger projects (company scale)
Their propositions look reasonable.