How to inform multiple view models of a variable change? - c#

One of my views contains a dropdown menu. When a selection is made, its view model and all other view models in the program must be made aware of the change so that they can update their views.
Currently each view model contains its own copy of the selection and when it is changed I have
to manually update them all (I just have a public Refresh(int newVal) on each one). Is there a better way of doing this?

A possible approach might be to use an event aggregator. The aggregator is used to dispatch the messages between the publishers and receivers.
The objects that need to send a message register the message type with the EventAggregator and the objects that need to receive subscribe for them also at the EventAggregator.
There are many ways to implement this, I suggest using any MVVM framework of your choice. Most common frameworks offer time-proven implementations of this.
An example would be Caliburn Micro. CM framework already offers the EventAgregator class for this.
See an example of this here:Introduction to messaging with Caliburn.Micro’s EventAggregator.

You could use an event aggregator and publish an event through it that could be handled by every view model (maybe in some kind of base class?).

Use an (aggregated) event.
Subscribe to the event when the view is loaded, unsubscribe when the view is unloaded and make sure to initialize the variables in your view model when it's loaded. Then publish the event (pass the new data as a parameter) when the selection changes.

Related

In wpf how can i reference MainWindowViewModel from other ViewModels?

I am developing a wpf/xaml app for windows. I want to use the material design framework and i have loosely based my app on the code from the example application here: http://materialdesigninxaml.net/ My C#/xaml knowledge is ok, but very rusty.
In this implementation there is a MainWindow.xaml view linked to a MainWindowViewModel, where the MainWindowViewModel is handling the data conversion from the model and the presentation logic.
My question is about the best design philosophy to use for the 'pages' that are viewed in the MainWindow.xaml - i have an app working where i can navigate through 'pages'. So the main window has a store of potential pages in a ObservableCollection and shows navigation buttons. Clicking on the buttons goes to the next page in the ObservableCollection.
My question is about how the pageViewModel can interact with the MainWindowViewModel. For example a user might click a button on a pageView to cause a command that moves to another page - to do this using this framework requires an ICommand to be actioned on the MainWindowViewModel.
What i have done so far is have the MainWindowViewModel create the other pageViewModels. On instantiation the pageViewModels save a reference to the MainWindowViewModel that can code on MainWindowViewModel can executed when needed. This seems to work but also i can't help thinking there would be a more optimal solution.
I have been doing some looking at similar questions on SO - do I need to look into IEventAggregator?
One possible solution is to use an UI Framework like caliburn micro. This framework will connect a View automatically with the corresponding ViewModel. There is also a so called conductor. The conductor allows to use multiple pages with it´s own View and ViewModels in a main page. It also provides activation and deactivation behaviour and many more. May it helps.
What i have done so far is have the MainWindowViewModel create the other pageViewModels. On instantiation the pageViewModels save a reference to the MainWindowViewModel that can code on MainWindowViewModel can executed when needed.
This is one approach. The problem with it is that it creates a tight coupling between the view model classes.
A better and common approach is to use an event aggregator or a messenger to communicate between the view models. This removes the tight coupling as a subscriber of an "event" or "message" only observes the event aggregator instead of the publisher and the publisher knows only about the event aggregator and not about the subscribers.
Please refer to this blog post for more information about the concept.

Avoid circular refence while classes have to communicate with eachother (Dependency injection)

I'm working on an application written in C# and WPF.
There's a view with a layout that consists of three separated sections (sub views).
A "content" view that contains the current main content (say, a listview of products).
A view located on top of it, containing tools and option
controls.
The main menu view on the left.
I use the .NET dependency injection for my application (Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.Configuration.Abstractions)
When a ViewModel is set for the content view, I also want to set a ViewModel for the top view. These ViewModels have to communicate/reference eachother.
Like, when a command on the top ViewModel is executed, the content ViewModel should be notified and/or do something, and vice-versa.
Say I have a TopViewModel and a ContentViewModel.
One bad thing I could do is:
Requiring the ContentViewModel in the constructor of TopViewModel
and requiring the TopViewModel in the constructor of ContentViewModel.
Of course that won't work, because it's a circular reference.
The alternative I can think of, is just requiring the TopViewModel in the constructor of ContentViewModel and don't do this same kinf of thing with the other class.
The constructor code of ContentViewModel could then listen to events of TopViewModel. The TopViewModel doesn't know anything about ContentViewModel, which can be a problem if it needs to reference it for some logical reason.
Some content views can have multiple top views (they change like when the user selects something)
I'm taking this quite serious. Everything I can think of seems ugly and bad practice to me. While I think this is a quite simple and common situation.
What is the best, generally accepted solution to this that doesn't break the OOP rules?
What is the best, generally accepted solution to this that doesn't break the OOP rules?
Instead of storing a direct reference from one view model to another, you should consider using an event aggregator to communicate between the view models in a loosely coupled way.
This removes the tight coupling between the view model classes and makes your application easier to maintain and evolve over time.
The idea is that a subscriber observes the event aggregator instead of the publisher and the publisher knows only about the event aggregator and not about the subscriber(s). Please refer to the following blog post for more information.
Using the event aggregator pattern to communicate between view models

Communication between loosely coupled Components using Prism for UWP App

I am new to Prism and have been looking into designing a UWP App which would have 2 XAML views. These 2 views would be loosely coupled and i want to pass messages between the 2 views. One view would have a button and on clicking on this button, a message would be sent to the other view which would highlight and item in the list in that view. I am reading up on the Prism documentation and have some confusion about what would be the best form of communication? In particular would my case benefit from Solution Commanding or using the IEvent Aggregator. Referencing this post Communicating across modules with Prism? i would love to understand why IEeventAggregator is a good solution
The purpose of using an event aggregator is to remove the tight copuling between the producer and consumer of an event or a message.
If you want to send a message from one component to another in your application, you can do this by raising an event or calling a method of a strong reference to the consumer. The downside of doing this is that you create a strong dependency between the subscriber and publisher classes and this makes the application harder and more expensive to maintain.
The solution is to introduce an event aggregator in between the publisher and subscriber. Then the subscriber and the publisher only know about the event aggregator. They don't know anything about each other which means that they can evolve independently from one another.
Please refer to this blog post for more information about the concept.
Edit: To answer your actual question, solution commanding is generally used when there is an expectation of immediate action from the user interaction whereas event aggregation is used when there is not a direct action-reaction expectation.
Please refer to the docs for more information.

Registering message recipients at the Application level in MVVM Light from XAML?

Specifically, in this case the Application itself would be the recipient. My thought process is that this would allow for the least possible linkage between Views and View-Models when dealing with the scenario where a new View would be created: They would deal strictly in messages and the App level of the WPF application would handle these messages, creating new views (and implicitly view models through the DataContext of those Views) as appropriate.
This is straightforward enough, as far as I can tell, if I go into the codebehind (app.xaml.cs). However, I would ideally like to handle this message recipient registration in the xaml if at all possible since the behavior is fairly straightforward, all it would really be doing is calling ShowDialog for the appropriate View (I don't think any further handling would be needed, but I may be forgetting something).
For the life of me, I can't think of a way to avoid the codebehind though (I know that MVVM does not really forbid the use of codebehind and I'm making things harder on myself with this, but I think it would make for better code organization if it is possible without violating some other MVVM principle). I thought I had it when I considered the use of System.Windows.Interactivity and tying an EventTrigger to the Startup event of the Application class, but was foiled when I discovered that it needs to extend DependencyObject for that to work.
To summarize, my question is twofold:
A. Is it even possible to handle message recipient registration within the app.xaml for the subset of messages that involve the creation of Views.
B. Is this even an appropriate structure to try and apply or am I way off-base with my thoughts on how to organize responsibility for the handling of messages that relate to other views. If it is not an appropriate approach, is there an easier way or a better way?
The View should contain all view-related code and no programme logic - this is MVVM separation. If your view needs to display a message box, this must then be handled by code in the View. This is the same as animation which must be defined in the View but can be easier in the code behind.
MVVMLight messages allow a simple way for a ViewModel to say "I want to show this" and the View to decide how to show it. The View registers to receive the required type of message and deals with the UI part of showing it - be it a MessageBox or other.
A purely XAML, and probably prettier way would be to build a custom message box.
As for part B: I would receive messages where I wanted to handle them.

Question About Classic MVC

In classic MVC the model notifies the view about changes made on it. In C# this means I have to subclass the View I'm interested in and in the subclassed class register to the model's event. For example,
if I were to implement MVC using C# and Winforms, I had to subclass TextBox class and then register inside the MyTextBox's constructor for the model events. Am I correct?
How was this issued in Smalltalk? Does one also need to subclass every View in order to register the model's events, or is there some way to dynamically add events to the views on the fly?
Thanks
To address the sub-question about how Smalltalk (from which MVC originates) handles this: originally (this is Smalltalk-80, where Trygve Reenskaug implemented MVC) it was indeed necessary to subclass the view superclasses for your specific view to register it as a subscriber to change events from a concrete model subclass.
Controllers in Smalltalk were only to delegate or dispatch window events (esp. keyboard and mouse) to the model. Basically you can say the controllers modified model objects, and view only showed them.
However the concept of Dynamic Values, or ValueModels as they became to be called, made this approach obsolete in VisualWorks Smalltalk. Now you could create a standard GUI framework, no need to subclass anymore, and every view would be able to register itself as an observer to an abstract model class.
The model for the view would not be a model class anymore but a value model with a standard interface. More on this here: http://st-www.cs.illinois.edu/users/brant/papers/ValueModel/ValueModels.htm
I think the MVP pattern would be more appropriate for your winforms UI application.
What are MVP and MVC and what is the difference?

Categories

Resources