Silverlight Commands MVVM - silverlight

I'd like to 'reduce' the number of commands in my ViewModel class.
I have one ViewModel which contains 5+ lists (using Listboxes on View to presentate, and I'm binding an ObservableCollection to its ItemSource parameter; also binding the SelectedItem property), and each list should have its own Add/Remove/etc button.
So, it looks like this:
public class PersonViewModel : ViewModelBase
{
Person _Person;
private ObservableCollection<WorkPlaceViewModel> _WPlaces;
private ObservableCollection<LanguageViewModel> _Languages;
... other lists
private WorkPlaceViewModel _SelectedWorkPlaceView;
...
}
Adding 5x2 command makes the ViewModel a bit large. I could hardcode a string to the CommandParameter and handle it with a switch-case in my ViewModel but this sounds like hacking. :p
Or should I go with creating a Remove command for each listbox, and pass the SelectedItem as a parameter?
Whats the best way for this in MVVM?

Why do you have a collection of viewmodels in your viewmodel? What is the PersonViewModel supposed to accomplish. It sounds to me like you need to break up your view into multiple views and bind them to different viewmodels. Your views and viewmodels should be as small as possible to reduce coupling.
That said, I would recommend commands for add/remove on each observable collection. Using a hardcode string is messy, as you guessed. If each observable collection has their own add/remove that will allow different logic for each collection and is more maintainable.
Can you post more code from your ViewModel and describe the app a bit? That will help us determine if there could be a better design decision.

Related

WPF MVVM - Binding DataGrid to ObservableCollection of Model

I am pretty new to WPF MVVM, so pardon me if I understood MVVM concepts wrongly.
I have a DataGrid in my View, which I have bound the ItemsSource to an ObservableCollection<M> in the ViewModel. The M class is a Model class. However, the M class has bool properties, which are to be displayed in the DataGrid as "Yes/No" strings.
Currently, I am using a Converter to convert the bool value to string. But, it just feels wrong for the ViewModel to expose a list (ObservableCollection) of a Model to the View. I have also read that in MVVM, conversions should be done at ViewModel. So, what is the right way to implement this the MVVM way for a DataGrid?
In an ideal world, you would wrap your Model objects in their own ViewModel so that your ObservableCollection contains a ViewModel type with those bool Model properties converted to Yes/No string properties.
However, in a pragmatic world, if you are not editing those values, I wouldn't bother except to note that if you are exposing many of those bool properties and have many thousands of rows, you will take a performance hit on rendering the grid while the DataGrid instantiates a Converter per property and row.
Using converters is not a wrong way. As per my suggestion, you should bind the data as you're doing now and in the view you can create and use a BoolToStringConverter for converting the boolean value to yes or no.

WPF MVVM: View's ListBox with source deep in Model. How to implement?

I'm new to WPF. I need to Bind UI's ListBox to the source that is deep in Model Layer.
App scheme is on picture below. Desc:
My MainWindowViewModel Class has a Scheduler Property (Scheduler Class in Model layer).
Scheduler Class has a CurrentParser Property (Parser Class in Model layer).
Parser Class has a Result field (ParserResultMetaData Class in Model layer).
ParserResultMetaData Class has a Log field (Log is a List(Of String))
Log can be changed only programmatically from model layer (Parser adds lines during it's work).
So my question is how can I bind my ListBox to this List to match MVVM pattern.
As I get it now, ViewModel must have an ObservableCollection(Of String) witch is a copy of my List(Of String) from Model layer.
Somehow you need to notify the UI when a line is added to the collection. There are multiple ways to achieve this, but if the collection is modified from within the model layer, you need a mechanism for communicating this to other layers in one way or another.
Use an ObservableCollection in your Model layer.
While types like ObservableCollection and INotifyPropertyChanged are widely used in MVVM architectures, they are not specific to them and in some cases it can make sense to use them in the model layer directly. Using an ObservableCollection in your Parser class is one way to provide this notification mechanism. You can then bind the ItemsSource of the ListBox to Scheduler.Parser.Result.Log directly and it will update accordingly.
Create a wrapper property in your ViewModel.
If you don't want to use an ObservableCollection in your model, you can expose the List via a property in your ViewModel, for example:
public IEnumerable<string> ParserLog
{
get { return Scheduler.Parser.Result.Log; }
}
Then you need to manually notify the UI when an item is added, so you're gonna need an event (or something equivalent) which tells your ViewModel that the list changed and it needs to raise the PropertyChanged Event for the ParserLog property. Add code like this in your ViewModel:
this.Scheduler.Parser.ResultUpdated += (s, e) => this.RaisePropertyChanged("ParserLog");
This will tell the ListBox to update the items from the ParserLog property.

WPF DataTemplate / DataTemplateSelector -- Best approach for a ViewModel used by 2 different Views?

Basically, I have the following scenario:
ViewModel: FooViewModel : BaseViewModel, BarViewModel : BaseViewModel
Views: MainView, FooView, BarView
Right now I "inject" the view and set the DataContext using DataTemplate and DataTemplateSelector. Obviously, my ItemsControl ItemSource is bound to an ObservableCollection<BaseViewModel> in which it contains (for now) an instance of a FooViewModel and a BarViewModel
The problem is I want to introduce a AlternateFooView which I want to utilize the same FooViewModel. I figure I'll create another DataTemplate and have my DataTemplateSelector return it, but there needs to be special logic to determine which DataTemplate to return (I can't just go by which ViewModel is there), and that means I'll have to have some type of property or field in the BaseViewModel. I don't know if that's really a good idea because that seems to be introducing a field/property into the ViewModel that is only used to select a view. It won't hurt my unit testing, but it seems like a waste to include a field just to help decide which UI View to choose. I don't think it breaks MVVM, but I'm curious if anyone out there has any other better ideas? The alternative ideas I had I dislike even more...
Idea #2:
- Turn FooViewModel into a base class that 2 different FooViewModel's extend (i.e. BaseFooViewModel, FooViewModel, DifferentFooViewModel). This seems stupid because there really isn't any difference between FooViewModel and DifferentFooViewModel aside from their class type.
Idea #3:
- Just copy FooViewModel and make it FooViewModel2 (it'll be exactly identical to FooViewModel). This seems even worse than idea #2.
Sample-Code (Adjusted obviously):
public abstract class BaseViewModel : NotificationObject
{
//Common Stuff
}
public abstract MainViewModel : NotificationObject
{
public MainViewModel()
{
MyItems = new ObservableCollection<BaseViewModel>()
{
new FooViewModel();
new BarViewModel();
new FooViewModel(); //New Item -- I want it to use the DifferentFooView
}
//Load items from a DAL later
}
public ObservableCollection<BaseViewModel> MyItems { get; set; }
//Other Stuff
}
<l:MyItemsControl ItemSource={Binding MyItems} ContentTemplateSelector={StaticResource MyTemplateSelector} />
Thanks!
I agree with krishnaaditya that the question really boils down to what determines which View to use based on the state of the ViewModel. This type of logic is often placed into a template selector, which works great. If you don't want to put that logic into the template selector, consider externalizing it by using my Routed Template Selection approach. That makes it easy to delegate the template selection logic by using a routed event.
The idea you proposed in your comment about using a DataTrigger could also work, but that reintroduces the need for a property on the VM object that indicates which View to load (which you said you don't want). In my opinion, that's not necessarily a bad thing.

Who sets DataContext in Silverlight MVVM

I have been reading about MVVM pattern from various sources like MSDN:
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
In that article it says: Unlike the Presenter in MVP, a ViewModel does not need a reference to a view.
If the View (XAML) assumes it's DataContext is the ViewModel then where in the code is the following line:
view.DataContext = viewModel;
The ViewModel doesn't know anything about the view so it cannot set the datacontext. If I give the ViewModel the reference do I break the MVVM pattern? My other choice is to have some kind of Builder or extra Presenter whose only job is to wire the whole thing (wait for the loaded event of the View, set the DataContext).
I know different view's can share the same DataContext (e.g. set the DataContext only for the mainwindow and others will see it) but in many cases that is not possible at all nor even feasible.
This is a great question that has many answers. It all depends on how you want to architect your application. For instance, I use dependency injection to create my IViewModel, which in turn creates my IView and my IViewModel runs an IView.SetViewModel(this) on the constructor.
Other people may wish to use a more Blendable method by setting the DataContext in the Xaml:
<UserControl.DataContext>
<ns:CrazyViewModel />
</UserControl.DataContext>
Sometimes the DataContext can be implied so it is set by the framework, like in the instance of a DataTemplate used by an ItemsControl. This is also pretty common in desktop WPF because it supports typed DataTemplates.
So there really isn't a wrong way to set the DataContext, just as long as what you have separates concerns, is maintainable and is also easily testable.
Shawn Wildermuth has a great post about whether the View or ViewModel comes first:
http://wildermuth.com/2009/05/22/Which_came_first_the_View_or_the_Model
I like, and use, his marriage concept where a 3rd party class creates both the view and viewmodel, and then associates the two. It's worked well for me.
I use MVVM a lot in with Prism. In Prism I use Unity for dependecy injection. Therefore I have an interface for every class registered with Unity including the View.
The IView interface has a method like this:
void SetViewModel(object viewModel);
The ViewModel calls this method at the end of its constructor, passing itself as a parameter:
public ViewModel(IView view, ...)
{
...
this._view=view;
this._view.SetViewModel(this);
}
In the View.xaml.cs the IView interface is implemented. This will be the only code I add to the codebehind of the view:
public partial class View:UserControl, IView
{
public View()
{
...
}
public SetViewModel(object viewModel)
{
this.DataContext = viewModel;
}
}
As for my own usage, the ViewModel doesn't know the View, or any interface on the View. And most of time, the View doesn't know its ViewModel, even if it is less important. The VM is just transprted by the DataContext.
This ensures that the VM and V will remain highly independant. Links are established thoughout bindings, commanding, Behaviors, Triggers & so on. Even if VM is often highly related to a given view, I try to make it as generic as possible, so that I can switch the corresponding View, and / or adapt the View behavior without needing to update the VM, except if the architectural link between V and M is impacted !

Should my ViewModel have an ObservableCollection of Views or ViewModels?

I'm trying to understand the basic MVVM design approach when using ItemsControl by binding it via DataTemplates to ObservableCollections on the ViewModel.
I've seen examples that bind to ObservableCollections of strings, Views, and ViewModels.
Binding to strings seems to be only for demos, it is the binding to "ViewModels that contain collections of Views that contain collections of ViewModels" that the power of WPF seems to really come out.
For those of use proficient in the MVVM pattern, what is your standard approach to binding ItemsControl, ListView, ListBox to collections in a ViewModel? I'm looking for advice from experience like this:
always use ObservableCollection<...> and never List<...> because...
something better than ItemsControl to display a collection is...
in order to get filtering to work in your ViewModel instead of code-behind, use...
use collections of Views when ... and collections of ViewModels when...
90% of the time I create an ItemsControl and bind it to an ObservableCollection of Views which have their own ViewModels...
I would use an ObservableCollection of ViewModels for the following reasons:
ObservableCollection already has events available for signaling when it has been modified (e.g. when items are added/removed from the collection).
We're at the ViewModel 'layer' so it provides cleaner separation to have a ViewModel contain a collection of ViewModels rather than Views
If it is necessary to modify or get data from items within the collection you can more easily modify/access that data if the items are ViewModels (if they're views you'll frequently be casting the View's DataContext or accessing its UI elements).
I like using an ObservableCollection of ViewModels. The view that binds to the collection can define a DataTemplate that gives the ViewModel its look. This leads to less coupling among the components.
I have the same question, but replace the "view" with "model". :)
I have a MODEL with a collection of other models.
I want my viewmodel to have an observable collection of other viewmodels, but once I instantiate it like that - the connection between the model collection content is lost.
Do I now need to start wiring all the events from the viewmodels observable collection back to the models collection?

Resources