How to use mulitple ViewModels in one MainWindow - wpf

I have a C# project in WPF. I've worked with MVC before and I am now trying to get around with MVVM in combination with XAML.
I have multiple models, I have one GUI Window with Tabitems, and I have multiple ViewModels.
Each tab item is related to each model, therefore I have a ViewModel for each model.
Now I want to use binding (why else use WPF/XAML). How do I bind a button to a command in ViewModel X?
E.g.:
Two Models: house and person
View: Two TabItems in the GUI, one TabItem about all interaction with houses, and one TabItem for persons.
Two ViewModels, correlating with each TabItem.
I have a command to put a house for sale.
I see alot of code that just binding to the name of the command, but since I have multiple views, and not just 1, how do I do it? Should I create 1 ViewModel that will handle all other ViewModels?

I see alot of code that just binding to the name of the command, but since I have multiple views, and not just 1, how do I do it?
Make sure you understand how the binding system works. You're binding to a DataContext. So, if each individual tab has a separate DataContext value set, then you can bind using the name of the command.
Knowing this, you can proceed using the pattern you've established. In my humble opinion, I think it will get much too complicated. Majority of MVVM developers are applying a one-to-one relationship with the View to ViewModel (things get tricky when talking about UserControl objects though). Nothing is set in stone though, so ultimately it's up to you on how you want to proceed.

I guess you have limited number of viewmodels. So you have 2 choises: first, is to use DataTemplateSelector, and the second is to define in xaml each TabItem view and Bind each Content to necessary VM.

Related

Split view into two separate views

I'm building a WPF application which very simplified looks something like this:
I have an ApplicationView which holds the menu and a ContentControl.
The ContentControl binds to the property CurrentViewModel which is set by the menu and rendered by its related View (Views and ViewModels are coupled by DataTemplates defined in the App.xaml).
I found this approach on Rachel Lim's blog
So in this example my View contains a list of duties as well as a "Details" window of the currently selected duty.
This setup works fine, but I think my ViewModels are getting too fat!
The non-simplified version of this ViewModel is up at around 500 lines of code, for handling:
Initializing filters
Logic for filtering list
Displaying duty details
Add/Update/Cancel/Delete logic
Now I'm very new to WPF but that seems like too much code, yea?
And it will be even bigger before I'm finished with it.
Anyways, I was thinking that I could split the ViewModel into two separate ViewModels; one for holding list and filters and one for showing the details. But how is this best accomplished?
I have thought of two approaches, but don't know which is preferable:
Create a DutyMasterView whose sole purpose is to hold two ContentControls for the actual Views (ie DutyListView and DutyDetailView each with their own ViewModel)?
I'm using MVVM Light as my framework so I suppose I could use the messaging service to tell the DutyDetailViewModel which Duty to display, right?
Alternately create a DutyMasterViewModel which exposes the selected duty.
Ditch the DutyMasterView and nest the DutyDetailView in the DutyListView.
Does it make sense to split my ViewModel into two or should I just stick with my fat ViewModel?
If splitting the ViewModel is recommended which of my suggestions makes most sense?
Are there other approaches that I should consider?
If you're still looking for opinion, I'd do it almost like you mentioned in point 1 but you don't need any messaging.
You create two VMs. Let's say DutiesVM and DutyDetailVM. DutyDetailsVM contains just some string properties for ID and Name.
In DutiesVM you create two properties:
ObservableCollection<DutyDetailVM> DutiesList
DutyDetailVM SelectedDuty
Your DutiesView can look like this:
<DockPanel>
<v:DutyDetailV DockPanel.Dock="Right" DataContext="{Binding SelectedDuty}">
<ListBox ItemsSource="{Binding DutiesList}" SelectedItem="{Binding SelectedDuty}"/>
</DockPanel>
Now you can create ListView ItemTemplate that binds to DutyDetailVM Properties.
is usercontrol that defines the DutyDetail view. Selecting the item in the list updates the details control automatically.
That's just the sketch but I think you can get the point from it.

Models, Views, View Models and Presenters

I'm trying to get to grips with different patterns (MVP, MVVM etc) and find one that suits my needs. After all my reading I'm still not sure. Hopefully someone can shed some light on this for me.
At the moment I have a WPF View which implements an interface ICustomView. This interface is injected into my Presenter. The presenter then is responsible for subscribing to data, managing subscriptions etc. When the data is returned to the Presenter it calls various methods against the Model (an IObservable collection of CustomBusinessObjects). It does this using the interface ICustomView since the IObservable is a property of the Model.
The problem I see with this is the Model is too coupled with the View. Also the Presenter is deciding which methods to call against the Model. At the moment the View consists of a WinForms grid and this is exposed by the ICustomView allowing the Presenter to call methods against the View. However it adds to the coupling of Presenter and View which makes it difficult to swap out this WinForms grid for a WPF grid or chart etc
I am considering making the Model an entirely seperate entity lets say IModel with a single method ProcessUpdate(string topic, IMessage payload). This would move logic away from the presenter into the Model. It would also mean more than one view could share the same model. The custom model could have additional interfaces for specific customisations but the Presenter would only need to know about IModel.
Does this sound like a reasonable idea? Am I missing something here?
Any advice appreciated.
Thanks
I would recommend switching from MVP to MVVM because you are using WPF. I would only use MVP if you were using ASP.Net or WinForms.
That being said, your MVVM objects would be:
Model: Simple data object. It should not contain any functionality such as Save or Edit, but can have Validation logic.
View: Your UI. I usually do mine as a DataTemplate for the ViewModel class type. It should bind to your ViewModel's Properties and Commands.
ViewModel: The piece that combines the two. Any data displayed in the View should bind to a property in the ViewModel. Any commands in your View such as Button Clicks should also point to methods in the ViewModel.
For example, when a user hits a GetCustomer button on the View, the ViewModel should receive the command, go and get the CustomerModel, and expose it's Properties for the View to bind to. When the user hits Save the ViewModel should validate that the Model is valid, and then execute the Save code using its CustomerModel property.
Personally, when using WPF I prefer to use a WPF datagrid, and bind it to a datacontext in the MVVM pattern. I think the first thing you need to get rid of is the WinForms grid (it will be almost impossible to decouple your model/view as long as you are using a WinForms grid.
I would do research on a few different things.
The MVVM pattern
WPF DataGrid
Binding the DataGrid to a DataContext
Once you get to that point, all you will need to do is update your datacontext, and your view will update with it.

MVVM Modelview to View

As far as i understand ViewModel communicates with View via databinding. But how can one create in ViewModel UIElements for View.
Thanks.
The ViewModel should not create any UIElements directly because the ViewModel should not depend on the View. The ViewModel provides data that the View (i.e. the UIElements) can bind against.
If your question is geared toward how to bootstrap a View, there are two approaches: View-first and ViewModel-first. In the former you create the View first and then create and bind against the ViewModel. In the latter you make the ViewModel create the View (through interfaces). Read more about it here.
If your question is geared toward composing the view of UIElements, this is done through DataBinding and the use of DataTemplates and ControlTemplates.
MVVM is a loose design pattern, it is accectable to put code in the code behind as long as it purely concerned with the UI only, just keep in mind that it may be harder to unit test.
And strictly speaking the ViewModel does not communicate to the View, there is no reference to the View in the ViewModel, rather the View reads data from the ViewModel and executes commands on the ViewModel.
The problem is dynamic component creation needs as I see.
You can put a Container object on a view then on modelView create UIElements and Bind this UIElement collection to Container's Content Property. But I think its not a good practice. This approach breaks Model and View seperation.So you need to avoid of dynamic component creation.
MVVM approach is a bit diffrent. Sometimes force us using tricks. i.e. Instead of using ListBox's MemberPath property you define a ItemTemplate and put ButtonBase elements on the template for supporting Commanding! Or you Extend ListBox and Support Commanding.
My offer instead of dynamic object creation. Use DataTemplates and change the binded members on ModelView,then the view will be automatically created for you.For complex senario's it could be hard. We do them all for the sake of keeping MVVM structure.

Should a ViewModel in MVVM reference the View?

In the MVVM (Model-View-ViewModel) pattern should the ViewModel reference the view. I would think that it should not. But how should the following scenario be handeled? I have a view that has a tab control as the main container, the viewmodel for this view implements a command to add a new tab to the tab control. The easy way would be to allow the viewmodel to reference the view and then in the command implementation to just programmatically add the new tab to the tabcontrol in the view. This just seems wrong. Should I somehow bind the tabcontrol to the viewmodel and then implement a data/control-template to add the new tabs. I hope this makes some kind of sense to somebody :)
In "pure" MVVM, the ViewModel shouldn't really reference the View. It's often convenient, however, to provide some form of interface in the View whereby the ViewModel can interact with it.
However, I've found that I almost never do that anymore. The alternative approach is to use some form of attached property or blend behavior within your View, and bind it to your ViewModel properties. This allows you to keep the View logic 100% within the View. In addition, by creating a behavior for this, you create a reusable type that can be used to handle this in every ViewModel->View interaction. I strongly prefer this approach over having any View logic within the ViewModel.
In order to demonstrate this technique, I wrote a sample for the Expression Code Gallery called WindowCloseBehavior. It demonstrates how you can use a Behavior within the View bound to properties in the ViewModel to handle controlling a Window's life-cycle, including preventing it from being closed, etc.
Reed and Dan covered the general approach but in reference to your specific case, TabControl is an ItemsControl and so can bind its ItemsSource to a data collection in your ViewModel representing the set of tabs to display. The UI for each type of tab can then be represented by a DataTemplate specific to the data type of an item (either using DataType or a DataTemplateSelector). You can then add or remove data items as needed from your VM and have the tabs update automatically without the VM knowing anything about the TabControl.
I find that it's often a helpful compromise to expose an interface on the View that handles View-specific functionality. This is a good way to handle things that are awkward to accomplish with pure binding, such as instructing the form to close, opening a file dialog (though this often gets put in its own service interface) or interacting with controls not designed well for data binding (such as the example you provided.)
Using an interface still keeps the View and ViewModel largely decoupled and enables you to mock the specific IView during testing.
One of us is missing something obvious. Your tab control is an ItemsControl. You should bind the ItemsSource of your tab control to an ovservable collection in your view model. When you handle the command in your view model to add a tab, you simply add a new element to this collection and, voila, you've added a new tab to the control.

WPF: Binding with nonstatic parameter? (newbie question)

This will probably be obvious but I can't find the best way.
I want to show the user's ToDo's in a listbox. These ToDo's are in the database and consist of an Id, UserId and Description.
The user logged in to the app.
How can I retrieve the ToDo's for that certain userId and set it up for binding to the listbox?
I was trying with an ObjectDataProvider but I cant figure out how to use that in combination with nonstatic stuff (like my _dbService, userId, language, ...).
Are the only options to make all those things static versus binding in the code behind?
If so, this means that ObjectDataProvider isn't very useful, no?
I find a lot of examples of it being used with a hardcoded parameter but I hardly see any situation where I'd need such a functionality..
I do all my WPF using the Model-View-ViewModel pattern. I've given you one link there but Google will give you loads. MVVM seems to be the standard pattern for WPF. This project is probably more complicated than you need but it is well-written and brings home the use of MVVM.
Basically, you create a Model of your data. In this case, you'd probably create a simple class (I'll call it ToDoItem) with properties Id, UserID and Description. Use your preferred mechanism to get a collection of these from the database. Link to SQL, Entity Framework, a standard query, whatever.
Then you have your ViewModel - you have an instance of the ViewModel for each instance of the Model: the VM has a reference to the M and 'forwards' properties to it. The ViewModel is what you use to manipulate the model.
Then you have your View - this is the UI. You set the DataContext of the View to be the ViewModel and then your bindings automatically bind to the ViewModel. Your View just ends up being the things you can see. All of the work gets done in the ViewModel. This means it's very easy to test.
So, when you click on a button in your View, the bindings pass this onto a Command in your ViewModel which manipulates the Model.
The UI is also a View with a ViewModel. So, your UI VM might load a collection of Models from the database and stick them in an ObservableCollection. The ListBox items collection would be bound to this ObservableCollection.
It's hard to explain all of this in a post like this. Read a couple of articles and see what you think. I'm still quite new at this, too, but I believe my reading about MVVM has paid off.
Hela Thomas, Tom here from Orbit One :)
MVVM is the way to go. I'm on my 4th project and WPF really shines if you use mvvm. You already tried MVC (or MVP as we did on recy*tyre) and that's a nice separation of concern.
MVVM takes it a step further since the viewmodel knows absolutely nothing about the view.
The view binds to the viewmodel, so it has a reference to it (2 way, super powerful and works beyond the typical MS demo). The viewmodel is just a poco and is a representation of your view, data + behaviour. Once you dig this paragraph the cool term mvvm will have no secrets.
I see if I can come up with a small demo. Maybe I'll have time later.
What I will come up with is a view (xaml, file 1) that binds to a viewmodel (file 2, a poco class, not to be mistaken with code behind). The model can be whatever you like (service layer or directly to the repositories). Using the power of 2 way binding we will bind to an observable collection meaning that if we add/delete/... something to the collection the view will pick it up without us putting energy into it.
My first 2 wpf projects was done with Caliburn Micro (see codeplex) which is a powerful framework based on conventions. It shields you away from hardcore wpf (creating tour dependency properties yourself mainly) and you can create something relatively fast without fully understanding wpf. That's a downside of itself but it worked for me. As of project 3 I started taming those dependency properties myself and it will make you a better wpf developer.
I see the question is from October.. did you find a good solution?

Resources