Call a method in app.xaml.cs from ViewModel - silverlight

I have some common code written in three ViewModels, which should be refactored. I have moved the code in a method in app.xaml.cs. Is this a right approach ? Now I have to call this method from the ViewModels, should I raise a custom event (from all ViewModels) and handle it on the app.xaml.cs ? If yes that would mean I have to create references of the ViewModels on the app.xaml.cs page (we are using Unity).
Does this seem right ? I am new to MVVM, any other suggestions ?
Any help will be appreciated.

You haven't mentioned what the code is. Why is it in the App.xaml.cs file?
The fact that you need to call it from three different ViewModels would indicate that you should refactor it into either:
a static helper type class
a base class that your ViewModelss inherit from
The ViewModel's job is to hold and shape (or transform) data ready for display, but it shouldn't know about the display. Nor should it know about the contents of the App.xaml.cs, especially as your ViewModels may end up being in a totally different module or assembly to the App.xaml file.

Any time you have "Cross cutting" challenges like where 2 totally separate objects need to communicate, an event style (publisher/subscriber) pattern works well.
If you are using Unity, then use the EventAggregator.
That way you can simply publish an event from your VM and have your app.xaml.cs listen for the event.
this way you wont have to let your VM know about app.xaml.cs.

Related

WPF - How to run a method of a custom control from a view model?

I work on a custom WPF Diagram Control. The control has a method that arranges the elements in the Diagram and I need to add MVVM support to call this method from my View Model.
At the moment I am a bit confused how to implement this and I hope that someome can point me to the right direction.
Maybe you need to rethink your concept. What needs to be re-aranged?
Think of ViewModel the logic behind a view and the view should be as dump as possible without any logic.
I assume also that the "arranges" method should be well tested and this could also be "easier" done on a ViewModel (if done right). Your best bet would be to place all logic in the ViewModel.
From the top of my head I could think of a DiagramViewModel with an ObservableCollection<ShapeViewModel>. ShapeViewModel can either be a base class or a concrete class which could also have some information about the location of the shape etc. The communication between the view models can be done via a Messenger (MVVM Light Messenger) or EventAggregator https://msdn.microsoft.com/en-us/library/ff921122.aspx.
If you still want to leave your architecture as you have it and want to execute a method on the view I would abstract it in a service. IDiagramUpdateService.
Look at following article which gives you good insights in communication between views and view models (and vice versa).
https://msdn.microsoft.com/en-us/magazine/jj694937.aspx
You'll find great information for both approaches.
HTH
Thanks for the quick response to my question.
I think my concept was a bit wrong, since the ViewModel should have no reference to the View.
What I would like to achieve is that I can place a button in the Main Window that calls the Arrange Method in the Custom Control.
I realized this by adding a RoutedCommand to my Custom Control.
And the Command Property of the button on the main window is bound to this RoutedCommand.
So the ViewModel is no longer involved in calling this method. It just manages the items that are shown in the Custom Control.

How to implement print operation using MVVM

In my view-model i have an command which implements print operation using PrintVisual of PrintDialog class . As i don't have the access to the view i cannot print it .how should tackle this ?
Is there an easier and better approach?
I think your solution would be to pass a service class in that performs the work of printing the grid, showing a dialog, and whatever work is required to get the job done.
In MVVM, most of people use dependency injection to do this. You would create another service with the same interface for your tests to use that wouldn't block execution. The service, in this case, is a view layer service, and should have no dependency back to the viewmodel. The only thing the viewmodel knows is that it has a service interface to call into, and the only thing the service knows about the viewmodel is the interface it implements for this interaction.
I read this Wikipedia article that has helped me in the past:
SOLID - Wikipedia
Let me know if this makes sense.
This is how i solved it.
I created an event in my viewmodel. Raised the event here whenever i want to print operation.
I defined my listener method in the mainwindow.xaml (this is where i have defined my content presenter , and all the data templates are being assigned to this contentpresenter.content)
In this listener method i am calling the print operation using PrintVisual of PrintDialog Class.
!

Standalone Command Objects in WPF

Is it possible / practical to implement WPF commands as standalone objects? If so, how is this typically done? Most of the examples I see about commanding typically involve using RoutedCommand, RoutedUICommand, or some other implementation of ICommand like RelayCommand. The way these commands work in the MVVM pattern is to expose an instance of one of these types of commands through a property. Inside the ViewModel, the logic for the command is implemented as a method on the ViewModel and then passed as a delegate to the command object.
The "classic" Command pattern as I understand it would be to have each command implemented as it's own standalone object, such as an OpenCustomerViewCommand. Since the logic would be completely encapsulated in its own object, it could potentially be reused in other parts of my app. For example, if I could open the CustomerView from several places in my app it might be helpful to be able to simply create an instance of the OpenCustomerViewCommand on each ViewModel where the CustomerView could be accessed, rather than copy and paste that method into each ViewModel, and pass the delegate to a RelayCommand. If I understand correctly, the predefined ApplicationCommands such as Cut and Paste behave this way.
To me, having to provide the logic inside the ViewModel seems to diminish the value of the command pattern a bit. I suppose I don't really understand the major difference between doing it this way, and having a code behind that implements command handlers for UI events. Is there any reason I should be using the RoutedCommand pattern over the more classic approach I described above?
You could do this, but it requires some method of routing the request appropriately.
In your example, provided the OpenCustomerViewCommand knows how and where to open the "Customer View", you could easily reuse this anywhere. Instead of using a class like RelayCommand, you can just implement ICommand directly and add your logic to do this.
The problem, however, is that most commands tend to be more of an adapter for xaml to execute ViewModel-specific functionality. In most applications on which I've worked, there tend to be few commands that really need the reuse - most commands are tied to functionality specific to the ViewModel in question. As such, something like RelayCommand makes hooking this up fairly easy.

viewmodel have to be public. How should I deal with that?

Pretty much it summarizes my problem here:
Double check - does it ever make sense to have internal viewmodel class?
I have controls.DLL and I'd like to keep this custom control bindings and viewmodel's internal. However, this doesn't seem to be possible.
How do you get around that? The only way I see it - don't use bindings..
Why do you have a view model for a custom control? I assume you're assigning the view model object to the DataContext property, but this is almost always a mistake: the DataContext should be available to consumers to use and abuse as they please. Stated another way, what happens if a consumer of your custom control explicitly sets the DataContext? It sounds like your control will stop working and throw a bunch of xaml binding errors.
A custom control is inherently lookless. There is no model or view model, just a view. That view is the .cs file. You supply a default look via your themes/generic.xaml file, but consumers should be able to supply their own template. If you're tying them to a view model, they also need to know how to create a view model instance and all of its dependencies. You've just created highly coupled code. DI containers can loosen the coupling, but that just downgrades the relationship between classes from "coupled" to "related". I say, why do consumers even need to know that information?
A better approach is to provide all of the properties for your control as dependency properties. Then your generic.xaml can provide a control template that uses the more efficient TemplateBinding to bind properties/objects to your control. If you need to populate these dependency properties from a business object, expose another dependency property of type IBusinessObject and set the derived values in that object's PropertyMetaData changed handler. If your IBusinessObject type contains a property which is yet another class which implements INotifyPropertyChanged, you should probably (1) rethink your object graph or (2) create a Bnding object in code using the subclass.
I think following all of the above advice will eliminate the problem about which you're concerned plus the other problems as well. Leave the view models to the UserControls. And yes, this is why custom controls are a MASSIVE headache. Doing them right is fairly involved.
Try protected internal. I suppose this should work. Although I don't think its good idea to have the ViewModel not public at all, cause one of the purposes of it is to be able to define several Views against the same ViewModel, which may come from different assemblies.

Using MVVM in WPF, should I launch child windows from View code behind, or ViewModel?

I've been puzzled by this for a while. I am writing quite a large RibbonWindow WPF application using the MVVM pattern. The screen has a RibbonBar menu along the top and the rest of it displays the various Views. Some Views contain other Views and some of these have buttons that launch child Windows.
So far, I have been doing this from the View code behind file, but I'm aware that these files are supposed to be empty when using MVVM. I could move the child window launch code to the ViewModel, but then I would need a reference to the main RibbonWindow (to set as the child window owner) and that doesn't seem right.
Any advice or tips on how this is normally achieved using MVVM would be greatly appreciated.
I usually handle this by creating some sort of WindowViewLoaderService. When your program initializes you register your Window's and your ViewModels with code something like this:
WindowViewLoaderService.Register(TypeOf(MainWindowView), TypeOf(MainWindowViewModel));
WindowViewLoaderService.Register(TypeOf(MyWindowView), TypeOf(MyWindowViewModel));
Then when you can for example call into this service from your ViewModel and all you have to reference is your other ViewModel. For example if you are in your MainWindowViewModel you might have code like this:
var myChildWindowVM = new MyWindowViewModel();
WindowViewLoaderService.ShowWindow(myChildWindowVM);
The WindowViewLoaderService would then look up what View is associated with the specified ViewModel you passed it. It will create that View, Set its DataContext to the ViewModel you passed in, and then display the View.
This way your ViewModels never know about any Views.
You can roll your own one of these services pretty easily. All it needs to do is keep a Dictionary with the key being your ViewModelType and the value being your ViewType. The Register method adds to your dictionary and the ShowWindow method looks up the correct view based on the ViewModel passed in, creates the view, sets the DataContext, and then calls Show on it.
Most MVVM Frameworks provide something like this for you out of the box. For example Caliburn has a slick one that just uses naming convention its called ViewLocator in this Framework. Here is a link that summarizes: http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/04/mvvm-study-segue-introducing-caliburn-micro.aspx
Cinch on the other hand calls it a WPFUIVisualizerService which you can see in action here:
http://www.codeproject.com/KB/WPF/CinchIII.aspx
These should help get you rolling.
Well, one remark to start with is that, "Having no code AT ALL in the code-behind" is actually a "myth". If you want to be pragmatic, and you see that having some code (as little as possible would be better), will make your life easier and solve your problem, then you should go with that.
However, in this situation, there are actually some loosely coupled ways to do this. You could have a service that does the interaction for you. You initiate the interaction with the user from the ViewModel, the service takes care of that (by showing a ChildWindow for example), and gives you back the user's reponse. That service can be mocked for testing easily. And it can be tested seperately.
That is, if you want to do things yourself. If you want a framework to do the heavy lifting for you, you can check out the InteractionRequest functionaity offered by Prism. Here's the MSDN article that talks about adanced MVVM scenarios which includes a section on User Interaction Patterns. That's the way I do it, and it's pretty simple, elegant and straightforward.
Hope this helps :)
To take Matt's answer one step further, you can have all your view's be a user control. Then create a ViewContainer, which is a window with your data templates (as you described).
Then you just ship the viewmodel you wish to open over to the window service, which sets the DataContext. The service would then open the window and the contentcontrol will resolve the correct view for the viewmodel.
This means all the registration is done in the XAML and the window service just knows how to do just that...open and close windows.
This is an old post, but maybe this'll help someone along the way: I use MVVM, and raise events for opening child windows from the ViewModel back to the View. The only code behind is handling the event, opening the window, setting owner of the child window and that's pretty much it. In the viewmodel, if the eventhandler is null, then it's not subscribed to by the view and doesn't fire. The VM does not know about the view. The code is pretty simple also and only takes a few lines.
In this situation View should handle the opening of the child windows.
However, ViewModel might drive the creation of the windows, but calling into View to create a new Windows.
This will save the logic of MVVM pattern: ViewModel has the "brains" but is not involved in a particular window creation.
ViewModel only is used to present system state and UI logic. One viewmodel may be referenced by multiple views. It have no knowledge of UI specific code like parent/child relationship, position, layout, size etc. So it is better to pop child window in view's code-behind with ViewModel's state changed event or command event and event arguments. In this way you can specify which one is the parent view in the UI layer.

Resources