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.
Related
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
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.
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.
I'm using PRISM and MVVM in my modular Silverlight application. I'm still trying to figure out PROPER way to do interactions in MVVM fashion and 2 methods that PRISM and samples offer is not something I like for different reasons.
Method 1(PRISM): To use different region adapter. Basically, it involves attached properties on container and injecting view into region. This works almost 100% but negative of this method is that there is no good way to communicate results back. I can use EventAggregator but something doesn't feel right to raise event with data when interaction completed.
Method 2(PRISM): To use InteractionRequest. That involves trigger action and some big boilerplate XAML that I have to repeat on each view.
I'm thinking on creating something on my own which would require creating my own control which will have to be added to each view but with very little XAML and some kind of IPopupService that I can bind this control to. I can pass all needed data via PopupService but in order to actually make action of POPUP happen - I need to call method on this control and that falls apart in MVVM
I wonder how to call method on control in MVVM where view shouldn't be aware of VM ?
View has no option but be aware of VM, since it binds to it.
You could define some kind of a service indeed with a run-time implementation that would interact with the UI and design/test/debug implementation that does something else. You might also publish some events in your VM layer that the View layer would decide how to interpret.
First off, I don't think MVVM is a good choice if you are developing a UserControl that will be consumed by others. A lookless control is what you really should be developing. Jeremiah Morrill has a blog post about this subject.
With that said, you can set the datacontext with XAML if you have a default public constructor.
Inside ControlView.xaml put:
<UserControl.DataContext>
<local:ControlViewModel />
</UserControl.DataContext>
Please excuse my ignorance, I only started coding in Silverlight recently.
I tried implementing the command pattern in Silverlight and hit a wall.
They say commands are great, because you can write them into xaml, so you can keep your code-behind clean, also you have loose coupling between your view and your viewmodel because there is no direct reference to the viewmodel in the view.
You can not keep your code-behind clean, because you can bind only one command to a control, and you have to decide which event will fire your command when you bind it. If a control has 30 events, you have to choose one for commanding. The other 29 will execute the other commands from event handlers from the code behind.
Loose coupling can be achieved more simply by dependency injection, commands add a useless layer of indirection that gives nothing extra, they only make it a bit harder to maintain your code. It is easier to maintain your code, when you are programming against an interface and see exactly what method gets called, then when you have to keep jumping between your command definitions and your viewmodel.
Did I miss anything, or commands are really not meant to be used for view and viewmodel interaction?
Please see the following question. This is why I don't get all the hype with commands:
How should I handle multiple events per control w/command pattern using MVVM in Silverlight?
Take a look at Prism (http://prism.codeplex.com) and their DelegateCommand<> infrastructure. Its a good solution for Silverlight and WPF to create commands in the ViewModel (or Presenter) and bind directly to it. Also in Silverlight 3, Behaviors can give you some of this same XAML-based syntax.
SL 2.0 is not so powerful as WPF, you will have to write some code behind :-(.
Not sure if you have read this article about MVVM and SL, talks about commands limitations on SL:
http://msdn.microsoft.com/en-us/magazine/dd458800.aspx
I believe that you could trick your event handlers with attached behavior pattern.
Please see following url for more information:
http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx