Composite events in locally scoped regions with Prism (CAL) - c#

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

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.

c# Best way to communicate between classes

Right now I am coding an application and am thinking that there has to be a better solution to what I am doing right now.
I have a main window which shall handle the settings of the program. Then I have further classes and windows. For example a language handler class and a form that is handling the user input needed for the "main function".
However, until now I always have to pass my main window to each of this classes, because the language handler shall be able to change the main window's strings. And the other form should also be able to pass data to the main Window.
If we imagine there will be much more classes and every class needs a copy of the main window this would consume a lot of resources depending on the main window's "size".
So, is there a better/more efficient way to communicate between these classes.
Common way to do that is to use observer pattern, which in .NET is events system. Simply said, your classes subscribe to each other's events and perform action when event is raised. As noted in comment, passing references is not memory heavy, but it results in tight coupling between different pieces of your code - observer pattern addresses that problem.
Another option is to consider you classes as services. Code them to an interface and then use dependency injection (aka Inversion of Control) to build up the object graph (You tell the IoC container you want a frmSomething and it will determine what services/classes it needs and instantiate them as appropriate).
This means that:
you only ever have to code against an interface not an implementation
your code is loosely coupled (You can swap an OldTranslator for a NewTranslator and as long as they both comply to the same interface, nothing has to be changed except the configuration of the container)
you can develop high-level features which rely on services that haven't been written yet and your code will compile
You can very easily change how your app works, at run-time if needs be, by changing what classes/services are registered in your container.
Have a look at Unity for the MS-Supported DI container. Castle Windsor is a popular alternative but there are many more
It's worth noting that passing a "Copy" of the main window around as you've said is not a bad thing - You're actrually only passing a reference (effectively a pointer) to the main window (since anything more complex than the real primitives are reference types). This means that there's very little overhead whatsoever
I would suggest you to use Galasoft or Prism MVVM implementations. There you can use their messaging service which is quite easy to use. The class that needs info just sends a message to the subscriber and they in turn can send all data needed. I think that this is the easiest way to handle communication.
in addition to the ans given by IVAN.. if we look at a higher level view without all those terminologies then you should probably create a static class which would server as InMemoryStorage and defines fields on it to save information
this what you will have complete control over what is being shared and multiple components can change it
moreover you can defined getters and setters and raise an event whenever the property is changed so that different forms or windows (views) can subscribe to the change and take action accordingly

eventaggregator vs services

When developping rather large applications using Prism and MEF/Unity I always reach a point where I should choose between using events, a service or maybe both. And I cannot decide what's most usable. Maybe something is wrong with my architecture (as in this decision shouldn't have to be made in the first place) but I don't see what.
Here's a typical example: my application has a main window and a lot of slave windows that are created on demand by modules or user actions. The application decides what a slave window's chrome looks and behaves like, remembers window placement etc while the content itself is created somewhere in the modules. There are also a lot of user actions resulting in hiding/showing/bringing to front of windows. To achieve all this, I currently have a WindowManager service that listens to CreateWindow/SetWindowState/.. events.
This has benefits:
classes using this only know about IEventAggregator (which they already use most of the time anyway for other events) and the events consumed by WindowManager, not WindowManager itself
classes like ViewModels don't deal with windows directly. Instead they refer to them by their title or id and small event classes that encapsulate just what's needed.
no need for a seperate IWindowManager interface just for the purpose of mocking it in a test
And withdrawals:
WindowManager could be used perfectly standalone, but now it needs to subscribe for events. Or probably better, some other class has to take care of that.
extending it to show a modal dialog is somewhat tricky: if a VM fires an event to show a dialog, it's of utter importance that the Publish call only returns after the dialog was closed
WindowManager is available as a service and it's in the CompositionContainer, why not use it as such anyway?
Using the service directly just shifts benefits/withdrawals around and there doesn't seem to be a clear winner.
Question: what would you use as guidance rules to pick one or the other, or would you rather always pick just one, or both? Is there something particularly wrong in my application design that I have to make this decision?
Events and services are used for different things. You don't have to choose between them, you can use them for different purposes. You would typically use event to notify listeners that something has happened. Example: users changes the font size in the application settings. You would send event to all listeners (e.g. viewmodels) so that the views update. Usually event is kind of thing for which you don't get a response (although you could attach e.g. callback function/action that the event listener would call).
What if your viewmodel needs to open new window? Usually the viewmodel shouldn't care how this new window is opened or whether it is modal or not. In this case it would be easy to use a service:
windowManager.ShowDetailsView();
The WindowManager (which you use through IWindowManager interface) is responsible for displaying the details view. Maybe it is a modal view or maybe there is some kind of slide animation. The point is that the viewmodel that uses IWindowManager doesn't care.
In some cases you might need to receive notification if users clicks Ok or Cancel. You can still use the IWindowManager by having method like this:
public void ShowEditView(Action userSavedChanged, Action userCancelled);
Then just call it from the viewmodel
windowManager.ShowEditView(this.SaveChanges, this.CancelChanges);
// in your viewmodel you have the SaveChanges and CancelChanges methods
private void SaveChanges()
{
// save the changes.
}
Hopefully this all makes some sense. After all it is friday :)

Categories

Resources