Silverlight - communicate between viewmodels - silverlight

This UI consists of a Main.xaml which contains a navigation frame which holds (Person.xaml), so there's two different viewmodels involved.
I would like to filter the content of the datagrid when the menu in Main.xaml is clicked.
People (shows all)
Score above 50
Score below 50
My approach is to use the MVVM light Messaging by having PersonViewModel subscribe on a certain message which is sent from MainViewModel. This would work, but are there any other ways of doing this (best practice)?
I'd hate to implement the MvvmLight Messaging for all my scenarios where UI elements from different viewmodels have a need to communicate, if there is a better way of solving this.

If you are using MVVM light, I guess you have created these viewmodels in the ViewModelLocator. So just use it to get access among viewmodels in your application.
Another approach is to use some type of IoC container like Unity or SimpleIoC.
I hope this helps you.

We use MVVM light also. From my understanding of your requirements. you can probably just use a single DomainContext and then loading all the entities to it and then querying the context for each click item.
once you have a Context, you can basically query it dynamically. Here's something from one of my code.
GetUserBUGroups = SecurityDomainContext.Current.UserBUGroups.Where(ub => ub.UserID == GetUsers.UserID).OrderBy(o => o.BUGroup.BUGroupDesc).ToList();

For simple scenarios such as this, it does not seem appropriate to use several ViewModels.
I believe you should insert the filter options directly in the PersonViewModel

Related

Can we create UI Element in ViewModel?

I have some confused about create ui element in viewmodel ? If yes then how can it possible ?
Thank's in advance.
No, in the mvvm pattern the viewmodel is only responsible for providing data and state.
You can theoretically have many views connected to the same viewmodel; A wpf-view for graphics displays and a command-line for text-mode for instance. If you think like that it makes sense where to put which functionality.
If you want to create UI objects programatically, you do that in the views code-behind. You are absolutely allowed to do it there and hook into any events just as you would have in a traditional forms project.
Why do you want to do that? Do you need to generate a dynamic UI at runtime?
The ViewModel isn't for UI elements, though it can hold backing data elements for the UI element (like list of items for a combo box).
UI is a job for the View. You can generate XAML at runtime, but I would not create it "in ViewModel" I would create a separate, distinct presenter or controller class, or use XAML code behind logic. You can reflect over the ViewModel to generate XAML, but I would limit the ViewModel to data and mediation between the View and the Model and keep all UI separate.
I am not a WPF expert, I'm just answering from the general best-practices perspective of MVC/MVVM and the purpose of the ViewModel. Theoretically, your ViewModel should be reusable across multiple UI presentation layers (ASP.NET/Razor/XAML) so avoid UI specific markup in the ViewModel. Limit it to properties, containers, methods, data access calls or service calls, etc.

Transfer data between two ViewModels

I have two Views and two ViewModels in my WPF app. I am using MVVM ViewModelLocator to transfer data to and fro between my ViewModels. Is this the recommended practice? Is there a better way to achieve this? I am currently using this code to access properties of ViewModel2 in ViewModel1
var _viewmodel2 = (Application.Current.Resources["Locator"] as ViewModelLocator).ViewModel2;
Thanks
What you are after is something like the Event Aggregator pattern. It will use a central 'aggregator' object and subscribing/raising events (with payloads) to ferry data back and forth. Yes, a bit complicated. If your scenario is complex enough for this , here is some more information from a previous SO post here
However......If your scenario is less complicated, you are ok maintaining a reference in viewmodel A to viewmodel B and vice versa. Which seems like it is what you are doing with the ViewModelLocator (which actually uses DI behind the scenes to resolve the instance of ViewModel you are after). This does not violate the MVVM pattern. You just want to be sure to clean up after yourself if during the course of your data share you are subscribing to any events across the viewmodels (same case with event aggregator solution).
If you register your viewmodels in a service locator or IoC container, you can simply fetch the reference from there.
SimpleIoc.Default.GetInstance<MyViewModel>()
Above example uses MvvmLight

Design pattern for Viewmodel change triggering another viewmodel change?

In my WPF application, I have several models and viewmodels. Consider an example:
The SurfaceCondition property of my RoadViewmodel changes. I want this to (asynchronously) trigger a change of the Wheel property of my CarViewmodel.
I can think of several solutions, but I sense this particular problem has a well-recognized solution. Using messages? Putting a reference in the RoadViewmodel to the CarViewmodel and trigger an update through the property? Merging the viewmodels? WPF gurus out there, please enlighten me!
Definitely not the two last solutions you propose as they violate Seperation Of Concerns (RoadViewModel knowing about CarViewModel) / DRY principles (RoadViewModel having to update CarViewModel or merging two classes).
Messages on the other hand seems like a fine, decoupled solution here. There are a couple of implementations available, for example Prism has en EventAggregator class, MVVM Toolkit has MessageBus etc. Or search for terms like 'MVVM event bus'. Now whatever you choose, know that it is always good to not use those classes directly but instead pass an interface. For example with Prism, you'd program your viewmodels to use the IEventAggregator interface only. In the actual application you pass them an instance of the actual EventAggregator, whereas during unit tests you pass the a mock.

Choosing between bound ViewModel properties or messaging to communicate between ViewModel and View using the MVVM Light Toolkit

I'm using MVVM Light toolkit (which I love). I currently have messaging in place for some interaction originating from the ViewModel and intended for consumption by the View. Typically these types of messages indicate the View should do something like hide itself, show a confirmation message that data was saved, etc.
This works. In the constructor for the View, I register with the Messenger:
Messenger.Default.Register<NotificationMessage<PaperNotification>>(this, n => HandlePaperNotification(n));
When I'm using the Messenger to communicate cross-cutting concerns between ViewModels (like identity), I can see that when the ViewModel is cleaned up in the ViewModelLocator, the base class for ViewModels (ViewModelBase) unregisters any subscribed messages. I don't have to do anything, as MVVM Light Toolkit handles that for me. However, when I use them in the Views, I have to expressly unregister them at Closing time, like so:
Messenger.Default.Unregister(this);
I suppose I could implement a base class for Views to inherit from.
However, it strikes me that perhaps this is a code smell to be using the Messenger in the View... it works, but it might not be the best way. I'm wondering if I should instead create a property on the ViewModel and bind whatever part of the View's elements to it. In the example of hiding a form, a property could be a boolean called "Show". As I think about it, I can see that in many cases this will result in having to write a ValueConverter. One way seems less testable. The other way seems to require much more code and perhaps the introduction of excess ValueConverters, which could become a code smell in themselves.
So (after all that build up) my question is this:
Is it preferable to use messages within the View or is it better to add properties (and potentially ValueConverters) to allow the ViewModel to drive it in a more bindable fashion?
In MVVM. ViewModel comunicates with View through DataBinding and Commands. If you need some other functionality, you need to implement it using this means.
Messaging is supposed to be only for ViewModels. Views are supposed to be "stupid" visualisers of your data in ViewModel.
The Messaging logic in MVVM Light is there for communication between ViewModels. I've never run into any communication between View and ViewModel that I couldn't solve with binding and/or commands. Sometimes I need Value Converters and sometimes I need code in the code-behind, but I've never had to make the ViewModel directly push data to the View.
This is an interesting discussion and I found this thread when I was wondering about view model to view communication. Interestingly, MVVMLight's creator seems to find it perfectly acceptable to send messages from a view model to a view. Another example of differing opinions about what is a good MVVM design.

Multiple "sibling" controls, one-at-a-time visible, MVVM

I've got what I think is a fairly simple problem in Silverlight, and I'd like to solve it using MVVM principles, largely as a way of enhancing my own understanding.
Let's say I have a simple LOB app that's designed to let me load up and edit a single Employee (just an example, for the sake of explanation). In my example, Employee is made up of a number of complex objects - an Employee has a ContactInfo, a Skillset, an EmploymentHistory, an AwardsEarned, etc. The idea is that I can have this app load up a single employee and get access to a number of different editor screens. Each component of an Employee has its own editor screen.
Visually, the app just ha a left-hand nav bar and a main view on the right side. The nav bar just lets me type in an employee number and load it into memory as the "active" employee. It has a simple list of links - clicking a link should load the appropriate editor screen on the right side.
There are a couple concepts that I don't think I understand well enough, and I'm having trouble proceeding. I know there's always more than one way to skin a cat, especially when it comes to WPF/Silverlight/XAML/MVVM, but I'm having trouble thinking through all the different concepts and their repurcussions.
View-First or ViewModel First
After much thinking about MVVM, what seems most natural to me is the concept of viewmodel composition that Josh Smith seems to promote in his often-quoted article. It seems like the idea here is that you literally model your UI by composing viewmodels together, and then you let the viewmodels render themselves via typed DataTemplates. This feels like a very good separation of concerns to me, and it also makes viewmodel communication very direct and easy to understand.
Of course, Silverlight doesn't have the DataType property on DataTemplates, to many complaints: one, two. Regardless, what I see promoted much more often than viewmodel composition is a more view-first design, where the viewmodel for the view is typically instantiated in the view's XAML or via a DI container, meaning that you can't hand it any parameters. I'm having a really hard time understanding this: how is a ViewModel supposed to serve a Model to a View if I never get to tell it what data is in the model? Reaching through a view to get to its viewmodel doesn't seem to make sense either. I'm very hazy in this area but it seems the accepted answer "use a mediator/lightweight messaging framework." I'm just going through some tutorials now on the messaging system in MVVMLight and I'll be looking at similar stuff, if for nothing else than simply to understand the concepts, but if anyone can shed some light on this I'd very much appreciate it. Anything involving Unity/Prism or MEF is valid, but I haven't gotten that far in my quest for knowledge yet :-)
Instantiating Views and Selecting Them
Theoretically (I say that because SL doesn't support DataTemplate DataType), the viewmodel composition approach could make this very simple. I could have the right side of the screen be a content control whose Content property is bound to a property called ActiveEditor. A parameterized command for the hyperlinks would set ActiveEditor to a given viewmodel.
With a more view-first approach, how would I proceed with this? The first thing that comes to mind is instantiating all of the controls in the XAML of the main view.
Is manipulating the Content property of a ContentControl a good way to go for this kind of situation, or am I better off doing something like setting visibility on each individual control?
The ViewModel (VM) is written so that it is 'wired up' to the Model but has no knowledge at all of the View - in fact, this is what makes it very good to unit test (see NUnit) as it has no idea, and less does it care, whether it is being used by a UI or a Test Framework.
The VM exposes public CLR properties which implement the ICommand interface, the View, having instantiated a VM using (generally speaking anyway) its default constructor, then binds its Buttons/Hyperlinks etc to these Command properties like. So, for example, you may have a VM that exposes a CloseCommand to exit the app, the View may contain a MenuItem that binds to that command, such as:
<MenuItem Header="E_xit" Command="{Binding Path=CloseCommand}" />
Now, the VM would also expose a public ObservableCollection of objects that you want to display in your UI. Whether you populate this ObservableCollection as part of the VM constructor, or whether you do it via a UI interaction (say another Command assigned to a Button click) is up to you but the end result is that you bind a View control to this exposed ObservableCollection in XAML like:
<y:DataGrid ItemsSource="{Binding Breakdown}"/>
or equivelant for whatever control you are using to display the data (not sure off the top of my head what elements a DataGrid has in Silverlight as opposed to WPF).
Meanwhile...: The Mediator pattern is used for VM's to interact with each other, not for the View to interact with the VM. For example, you might have a custom TreeView that has its own VM on the same View as the main chart screen. In this case you could use a Mediator for the TreeView's VM to communicate with the Charts VM.
As for the last bit of your question, I think set up a basic framework using Josh Smith way in the article you mentioned and use that method to add additional ViewModels to the right hand side of your silverlight app.
Hope that helps a bit at least.

Resources