I struggle to understand the purpose of the ViewModel sometimes, especially with respect to what it should and shouldn't do.
So... I find myself wanting to expose a display string from my ViewModel. Ok, actually it's a Date string, where I want to display something like "Unknown" if the date isn't set. Really I want a solution to cover the general case, so I don't want a discussion about using null and fallback values. It could equally be a status message like "Awaiting Dispatch" or "Launch Aborted".
So the quesion is, how should the ViewModel expose display strings to the View. The App will need to be localized, so we can't have hard coded strings in the ViewModel.
Is it ok to access the app's resources from the ViewModel, and return the display string?
As an aside, should I be using a resx string resource, or a Xaml resource dictionary? I'm leaning toward the Xaml. Advantages/Disadvantages?
Thanks,
Mark
As mentioned in the other answers, this is clearly the view's responsibility. The view model should expose the data property (a status enum or something similar) for the view to inspect in order to determine the particulars of the display message. From a purist's perspective, generating display properties from the VM or code behind is right out.
I'm surprised to hear no suggestions of datatriggers, though. Use them in your TextBlock to bind to the exposed status enum value and update the text appropriately. This question compares their performance against binding to a converter and suggests that triggers will perform better in this scenario. I haven't done any testing myself, so I'm not sure, but it seems intuitively reasonable to me, provided you aren't listening for an outrageous number of different enum values. I also think it's the more appropriate method in this case, and I'll cite this question asking for a comparison of VC vs. DT use cases, though I don't think it's terribly contentious. To put it another way, if one holds that a VM is a value converter on steroids (a statement which I'm very leery of and will not agree or disagree with at the moment), then this argument holds: a VM shouldn't be exposing display properties; a VM's purpose and abilities are a super-set of those of a VC; therefore, a VC should not be exposing display properties.
I'm doing my best to give the purist's answer (or what I think it is, at least), but there are certainly easier ways to code it than writing a lot of datatriggers, especially if you have many different values to address.
Regarding your resource question, have a look at this MSDN article on resource files, which is, in certain ways, easier to work with than a resx file. Which approach you should use depends on your use cases.
What you are doing is taking data that is inside the system and converting it to a format that makes it more useful and clear to the user. This is the responsibility of the view. It would be the responsibility of the view to format a valid date into the correct culture and it has the same responsibility for any text that you wish to display.
In the same respect the status examples you give would probably be stored as an enum in the viewmodel (since that would make it easier to apply business logic to them, which is the role of the viewmodel) and it would be the responsibility of the view to display the values in a way that works for the user in all respects. This would include size, colour, font, position and culture.
That being said though I have been known to put display logic in my viewmodel (concatenating firstname and surname for example) simply because it is easier. I've even been known to use code-behind (shock, horror!) where it suits my purpose. There is a sliding scale between purity and pragmatism, and it is up to you where you sit on that line.
To display the string Unknown when the date is not set is a display issue and therefore has to be solved in the view. Even "Awaiting dispatch" is a presentation of a value.
So the answer is: The view model should never expose display strings. The view model has to expose a value that leads the view/a converter/whatever object from the presentation layer to choose a display string.
Even if this answer is not the answer you want to read, it is the answer an MVVM purist has to give. And as you asked for MMVM purists, here it is.
For the date, I would have the ViewModel export a nullable DateTimeOffset, where the null value means "not set". The in the View (via a converter or similar), the null value is displayed as whatever you need.
As to the aside: I would use resx. The reason is that there is a defined fallback mechanism when strings aren't available in the language.
An approach I have taken was creating Culture specific Resources and adding instances (singletons?) of these to the ViewModel.
Then the View can simply Bind to the ViewModel.Resource.DisplayString
See this article for Windows Phone 7 which easily translates to WPF.
If you dislike this because you do not want to tie the culture specific resource to the ViewModel and want the View to solve it you could use/write a ValueConverter that turns a value from a VM property into a display string.
Related
Advance apologies for the event-style explanation; there's a lot of factors that I feel all play a role of their own. WPF is not my native framework of choice, and it probably shows. :)
Old situation: I had a window with several controls. Depending on their selections, I used multibindings and a converter to determine whether certain controls needed to be shown that inform the user about the implications of their changes before they'd eventually confirm them by OK (or simply dismissed by using Cancel). This worked perfectly.
Problem: Too many controls as time went by, too much clutter.
Solution: Put stuff in different Pages so it becomes easier to browse for the user. In order to have changes-to-be persist as a user arbitrarily browses between the pages, I create these dynamically and put them in a cache (Dictionary<string, BasePage>, see below), from which they will be pulled as the user chooses them.
Consequence: I need to decouple the bindings to the notification controls as the different options are now on different pages.
Solution? I put a BasePage class in that exposes certain abstract read-only properties that define the various aspects that the window needs to know about in order to do its notifications. For example, a bool requiresReboot property defines whether the current state of things on that page requires a reboot to take (full) effect. A specific page implements the property based on its controls.
Problem: I do not know how to keep create a proper binding that properly gets updated as the pages are changed. I tried giving my notification controls a binding to the Dictionary<string, BasePage> with a converter that checks all pages and the relevant property.
Questions:
1) How do I create a proper property for this purpose? I presume I need a DependancyProperty as I did a fair bit of reading on MSDN, but I can't figure out how this fits together.
2) How do I make a link between my custom property so that it allows (multiple) control(s) on a page to change that property? Do I use INotifyPropertyChanged somehow? My old example bound against several CheckBox.IsChecked properties in XAML. I am trying to avoid putting tons of events (OnChange, etc) on the controls as the original code did not need it and I have been told it makes for a messy solution for as far WPF is concerned.
3) Finally, I suspect I may need to change my Dictionary<string, BasePage> class to a custom implementation that implements some sort of INotifyPropertyChanged but for Collections? Observable Collection is the term I am looking for, I believe.
I hope someone is able to bridge the gap in my understanding of WPF (property) internals; I would very much appreciate it. A basic sample would be even better, but if it is too complicated, just a nudge in the right direction will do. Thank you. :)
It's been a while since I solved this, and while I cannot remember the exact cause of the problems, there were a few different issues that made up the bulk of the trouble I ran into.
I ended up making the Property in question a non-abstract DependencyProperty in the base class; it was the only way in which I could properly delegate the change notifications to the interface. Derived classes simply ended up binding it to their controls (with a proper Converter in the case extra logic was necessitated).
As Dictionary<string, BasePage> does not support any sort of change notification, I made an extra collection of ObservableCollection<BasePage> which I used for binding purposes.
However, such a collection does not propagate a change event when items inside of it has a property changed. Since this situation required that, and I was binding to the collection itself in the context of a property that does not have a Master<->Detail relationship like a DataGrid (which basically add their own OnPropertyChanged handlers to the binded object), I ended up subclassing a VeryObservableCollecton<>. This one listens to its own items, and throws a proper change event (I think it was an OnPropertyChanged from the INotifyPropertyChanged interface) so that the binding (or in this case a multi-binding) would refresh properly and allow my interface to update.
It is hardly the prettiest code, and it feels over-engineered, but at least it allows me to properly bind the UI to the data in this manner.
I'm having trouble deciding what to think about this piece of code:
public SolidColorBrush Brush
{
get { return IsValid ? _validItemBrush : _invalidItemBrush; }
}
It is part of a view model in my current project and as you can imagine, the Brush will be bound to some text elements in the UI, to indicate (in-)validity of other pieces of data, in an otherwise fairly simple and straightforward dialog.
The proponents of this piece of code say that since we're using WPF, we might as well allow for some simple WPF specific constructs in the view model.
The opponents say that this violates Separation of Concerns, as it clearly dictates style which should be taken care of solely by the view.
Please share your arguments, and if you're not happy with the code above, please share your ideas around alternative solutions. (I'm particularly interested in what you have to say about using DataTemplates).
Is it possible that there is one solution that could be considered best practice?
Personally, I would have the two brushes be defined in XAML, and have the controls that use them switch brushes (in xaml) based on the IsValid property. This could be done very easily with DataTriggers, or even a single IValueConverter - the converter could take 2 brushes and a boolean and swap between them fairly easily.
This keeps the business logic presentation-neutral - a "Brush" is very specific to a specific form of presentation, and a pure View choice. Hard-coding this into the ViewModel violates the single responsibility principle as well as is not a clean separation of concerns.
I would very much keep this in the View, and switch based on the IsValid (bound) property that is ViewModel specific.
While there are circumstances where I might use WPF constructs in the view model, this isn't one of them. Here's why:
It's harder to change. If you define brushes as resources and use them in styles, changing your application's color scheme can simply be a matter of loading a different resource dictionary. If you hard-code color values in your view models, you have a lot of different things to change if it turns out your end users need different colors.
It's harder to test. If you want to write a unit test that checks to see if a property is returning the right brush, you have to create a brush in your unit test and compare the values of the two, since it's a reference type.
In many, maybe even most cases, it doesn't make the code simpler or easier to maintain. You're pretty likely to already be using a style (assuming that you are conversant with styles), since they make just about everything in WPF easier. Binding IsValid to brush colors is just a matter of adding a DataTrigger to a style. Which is where anyone maintaining this code would expect to find it.
There are certainly times when I do use WPF constructs in the view model - for instance, long ago stopped wondering if it was problem if a view model exposed a property of type Visibility. Note that none of the above concerns apply to that case.
In cases like yours where it's purely aesthetic I use Triggers or the Visual State Manager to change colors.
Sometimes I do use colors in my ViewModels, but only if its part of my software spec (e.g., the color of the chart displaying a patient's CO2 depends on localization). In that case, I use a Color struct bound property, allowing the View to use the Color for a SolidColorBrush, a GradientStop, or whatever it wants. I initially used a string in #AARRGGBB format to completely remove the WPF dependency but my more seasoned co-workers didn't like that.
If I had a label on a view that I wanted to have the width equal to the width of two columns in one of my grids on the same view, how would I set up the binding without using a converter? Should I use properties to preform my calculation and store a value? It is my intention that if the view's grid size changes then this label's size will also change to match the new width of the two columns.
And where should I put this logic? I am trying to follow MVVM pattern but I see that a lot of threads about "converters in MVVM" say to put the logic into the viewmodel.
I tried to implement this behavior with dependency properties on my view since my viewmodel technically has no knowledge of my view (so how would my viewmodel know how wide my columns currently are?). This goes against what I have read online though. When implementing this behavior I noticed that I cannot reference my columns by name unless my property is not static, but dependency properties are static so I am not sure how to shuffle my values around without creating yet more properties to hold values.
Can someone provide help here? I feel like i'm overcomplicating this. I just need this label to sit over these two columns however they stretch. It just provides a visual grouping of related fields in the grid. Once I can do this first one, the other two should be equally similar.
My rule of thumb is if it's "View" related then keep it away from the ViewModel. From your description this sounds like it's purely view related, so I would just use logic in either the codebehind or a converter.
Now what I don't understand is why you are reluctant to use Converters. With converters you certainly don't want to store business logic that is going to lead to confusion or pain points for refactoring, but if you have some value that needs to be converted for a specific view operation then Converters are exactly what you should be using.
So my advice is Converters ... if it's View related then feel free to use Converters and Codebehind ... in fact you should use them and not the ViewModel.
Does that help?
I often hear a Model must be wrapped by a ViewModel that the View is not coupled to the Model/not aware of it.
With MVC it is common to bind the View to the Model... nobody complains so what ?
I am frightened of creating all that wrappers and doing nearly only duplicating property stuff.
In some cases you don't need to, just as you don't need properties in many cases but can get away with public fields.
But your model should mirror the domain structure and logic, while a view model mirrors the UI structure and logic. At least, as far as I understood it. Those two are not necessarily the same and each one can change independently from the other.
You should always apply a pattern to your individual problem, and modify it in areas where it does not apply. Just because the pattern implies the usage of a view-model, doesn't mean you necessarily need a view-model in every scenario. In the case that your model exposes all of the needed properties and no further abstraction is needed, maybe a view-model is unnecessary.
However, in many cases the view-model will eventually be of great use and far easier to maintain than adding extra properties to the model. Consider this carefully before binding directly to the model.
The ViewModel is used to only pass the data that you really need to a view.
When you use the model, instead of the viewmodel it is possible that you use data that came directly from the database.
When using the model the wrong way, it is possible to edit data in the database that you don't want to edit.
It is safer to use a ViewModel.
One point which didn't seem to come up (directly) yet is that ViewModel can easily support data that should never even be in the model such as the text typed in the search text box or selected list items in case these values are needed in commands or further data bindings and passing them as parameters every time seems like too much trouble.
But as stated already, if you are confident that all the data you need is already available in the Model, go ahead and do away with the ViewModel.
One common scenario where ViewModels come in very handy is when Enum values should be displayed. In my eyes, a ViewModel is the perfect place to convert Enum values to user-friendly representations. You could even introduce a localization step in your ViewModel.
Furthermore, ViewModels can simplify some other scenarios. However, as you said, they can also duplicate a lot of code. That said, you could create a ViewModel with a Model property which allows to bind directly to the properties of the Model class. Now if you later realize that you need some conversion step, you can still add that property to the ViewModel and bind to that property.
But I think in most cases it makes sense to use a ViewModel from the beginning because it might be hard to introduce it in a later development stage.
There is no problem binding directly to a Model from your View where possible.
What you will find though is very quickly you run into a situation where you need to model things your view needs that aren't in your Model.
Given you never want to corrupt your Model with View concerns, you are left with no choice but to create a ViewModel.
It depends on may indicators: e.g. if your model is provided by EF there's no point in exposing it to your View - why the heck the View would need all model's method/properties and tons of stuff (not mentioning data security) But if your model is really simple and you feel, that you're not going to expand/change it much by and VM, there's nothing on the way to use it just like that :)
You might as well ask, "What's wrong with putting all the functionality of my program into one giant class?" On the one hand, there's nothing wrong; it can be made to work. On the other hand, everything is wrong: if your program is one big ball of wire, you have to straighten all of it out in order to change any of it.
Look at a Windows Forms programmer written by a beginner. You'll find all of the business logic in the buttons' Click event handlers. What's wrong with that? Don't you want that logic to be executed when the user clicks the button?
This is essentially what you're proposing doing within the world of WPF. Will it work? Sure. For trivial projects, it may even work well. You're accumulating technical debt, though, and when the time comes, you'll have to pay it off by refactoring your code into something manageable.
We're just getting into MVVM in WPF.
We have implemented our ViewModels with 'strongly typed' properties (int, double? etc.) that we bind to in the view.
Type conversion works OK, mostly, and so entering data is simple enough. But we run into problems with validation.
If, say, a non-numeric value is entered in a text box bound to a numeric property, the conversion fails, the property is never set, and we never get a chance to provide proper feedback to the user. Worse, the property retains its current value, leading to a mismatch between what's displayed in the view and what's actually in the ViewModel.
All this can be handled with value converters, I know. But I have seen several opinions to the effect that conversion should not be the view's responsibility at all. What is entered in the view are strings, and the conversion, validation etc. should be the ViewModel's responsibility (so the argument goes).
If so, we should rewrite most of the properties on our ViewModels to string, and provide error information through the IErrorInfo interface, for example. It would surely make for simpler, leaner XAML in the view. On the other hand, conversion, validation etc. will be less declarative, explicit and flexible, from the point of view of the View designer.
It seems to us these two approaches are fundamentally different, so before we decide, we'd like some informed SO opinions on the matter.
So: should ViewModels expose a simplified, 'text-based' interface to the view and handle conversion internally? Or should ViewModel properties expose the actual data types, leaving such chores to the view to handle?
Update:
Hard to pick a winner here, but I finally landed on one of you who concludes more or less like myself.
Specifically, we have decided to keep the ViewModel properties typed. The main reason for this is the flexibility it affords us in the design of the view, and the power of explicit, declarative conversion/formatting in XAML.
I noticed an assumption with you who will disagree with us in this, that the design of the view is fixed and ready. Hence, no decisions about conversion, formatting etc. need be made in the view. But ours is an agile process, and we haven't got all the nitty gritty detail of the UI figured out on beforehand.
In fact, leaving the details of the UI to be worked out along the way leaves room for creativity and besides, in my opinion, even a meticulously worked out design will always end up morphing throughout the implementation process.
The point of all this is that whereas business rules enforcement certainly belongs in the ViewModel, it seems to us that simple conversion and formatting is a view-thing. It may sound like heresy, but I don't actually think type conversion in the view needs unit testing at all (so long av we unit test the actual type converters).
All in all a great discussion, folks, with well formulated, informed opinions. Thanks.
This is a very interesting question and one that I don't feel has a definitive answer, but I'll do my best to throw my thoughts out there.
Looking at the MVVM pattern as I understand it, the point of the ViewModel is to expose the data in a way the View can understand without any assumptions about the way the view is going to use it. For an example let's pretend that we are modelling the speed of a car:
public class CarModel
{
public int MilesPerHour { get; set; }
}
public class CarViewModel
{
private CarModel _model;
public int MilesPerHour
{
get { return _model.MilesPerHour; }
set { _model.MilesPerHour = value; }
}
}
In the example above I've exposed the property as an int since that is what it is in the model. The disadvantages of this you have listed in your question, but the main advantage is that it gives the creator of the view a valuable piece of information about how to display that data. Remember that we (as the authors of the ViewModel) don't know what the View looks like. By committing to the idea of the data being an int the View can use a textbox or some other control that only accepts numbers (a dial, for example) to display the information. If we say that we are going to format the data in a way that we assume is helpful to the View it takes that important power away from it.
On the other hand we work in real world. We tend to know what the view is. We rarely plug and play different views on top of the same ViewModel and adding the conversion code into the ViewModel is simply easier. I don't think it is right, but that doesn't mean you won't find my production code using it...
Finally (and I'm sure you know this, but for completions sake...) business logic should be done in the ViewModel. If we decide that the car shouldn't go above 70mph then it isn't the responsibility of the view to enforce that. So you'll still end up with some kind of error provider, but at a business rather than display level.
Okay, maybe that wasn't finally....
I wanted to address the comments made by Kent, and my thoughts didn't fit into a comment.
Obviously the primary difference between my and Kent's point of view (as I understand it) is he reads ViewModel to be a Model of the View and I read it to be the thing that exposes the Model to the View. A subtle difference I'll admit, but I think the upshot is that I don't want to remove information that the model provides, even if it makes it easier for the specific view I'm using.
My point of view is based on the assumption that you should be able to swap views out, they should be fleeting things that may change depending on the requirements of screen size, hardware, platform, latency and environment. The interesting twist is that I have never actually needed this functionality, nor seen anything (beyond proof of concept applications) that have ever used it, but if we accept that we won't use it now or at any point in the future, and that each ViewModel will work with one, and only one, View then we may as well go back to putting all the code in the code-behind file and throw the ViewModel out completely - after all, it's so tightly coupled that it may as well be the same class.
Ideally I would like a situation where the ViewModel can say "this value is an int, it will always be an int, and you can display it in anyway that you like. But you can give anything back to me and I'll do my best to make it fit, and if I can't I'll let you know". Basically my MilesPerHour property should have an int getter, but an object setter. That way the views keep all the information I feel they need, but don't have to worry about conversions or validation.
Absolutely it belongs in the view model, for all the usual reasons, including:
Designers own the XAML. Do you want the designers to have to understand and implement the requisite type conversion and validation logic?
Testability. Don't you want to validate that your conversion and validation logic is working correctly? It's much harder if it's embedded in the view.
On the other hand, conversion, validation etc. will be less declarative, explicit and flexible, from the point of view of the View designer
I think this is a moot point because the view designer should be responsible for these things. The designer is trying to make the UI look and feel a certain way; it is the developer who implements the business logic, including conversion and validation logic.
Should the MVVM ViewModel perform type
conversion/validation?
Yes.
The view model is an abstraction layer between the view and the model - the perfect spot to perform any type conversions (instead of cumbersome value converters). Validation should absolutely occur as part of the view model.
We use our View Model to handle the conversions as much as possible for data types. This reduces the need for a value converter to some very specific circumstances. You want to expose whatever type is easiest for the view to consume. This has been working well.
The one specific question you raised:
If, say, a non-numeric value is
entered in a text box bound to a
numeric property, the conversion
fails, the property is never set, and
we never get a chance to provide
proper feedback to the user. Worse,
the property retains its current
value, leading to a mismatch between
what's displayed in the view and
what's actually in the ViewModel.
might be handled by exposing your view model type as a nullable type. This should still allow the underlying source to be updated, even if invalid data is entered, and trigger validation. This worked in a similar situation we had with DateTime and a date time picker.
Keep the view as dumb. We don't have official designers, our developers are our designers, so keeping the view dumb has some benefits:
We (developers) get to keep our sanity (XAML is somewhat less verbose)
Business logic (including validation) stays in the view model and can enable testing
Good Luck!
-Z
This is a good question, and I can certainly see both sides of the discussion.
My thought is that what you're really looking for is a proper NumericInputControl that you can use in your xaml. This will provide a better user experience because your users won't be able to accidentally enter text in a number field and, because the control constrains input without validating it, you can maintain the more strongly-typed ViewModel.
I'm not sure how you'd want to go about implementing one, I know that the classic spinner/NumericUpDown controls are falling out of favor because they aren't touch-friendly, but I don't believe that the introduction of such a control will violate the purity of the design approach or your ViewModels. You'll receive a number that you can then range-validate in the appropriate place, supply feedback via IDataErrorInfo as usual, and so forth. :) This technique lets you get the best of both worlds without any real drawbacks (except the creation of a numeric control).
Or should ViewModel properties expose the actual data types, leaving such chores to the view to handle?
Conversion and templates are done in View, because they both are just a conversion of values, models and viewmodels into controls! Controls are available only inside View.
Validation is done in ViewModel, because validation is done according to business rules and can even be done through a call to a remote service. View knows nothing about business rules, but knows how to present validation results.
If, say, a non-numeric value is entered in a text box bound to a numeric property
A properly crafted numeric text box control never allows user to input a non-numeric value.