Handling a framework-specific event and MVVM? - c#

In a WPF application that uses Prism, I have a shell in which there is a docking manager control.
Now I have to listen to an event coming from that docking manager, specifically, when one of its children docking state has changed.
To me, this event should be handled in code-behind as letting the view model do some work against that framework-specific visual control is worse than doing it code-behind.
Question:
Is this the right approach or am I missing something?

As long as the code is only related for the presentation then it is no problem to have it in "code-behind".
The main problem with "code-behind" is having the presentation logic split in two different locations XAML and "code-behind". There are several ways to avoid that using MarkupExtension, DependencyProperty, ValueConverter or custom (derived) controls.

Related

Building WPF app around third party control

I have to convert a decent sized Winforms application into a WPF app following the MVVM pattern. I'm not sure what the best way to do this is.
The application is built around a third party map control.
Multiple windows: A main window that displays the map, and other windows that allow the user to change properties of the map (add layers, change styles, etc).
My plan was to create a viewmodel for each window, and have a base viewmodel containing the map control itself and any properties/methods that needed to be shared.
The main thing I'm not sure about is how to handle the map operations that are built into the control. For instance, there is a MapMouse_Down event. Normally I would just put this in the code behind if I wasn't following MVVM, and handle it there. Is that the correct way to handle this?
Normally I would just put this in the code behind if I wasn't following MVVM, and handle it there. Is that the correct way to handle this?
You could keep anything that is purely view related in the code-behind of the views but anything that is testable application logic should be implemented in view models. View-related stuff may for example be animations and any code that changes the behaviour or appearance of a control in some way, like for example setting some width or colour.
There are different ways to handle "events" in MVVM depending on what kind of controls you are using but you would generally defined commands in the view model and invoked these from the view. Please refer to this blog post for more information.
Having a separate view model for each different type of window is ideal.
View models should never contain controls. They should contain only abstractions of the controls. If all of your windows have mapping components, only then should your base window view model have an abstraction of the mapping control. (An example of the sort of abstraction I'm talking about: Imagine a view that where the user should enter a name. The view will have a TextBox which has a Text property. The view model will have a Name property. The view will bind the TextBox's Text property to the view model's Name property. Figuring out the right abstractions for larger applications is one of the challenges of MVVM.)
It's perfectly fine to have event handlers in your view if your controls don't support data binding or they don't have ICommand support. But the event handler in your view should do as little as possible, instead just transferring control over to your view model, which will update its abstract representation of the view, which the view will then re-synchronize to through data bindings or manual synchronization logic.
WPF is different for Winforms, the approach is based on the binding of proprety .
Below an Example of using MVVM.
Easy MVVM Example

What is the best way to talk between WPF and WinForms controls?

My project is written in WinForms (C#). I have WPF user control (implemented as MVVM) that would be placed in the project. Some WinForms user controls should talk/react on changes made in WPF user control.
I can think of couple approaches:
user controls can expose properties. For example: UC3 will have reference to UC4 which will have reference to WPF-UC. UC3 will also have reference to UC2 which will have reference to UC1 and thus UC1 could subscribe to some events in WPF-UC.
to use some kind of Mediator and thus we keep the dependency to a minimum.
inject some kind of service which is basically can be Mediator.
I think that approach #2 is the best since I can always move the controls. On the other hand, what kind of cons/pitfalls in this approach can be? What do you think?
If approach #2 is the best is there any library that I can use instead of re-inventing the wheel?
For example, in image below - the TARGET should be updated on WPF UserControl changes.
Black - WinForms controls. Red - WPF control.
I would create delegates in the WPF ViewModel and since it's an instance created by the Winforms module- you can register there for those events, then you can direct other winforms components to act according to your liking because they are also connected to registered component.

What is the good way to interface Ribbon control with Caliburn Micro?

I'm using Caliburn Micro for my project, and I decided to use Fluent Ribbon as part of the UI. My ShellView is really simple, and it's laid out like this:
Ribbon Control with 4 tabs.
ActiveItem.
The Active item is dynamically changed depending on the Ribbon's selected tab.
Question:
What is the proper way to use Ribbon control as a second view for my currently active ViewModel (ActiveItem), while maintaining modularity and all the goodies which come inherit with CM itself? Also, what would it take to "share" my Ribbon control among my ViewModels?
Details:
My ShellViewModel is of type "Conductor.Collection.OneActive", and it changes the ActiveItem to specific ViewModel I associate with selected tab (when event is fired).
My Ribbon is defined in XAML like this:
<ContentControl x:Name="RibbonBar" Micro:View.Model="{Binding ActiveItem}" Micro:View.Context="Ribbon" />
As it shows, Ribbon control is bound to currently active item as it's context view. That actually works for one view, because due to default CMs conventions, where it looks for the contextual views in the sub namespace (e.g. if my path to the view is Views.TasksTabView, it will look for the Context view at Views.TasksTab.Ribbon).
Problem is, when I change the ActiveItem, context view can't be located anymore, due to the different namespace, so It only works for one Tab.
I've also tried writing my own ViewLocator convention but I had no success with it.
Thank you.
Unfortunatelly since there are no answers, I'll answer it myself.
I did manage to write the additional ViewLocator logic to locate my Ribbon, but that created some problems (It seems that binding in CM only works once, so after Ribbon being located and bound to the VM, additional context view changes do nothing. There were some hard to find bugs as well).
I've taken a different approach then. I've separated Ribbon to it's own ViewModel, and composited it to the shell with rest of the modules. It uses EventAggregator and I also Inject it where neccessary. Not approach I was hoping for, but it works for now.
If anyone posts better answer, I'll definitelly accept that one.

Creating an MVVM friendly dialog strategy

I'm trying to create a strategy for handling popup forms for use throughout any part of my application. My understanding so far is that I will need a single UserControl in the root of my MainWindow. This will be bound to its own ViewModel which will handle the messages that are sent within the app.
I'm using MVVM Light, and I'm fairly new to the Messenger class.
Imagine a Master/Details scenario, where a list a objects are contained within a ListBox. Selecting one of these items and clicking an Edit button would display a UserControl which covers the whole screen. The user can then edit the selected item, and click OK to commit the change.
I want the UserControl that is opened to be "generic" in a way that I can throw any (probably a ViewModel) at it... for it to render the ViewModel via a DataTemplate and handle all the object changes. Clicking OK will callback to the sending class and persist the change as before.
Some situations where this would be useful are...
Display error messages with no required user input (other than OK to close it)
Display an edit form for a data item
Confirmation dialogs (much like a standard MessageBox)
Can anyone provide any code samples of how I might acheive this?
When designing a UI with MVVM the goal is to separate the concerns of the View from the concerns of the ViewModel. Ideally, the ViewModel should not rely on any view components. However, this is the idal and another rule of MVVM is that you should design your application as you wish.
In the area providing a service showing dialogs there are two different approaches floating arround:
Implementing the DialogService on the View (e.g. see http://geekswithblogs.net/lbugnion/archive/2011/04/13/deep-dive-mvvm-samples-mix11-deepdivemvvm.aspx Sample 03).
Implementing a service component that does is not attached to the view (e.g. see http://blog.roboblob.com/2010/01/19/modal-dialogs-with-mvvm-and-silverlight-4/)
Both approaches rely on an interface that defines the functionality the service provides. The implementation for this Service is then injected into the ViewModel.
Also, do both approaches have their specific advantages and disadvantages.
The first approach works also well for WP7, however, it requires a common view base class as this contains the implementation of the view service.
The second approach works well for SilverLight and WPF and appleals as it keeps the service separate from the view and does not impose any restictions on the view.
Another possible solution is to use messaging to show the dialogs.
Whatever approach you are using try to keep the View and the ViewModel de-coupled by using an IoC (inversion of control) pattern, i.e. define an interface so that you can use different implementations. To bind the services into the ViewModel use injection, i.e. passing the service into the constructor of the ViewModel or by setting a property.
I recently started learning MVVM for a WPF app I was creating, I used this article as a basis for showing dialogs, if you download the sample project then it is actually quite a nice decoupled method, it is nicely abstracted and to get a view you pass an instance of a viewmodel. I extended it somewhat for my own means, I also used the WPFExtendedToolkit MessageBox for warnings, errors etc because the standard win32 MessageBox is fugly.
With regards to dynamic forms then you'll want to investigate the ItemsControl, and in your ViewModels have a Collection of Data Items which need to be edited by the user for the ItemsControl to bind to. I have a dialog for editing actions and their parameters in a workflow system designer where the dialog list of actions was totally dynamic. This was done by exposing a collection of my items with their data types so I could then use a DataTemplateSelector to select DataTemplates which contained the correct types of controls, i.e. a datatype of DateTime showed a DatePicker.
Hope That Helps
From the perspective of a developer coming in to 'maintain' that generic code, it sounds like a pain. From what you've described, I would give the form and the dialog the same view model and create a specific XAML template for the dialog that you want to show.

MVVM: How to avoid adding DataContext to Xaml for Blend Support

We have a C# solution that is based on loose Xaml (or Hosted Xaml - have never been to sure of the correct term!). But basically we take a Xaml file and load it into a XamlReader and then pop that FrameworkElement onto a UserControl. We require the ability to handle data binding and we have a ViewModel that takes care of this. However, although I can inject the DataContext through code by setting it on the newly created FrameworkElement, if I want to work easy through Blend and use the built in list of bindable properties when you select the 'Data Binding..." option on a property I need to have set the DataContext right there in the Xaml (if not Blend will add it to the Xaml). I'd rather not have to do this because as I say I am doing this through code already.
The question is - Is there any way to avoid this?
I was thinking of doing this somehow through the app.xaml but the problem is depending on the screen and when it is shown it will have a different context (so we dynamically change the context) and I'm pretty sure you can't load in multiple data contexts.
Maybe there's a better way of splitting this up. Our solution has the following: -
A WPF application with a MainWindow.xaml (the main application)
A User Control in a separate assembly that is placed on the MainWindow.xaml by the main WPF application (above)
This User Control is then bound to the View Model
The main application sets the DataContext as it goes through it's build in state machine.
All Loose Xaml files are held in the main application.
So basically depending on when the state machine displays a screen it will have a different Data Context. The State Machine handles pushing the Data Context and those screens will only work if they are used in the correct context. So we don't really need (or want) to have to set the data context in the Xaml. It done by the state machine.
But I haven't been able to find much info on the Tinterweb around Loose Xaml so we're pretty much learning as we go...
Thanks in advance!
Have you tried d:DataContext={d:DesignInstance ...} ?
It allows you to define a DataContext for design time only, for Blend and VS.

Categories

Resources