Communication between loosely coupled Components using Prism for UWP App - c#

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.

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

Is it an antipattern to use both traditional click events and ICommand?

Generally, I think it's good practice to use ICommands to handle button clicks that need to do something (such as save user input). However, when the button does something strictly on the UI, like open a modal dialog, the view model doesn't need to handle that, or even be aware it happened. In such cases, it seems like it makes more sense to just use the button's Click event handler, but mixing and matching like that seems like a potential anti-pattern. Am I correct in thinking so?
For example:
var openModalButton = new Button();
openModalButton.Click += OnModalButtonClick;
//Elsewhere in the view...
var saveInputButton = new Button { Command = _vm.SaveInput };
It's not inherently clear by looking at the code why one uses a command, and why one uses a click event.
Jedediah,
I usually do as you and mix and match. Usually (for me) there is only 1 or 2 cases like this, and the idea of patterns and architecture is to make the code easier to read and simplify things. Adding a lot of code just to ensure the MVVM pattern is followed seems like it complicates things in this case. That said, the way I've seen this usually handled is bind the button to your ViewModel with ICommand, and then use a "mediator" or "service" to launch the dialog. You could do a Google Search on: "HOw to handle opening a modal dialog the mvvm way " and/or see:
Open dialog in WPF MVVM
The "pretty" way to make a modal dialog in WPF with Prism and MVVM Pattern
Handling Dialogs in WPF with MVVM
Good luck!
Dave
Of course consistency is important as Robin pointed out. However there are scenarios when you'd not want the ViewModel to be involved. Then there's no choice and I think it is much better to break consistency here but not to break the pattern (MVVM) by handling stuff in the ViewModel that is not its job.
You took modal dialogs as an example and I do not agree that the ViewModel should not know about it. Of course the ViewModel is not allowed to directly open that dialog, settings its owner and the likes. But the dialog most probably is part of the workflow and it's just fine to know about the current state of the workflow in the ViewModel. So there should be a layer in between. A service or something similar that allows you to say "I want to show the UI for X" and that solves this by using a modal dialog. The ViewModel doesn't know about the modal dialog but it knows the current state, for example that it is asking the user whether to save changes. Of course this requires some kind of infrastructure handling the special cases and tricky parts. MVVM frameworks offer solutions for this.
If that sounds like overkill for your application simply put that event handling in the code behind of the view. It is not beautiful style but it does not break the MVVM pattern.
In one phrase: Better to mix than to violate the pattern.
I think it is an anti pattern, or not very cool thing at least,first because you're mixing the two approaches and that's not consistent, secondly because I believe that that needs always to be handled in a Command instead of an Event handler, why ?
the view model doesn't need to handle that, or even be aware it
happened. In such cases, it seems like it makes more sense to just use
the button's Click event handler
Not really, additionally to the fact that Commands help you separate your object from the logic that executes the Command thus it makes it loosely coupled, but it also help enhancing the reusability of your code, for instance someone in the future may want to change that button into a whole new control that might have a different event, and different args for the corresponding event ...
and that breaks your code, using a command however is better and is always compatible and reusable.
Moreover, Laurent Bunion explains in this article how Events are problematic :
For all their utility, event handlers have one problematic side
effect: they can create a tight coupling between the instance that
exposes the event and the instance that subscribes to it. The system
needs to keep track of event handlers so that they can be executed
when the event is raised, but the strong link this creates might
prevent garbage collection. Of course, this isn’t an issue if the
event handler is a static method, but it is not always possible to
handle all events with static methods only. This is a frequent cause
for memory leaks in .NET.
Another consequence of the tight coupling between an event and its
handler is that the event handler for a UI element declared in XAML
must be found in the attached code-behind file. If it is not there (or
if there is no attached code-behind file), the compilation will fail
with an error. This is especially an issue when working with list
controls and associated DataTemplates. When an element of the template
must be actuated, an event handler can be defined, but as a
consequence, the DataTemplate cannot be moved into an external
ResourceDictionary.

Composite events in locally scoped regions with Prism (CAL)

I'm starting to train Prism (CAL) with a small application and faced some problems.
I'm creating multiple instances of my MainView, which itself contains some regions, and display them in the Shell.
I'm using locally scoped regions to easily handle view injections within my MainView.
Currently I'm searching for a way of communication between the views (viewModels) inside the MainView. Composite events could do it, but when I publish those events, they are handled in all instances of my MainView, which I really don't want.
Is there a way of raising "locally scoped" composite events like with locally scoped regions? Or may be there's a better way of communicating between views in my case?
It's also possible to create locally scoped EventAggregator and register in a child UnityContainer, created in the MainView (at the same place, where locally scoped region is created).
This is an equivalent to a locally scoped regions imho.
Pass form sender as an argument. (Anyway, there must be a way to distinguish your application's windows - use it.) When you recieve the event, check whether current form ReferenceEquals to sender (Or, check the form 'key').
After much discussion, EventAggregator was selected. Sharing with other in case they are in the same situation and our thought process might help them:
(Problem statement: Refer to my previous comment)
The main View (ViewModel) which has regions to hold views from other modules and which also forms the TabItem view is responsible for cleaning up itself and child views it contains. Hence on TabItem closing event this main View (ViewModel) should inform its child views to gracefully shutdown.
Both EventAggregator and .Net Eventing were thoroughly explored from various aspects as potential candidate for sending the shutdown message.
Since, in a Prism decoupled environment the main View should be technically unaware of its child Views and vice versa, EventAggregator was chosen.
One issue with event aggregator is that it publishes events to whole application, but our requirement was to filter events coming from the tabitemview being closed. The EventAggregator was designed to use a filter to verify if the shutdown request is coming from the same tabitemview (we used scoped regionmanager for every tabItem and this scoped regionmanager was used as the filter) only then it executes the shutdown action. This ensures that triggering shutdown in one tab does not close child views in other tabs which happen to have the same regionname.
Thanks,
RDV

Update UI from external event

First of i am not a UI developer and this is probably a very simple problem.
What i have is a external service that I subscribe to an event, when ever that event fires a service picks this up, manipulates the data in some way then gives the UI the data to display
What i am unsure of is how to archetect this and keep the dependancy between the service which will tell the UI to update and the UI as loose as possible.
Can anyone suggest a stratagy for this or post me some links on examples or an open source project to actually look at some working code.
I am using c# and ether wpf or winforms for this.
Cheers
Colin G
How simple is this application?
The simplest solution is to have the data access/manipulation in one object, and have the UI passed as an interface into that object. With the UI interface methods, you can give data to the UI but let the UI handle displaying the data in a GUI thread-safe manner.
If it's a more complex application, I'd say it would make more sense to look into something like MVC or MVP. Or MVVM for WPF, maybe look at Bea Costa's blog for databinding examples.
My solution to this problem is to create a timer in your ui, and have your ui subscribe to the 'onTick' method. Then, at every timer tick, have the UI look at the service and figure out what data to display.
There's a lot of ways to skin this cat, but without knowing a little more about your requirements and your existing infrastructure, let me suggest you use an EventBroker / Mediator for this. This is an easy way to implement a kind of Publisher / Subscriber type of relationship without worrying about too much of the plumbing.
If you are using Prism, I'd suggest using the EventAggregator.
If not, you might consider using the "Messenger" implementation of an EventBroker available with the MVVMFoundation stuff that John Smith wrote. It's not really dependent on you using MVVM or WPF and does what you are looking for:
http://mvvmfoundation.codeplex.com/
Hope this helps.
then gives the UI the data to display...
I would suggest you to have a service agent layer which will raise an event and pass a DTO. This event should be subscribed by the layer which contains objects bound to the UI. Once this layer receives the DTO, update the UI.

Categories

Resources