True MVVM and third party controls - c#

In a True MVVM model we do not expect any code behind in xaml.cs also we do not expect viewModel to have refernece of view.
However all third party controls do not provide good support for True MVVM.
In my case I am using Infragistics xamDatagrid control and I want to export its data to excel. The only way I can export data to excel of data grid is by using following code:
xamDataGridExcelExporter.xamDataGridExcelExporter xamDataGridExcelExporter1 =
new xamDataGridExcelExporter.xamDataGridExcelExporter();
xamDataGridExcelExporter1.Export(**this.xamDataGrid1**,
#"C:\Excel\ExportFile.xls");
However, XamDataGridExcelExporter takes input as this.xamDataGrid. xamDataGrid is part of View not viewModel.
So how can we handle such kind of cases where we need instance of view in viewModel.

It is a common misconception that MVVM forbids code-behind. The truth is that code-behind is not reusable and it is inseparable from the view, so it cannot be unit tested without automation. But it does have its uses.
There is nothing inherently bad about code-behind. In fact, it's not much different than all the other code your write in support of your view like converters, custom controls, etc. None of this code can be tested by your view-model unit tests. The only difference with code-behind is that it is less reusable. But it's still part of your view and views are not bad.
In general, the absence of code-behind is a good indicator of a clean separation between the view and the view-model. However the presence of some code-behind in an otherwise clean design usually merely indicates something that is hard to do with the standard controls and data binding and commands.
In your case, exporting the XamDataGrid is definitely view-specific. It has to do precisely with the third-party library you have chosen for the view. So it makes perfect sense that it should not be part of the view-model.
If you are are still dead set against any code-behind, you can use behaviors, such as ACB or Blend Behaviors to write functionality that you would otherwise put into the code-behind. Just realize that even behaviors are still part of the view, only more reusable that code-behind.

You can write a wrapper around xamDataGrid that has a dependencyproperty called filename. The viewmodel can then bind to this property. When the xamDataGrid detects a change on the filename property it can then execute the code you suggested. Afterwards reset the filename property for further notification.
This solution keeps out the code from you code behind and makes the xamDataGrid responsible for exporting its data.
-------edit---------
A second solution can make use of the MVVM light messenger class. In stead of declaring a dependency property, make your wrapper listen to a message. When the viewmodel sends the message (which could for example have the filename as parameter) the wrapper can then execute the code.
eg
public class ExportableXamDataGrid: XamDataGrid
{
public ExportableXamDataGrid():base()
{
Messenger.Default.Register<string>(this,"ExportExcel",ExportFile);
}
private void ExportFile(string file)
{
xamDataGridExcelExporter.xamDataGridExcelExporter xamDataGridExcelExporter1 =
new xamDataGridExcelExporter.xamDataGridExcelExporter();
xamDataGridExcelExporter1.Export(**this.xamDataGrid1**,
#"C:\Excel\ExportFile.xls");
}
}
Then in your viewmodel you can do:
Messenger.Default.Send(#"C:\Excel\ExportFile.xls","ExportExcel");
There are many solutions to your problem, all of which you do not have to start writing logic in your view.
http://www.lucbos.net/2011/06/using-codebehind-in-mvvm.html

I'd use code behind because the 'problem' is cause by the view so I would keep it there.
Yes, that will break MVVM but using these controls it is already broken. By keeping the solution in the code behind you willl keep the ViewModel as clean as possible so when the controls do support MVVM it is easier to clean up.

I'd strongly recommend to use System.Windows.Interactivity.Interaction.Triggers in XAML and use the Event trigger to call a event of XamDataGrid and use 'CallDataMethod' which will call a custom method that you will create on the ViewModel. The best thing in this is that you will get the object(XamDataGrid) reference as sender.
This will be purely MVVM and you will be able to acheive your goal. Also, i would recommend to use WPF DataGrid which is very light weight as compared to XamDataGrid. Only use XamDataGrid if you are using some major functionalities provided by this control, cuz just to initialize this UI Element the processor takes 200 milliseconds or may be more.
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedCellsChanged">
<is:CallDataMethod Method="YourMethodNameInViewModel" />
</i:EventTrigger>
</i:Interaction.Triggers>
And in the View Model your Method i.e.
public void YourMethodNameInViewModel(Object sender, EventArgs e)
{}

Don't worry too much about it. Yes, having "heavy" views is opposed to the ideas of MVVM (thin views, testability). But there are always exceptions to the rule.
The decision here is using the "free/existing" XAMDataGrid export functionality or write your own MVVM version of it (which resides in the ViewModel).
If you choose Option1, you'd need to cache the View object within the ViewModel (use ctor injection) in addition the usual approach of setting View.DataContext = ViewModel and relying on data-binding to handle the rest.

Instead of keeping the Excel Exporter in ViewModel you can place it in a Behavior around the event you are triggering the export.
create a DataPresenter(xamdatagrid) type dependency property in your behavior and bind that to your existing xamdatagrid in XAMLcode to get access of your xamdatagrid. This way you'll functionally achieve and ViewModel will be free of UI objects.
<i:Interaction.Behaviors>
<behav:ExcelExporterBehavior MyDataPresenter="{Binding ElementName=myxamdatagrid,Mode=OneTime}"></behav:ExcelExporterBehavior>
</i:Interaction.Behaviors>
if MyDataPresenter is the property in ExcelExporterBehavior behavior which is set to any other UI control (say any button to export).

Related

How can control in the view get specific data from view model?

I have multiple of views (user controls), each with its own ViewModel. To navigate between them I am using buttons. Buttons display image and text from corresponding view model and also need column and row (because there are like 10 views: 10 columns with different number of rows each).
Right now buttons are created dynamically (I made a Navigator control for this) and for view models I have base class to hold text, image, column and row. Number of views available will be different (depends on user level and certain settings), that's why it's I need control here.
Question: how shall my control get data from view models?
Right now I have interface INavigator, defined in (lol) control itself. And view models implement it. I could go opposite, let my control to know about view models. Both looks wrong.
There is a single Navigator control what has, lets say, Items bound to a list of view models. It can cast each view model to INavigator or ViewModelBase (common for all pages) to obtain specific view model image, text, column and row. So either view model knows about control (to implement INavigator) or control knows about ViewModelBase.. And this is a problem, both solution bind tight control and view models, which is bad in mvvm.
Schematically
The way you've drawn your diagram answers your own question as to how you should structure the code for this.
What you need is one VM (let's call it MainVM) which contains an ObservableCollection<VMBase> of the other VMs (using your base type so that they can all happily live in the same collection).
Your View needs an ItemsControl (bound to your ObservableCollection<VMBase>) where you specify a DataTemplate for the Button using the properties exposed by the VMBase type only. Set the Command property in the Button to call SwitchCommand, CommandParameter is set to the item itself (i.e. {Binding .}).
Your View also needs a ContentControl bound to a SelectedVM property on MainVM which you can populate.
Implement SwitchCommand to set the SelectedVM property based on the value from the CommandParameter.
public void ExecuteSwitchCommand(object parameter)
{
var vmBase = parameter as VMBase;
if (vmBase != null)
SelectedVM = vmBase;
}
All properties mentioned here should be INotifyPropertyChanged enabled so that the View registers when they change and updates the UI.
To get the different UIs for the ContentControl, add type-specific DataTemplates for each of your specific VM types to the Resources file of your View (or if you're smart and are building a custom plug-in framework, merge the Resource Dictionaries).
A lot of people forget with MVVM that the whole point is that there is a purposeful separation of View from ViewModel, thus meaning you can potentially have many Views for a single ViewModel, which is what this demonstrates.
I find it's easiest to think of MVVM as a top-down approach... View knows about it's ViewModel, ViewModel knows about its Model, but Model does not know about its ViewModel and ViewModel does not know about its View.
I also find a View-first approach to development the easiest to work with, as UI development in XAML is static (has to be).
I think a lot of people get to wrapped up in 'making every component (M, V, VM) standalone and replaceable', myself included, but I've slowly come to the conclusion that is just counter-productive.
Technically, sure you could get very complicated and using IoC containers, create some ViewLocator object which binds a View-type to a ViewModel-type, but... what exactly does that gain you besides more confusion? It makes it honestly harder (because I've done this at one point) to develop because now you've lost design-time support first and foremost, among other things; and you're still either binding to a specific view model interface in your view or creating the binding at run-time. Why complicate it?
This article is a good read, and the first Note: explicitly talks about View vs. ViewModel. Hopefully, it will help you draw your own conclusions.
To directly answer your question, I think having your ViewModels implement an INavigator interface of some sort is probably ideal. Remember your VM is 'glue' between your view and model/business logic, its job is to transform business data into data that is consumable by your views, so it exists somewhere between both your UI and business layers.
This is why there are things like Messengers and View Services, which is where your navigator service on the ViewModels can fit in nicely.
I think the design has led to a no way out situation.
I believe that creating a custom button control where the dependency properties tie the image, the row and column actually provide a way for the page, which it resides on ,to get that information to them; whether they are dynamically created or not.
Continuing on with that thought. There is no MVVM logic applied to a custom control, the control contains what it needs to do its job and that is through the dependency properties as mentioned. Any functionality of the button should be done by commanding; all this makes the button data driven and robust enough to use in a MVVM methodology or not.
Question: how shall my control get data from view models?
There should only one viewmodel which is the page the control resides on. The control is simply bound to information which ultimately resides on that VM. How it gets there, that is up to the programmer. If the button is going to contain state data, that is bound from its dependency property in a two way fashion back to the item it is bound to.
By keeping VMs out of the buttons and only having one VM that is the best way to segregate and maintain the data. Unless I am really missing something here....
Same as others here I find it a bit hard to actually understand what you are asking, so this is quite general. The answer to the question header is simply: the Control gets the data from the ViewModel through bindings, always. You set the DataContext of your Control to the corresponding ViewModel, and from there you keep the ViewModel and the Control synchronized:
If you add an ItemsControl containing buttons to the View, you add an ObservableCollection<ButtonViewModel> to the ViewModel and bind the ItemsSource of the ItemsControl to this.
If you allow the user to dynamically add content to the View, the actual code that does it resides in the ViewModel, e.g. when the user clicks on a button "Add Button", you use the Command property to call a ViewModel method that adds a ButtonViewModel to the collection and the View will automatically reflect your changes.
There do exist complicated cases that are impossible to code exclusively in the ViewModel, I have found Behaviors to be the missing link there, but I'll get into that when you show me the specific case.
If you'd like to get a working example, please provide as much code as you can, with your exact expectations of what it should do.

Dynamically generating controls in WPF using Prism, MVVM, MEF

I am using WPF with Prism and MEF for my application. There was a need to create controls dynamically. And so here is my problem!!
As far as I know I should not be having code in my code behind (SomeFile.xaml.cs) to keep my code easily testable. And so the code should be actually moved to ViewModel.
But my code generates UI controls dynamically. And I dont think that the ViewModel should know anything about the Controls.
So where and how should I go about writing this code?? What would be the right approach?
Hope I made myself clear!
Thanks
When working with WPF/MVVM, your data layer is your application (the DataContext), and you use things like Templates to tell WPF how to draw your application components to the UI.
For example, suppose you're given the task to dynamically render a bunch of controls.
The WinForms way might have been to loop through your objects, create a UI control for each object, then add the UI control to the screen.
However with WPF/MVVM, you would instead create a class representing each object (a Model), and give WPF a list of those classes to display.
There are many different controls WPF can use to draw a list of objects, but the most basic of them is probably an ItemsControl. I have some examples of a simple ItemsControl on my blog if you're interested.
Now even though you've given WPF the list of your objects to render, and told it what control to use to render the list, it still probably doesn't know how to draw your object. The usual solution for this is to include an XAML template of some kind to tell it how to draw your object.
Here's a simple example template that is used to tell WPF how to draw an object of type MyClassObject:
<DataTemplate DataType="{x:Type local:MyClassObject}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name:" />
<TextBox Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
I hope that helps get you going in the right direction :)
From my perspective, the view has the responsibility to render the data/model provided by the viewmodel. While it is ideal to keep as much of the model->view translation logic in the viewmodel, creation of controls adds significant complexity to move to the viewmodel, because of the coupling or infrastructure that it could add.
While you could:
1) Give the viewmodel direct access to the view, allowing it to create controls directly
This adds coupling...
2) Create an interface on the view to manipulate controls
This means the view must be passed (not simply bound) to the viewmodel
3) Create an abstraction of controls to bind to the view, and have the view render based on the abstraction created by the viewmodel
This adds a maintenance nightmare as your control set expands.
I suggest exposing the model (either directly or wrapped in micro-viewmodels) via a property on the main viewmodel, and binding that to a property on the view via xaml, such that any PropertyChanged on the viewmodel will send an update to the view. Use the model information and your control creation logic inside the view to clear and re-create the controls and bind the model dynamically to the controls you create. This will simplify both the creation and binding of the controls, and you won't have to practice any voodoo to get information entered into the controls back into your model.
Note that even if you created an intermediary class (an attached behavior, adorner, or something else), it will still need to be able to access the view's control structure directly to attach the generated controls to the visual tree, which may cause other problems.

Should I always use Command even though it might not be necessary?

Should I always use Command even though it might not be necessary?
Or should I only use Command in the case where more things, menu items, buttons,
whatever, when clicked execute the same code?
Maybe it is good practice to always use Command, or maybe it adds additional
unnecessary complexity. I am new to WPF so please share some advices.
If you're using the MVVM pattern, which is mandatory in every serious WPF application, 'ICommand' is the way to go for every action that is not purely interface logic.
I'll explain:
As you probably know, the MVVM pattern distinguishes between Model, ViewModel and View, where the ViewModel mediates between Model and View. The ViewModel usually holds all the data which is consumed by the view and which you bind your view to. The important thing is:
The View is agnostic of the ViewModel
This means, although your View is bound to the ViewModel, it doesn't reference it, there is no logical dependency to the ViewModel. The 'ICommand' bridges this gap: It kind of packs an action into a bindable property. That's the main point, probably:
A command wraps up an action or function into a WPF databindable
property
And as databinding is the mechanism which, in MVVM, View and ViewModel are connected with each other, the command is the vehicle to perform every action, no matter if it is triggered by one control or by many, that transcends the sphere of pure UI (which is almost everything):
Have a look here (MSDN), where this image is taken from:
If you don't use MVVM I'm not sure whether you need commands at all. There is no significant difference to WinForms then, regarding the UI event handling. But again: MVVM and WPF go hand in hand, in my opinion.

Should I write classes for WPF controls?

I have a grid which I call let's say FooHistory. Now I need plenty of functionality related to that so I go ahead and I create a FooHistory class. Now I have a FooHistory class and a control.
In my MainWindow constructor I create a new instance of this class and pass the instance of this (i.e. the MainWindow) to the FooHistory class sort of like dependency injection. Then later when the FooHistory class wants to interact with the FooHistory control, I do things like this.mainWindow.FooHistory.Items.Add(...).
My question is that is this the recommended way to write WPF applications or am I missing some fundamental approaches?
We use for our programs the MVVM approach. While the details may differ from program to program MVVM is usually build with 3 main parts.
Model:
This is you data object. This may be business data like
class Account
{
string Name {get;set;}
string Address {get;set;
}
but can also be UI data like:
class Window
{
Point Position {get;set;}
Size Size {get;set;}
}
These objects are for holding data, nothing more. No events, no commands no methods (Thats one point where different interpretation of MVVM differ).
ViewModel:
This is to wrap the model and provide logic around the underlying model. This class is also used to convert a business model property into a view understandable property.
class AccountViewModel
{
public AccountViewModel(Account aWrappedModel)
{
}
string Name {get {return Model.Name;} }
AddressObject Address { get{ return new AddressObject( Model.Address ); }
}
View:
Is the wpf part this can be user controls, custom controls, windows, datatemplates etc.
Despite a common believe, its fine to have code behind for view otherwise you have to bend over backwords just because you heard that the view isn't allowed to have code.
The usual approach now is to create a model, one or more viewmodels and set these viewmodels as DataContext in your view. Sometimes you need a DataTemplate to display the given data, like a DataTemplate for our AccountViewModel.
<DataTemplate DataType="{x:Type AccountViewModel}">
<StackPanel>
<TextBox Text="{Binding Name}/>
<Button Content="Save" Command="{Binding SaveAccount}"/>
</StackPanel>
</DataTemplate>
This design makes heavy use of Databinding which is fundamental for MVVM and works quite nicely. Of course a couple of problems can arise like: How to handle Collection with models? How to handle events in the viewmodels coming from the ui? How to store my data?
But for these you find many resources here and in the web. But this answer should give you a rough overview of how i and alot other people work with WPF.
if most of your functionality is presentation-logic,
you can create a user control (by subclassing UserControl), and have a pair of .xaml and .xaml.cs files,
and put your presentation logic in the .xaml.cs file.
if most of the FooHistory class functionality is business-logic (or anything other than presentation), it's worthwhile to separate the FooHistory control from the FooHistory class, but in this case perhaps it's better to define an interface for the control, and pass the FooHistory instsance a reference to the control using this interface.
this way your FooHistory class needn't know anything about presentation - doesn't even need to know that it's WPF.
if you can avoid passing a tree of controls (such as SomeWindow.ParentControl.ChildControl.Items), it would make your life easier.
What you've described sounds like some kind of Model-View-Presenter pattern, a variant of MVC. As it is definitely a good pattern, especially for ASP.NET and WinForms, it doesn't utilise some core concepts of WPF.
Things you're missing are called Data Binding and Commands. On top of that features a new variant of MVC evolved - Model-View-ViewModel (MVVM), sometimes called Presentation Model. Roughly explained:
Your Window is called a View.
Youd Busines Logic is encapsulated in a Model.
You create a ViewModel class that exposes some properties which are View-specific representation of the Model. VM should also implement INotifyPropertyChanged to provide a way of notifying the UI about data changes. You expose operations the same way - by a property of type ICommand.
In View's constructor you write something like this.DataContext = new ViewModel()
Then you bind your View controls properties and ViewModel using {Binding PropName} syntax.
You might also want to check out some frameworks for MVVM like Prism, MVVM Light.
Here is some sample: http://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/
Yes you can...... but there is no need to do that...........
the alternative way is.........
Make a dataset of data used in your grid......then import that whole dataset into your grid. so here no need to add items..... now you can filter,sort, add,remove or anything you want....

MVVM - what is the ideal way for usercontrols to talk to each other

I have a a user control which contains several other user controls. I am using MVVM. Each user control has a corresponding VM. How do these user controls send information to each other? I want to avoid writing any code in the xaml code behind. Particularly I am interested in how the controls (inside the main user control) will talk to each other and how will they talk to the container user control.
EDIT:
I know that using events-delegates will help me solve this issue. But, I want to avoid writing any code in xaml code-behind.
Typically, it's best to try to reduce the amount of communication between parts, as each time two user controls "talk" to each other, you're introducing a dependency between them.
That being said, there are a couple of things to consider:
UserControls can always "talk" to their containing control via exposing properties and using DataBinding. This is very nice, since it preserves the MVVM style in all aspects.
The containing control can use properties to "link" two properties on two user controls together, again, preserving clean boundaries
If you do need to have more explicit communication, there are two main approachs.
Implement a service common to both elements, and use Dependency Injection to provide the implementation at runtime. This lets the controls talk to the service, which can in turn, keep the controls synchronized, but also keeps the dependency to a minimum.
Use some form of messaging to pass messages between controls. Many MVVM frameworks take this approach, as it decouples sending the message from receiving the message, again, keeping the dependencies to a minimum.
Your conceptual problem is here:
Each user control has a corresponding VM.
Having a separate ViewModel for every view pretty much defeats the concept of a ViewModel. ViewModels should not be one-to-one with views, otherwise they are nothing but glorified code-behind.
A ViewModel captures the concept of "current user interface state" -- such as what page you are on and whether or not you are editing -- as opposed to "current data values'.
To really reap the benefits of M-V-VM, determine the number of ViewModel classes used based on distinct items that need state. For example, if you have a list of items each of which can be displayed in 3 states, you need one VM per item. Contrarily, if you have three views all of which display data in 3 different ways depending on a common setting, the common setting should be captured in a single VM.
Once you have strucutred your ViewModels to reflect the requirements of the task at hand you generally find there is no need nor desire to communicate state between views. If there is such a need, the best thing to do is to re-evaluate your ViewModel design to see if a shared ViewModel could benefit from a small amount of additional state information.
There will be times when the complexity of the application dictates the use of several ViewModels for the same model object. In this case the ViewModels can keep references to a common state object.
There are many differenct mechanisms for this, but you should first find out in what layer of your architecture this communication belongs.
One of the purposes of the MVVM framework is that different views can be made over the same viewmodel. Would those usercontrols talk to each other only in the view you are currently implementing, or would they have to talk to each other in other possible views? In the latter case, you want to implement it below the view level, either in the viewmodel or the model itself.
An example of the first case may be if your application is running on a very small display surface. Maybe your user controls have to compete for visual space. If the user clicks one usercontrol to maximize, the others must minimize. This would have nothing to do with the viewmodel, it's just an adaption to the technology.
Or maybe you have different viewmodels with different usercontrols, where things can happen without changing the model. An example of this could be navigation. You have a list of something, and a details pane with fields and command buttons that are connected to the selected item in the list. You may want to unit test the logic of which buttons are enabled for which items. The model isn't concerned with which item you're looking at, only when button commands are pressed, or fields are changed.
The need for this communication may even be in the model itself. Maybe you have denormalized data that are updated because other data are changed. Then the various viewmodels that are in action must change because of ripples of changes in the model.
So, to sum up: "It depends...."
I think the best solution would be using Publisher/Subscriber pattern. Each control registers some events and attaches delegetes to events exposed by other controls.
In order to expose events and attach to them you would need to use some kind of Mediator/EventBroker service. I found a good example here
The best way to do this in my opinion is via Commanding (Routed Commands / RelayCommand, etc).
I want to avoid writing any code in the xaml code behind.
While this is a laudable goal, you have to apply a bit of practicality to this, it shouldn't be applied 100% as a "thou shalt not" type of rule.
You can communicate between elements on the UI by using element binding, so assuming a user control you created exposes a property, the other user controls could bind to it. You can configure the binding, use dependency properties instead of basic properties / implement INotifyPropertyChanged but it is in theory possible, but does require some forethought to enable to communication this way.
You will probably find it far easier using a combination of events, code and properties than try a pure declarative way, but in theory possible.
You can share some View Model objects between controls as well as Commands...
For example, you have some main control, which contains two other controls. And you have some filtering functionality in the main control, but you want to allow user to set some part of the filter in the first sub-control (like "Full filter") and some part of the filter in another (like "Quick filter"). Also you want to be able to start filtering from any of sub-controls. Then you could use code like this:
public class MainControlViewModel : ObservableObject
{
public FirstControlViewModel firstControlViewModel;
public SecondControlViewModel firstControlViewModel;
public ICommand FilterCommand;
public FilterSettings FilterSettings;
public MainControlViewModel()
{
//...
this.firstControlViewModel = new FirstControlViewModel(this.FilterSettings, this.FilterCommand);
this.secondControlViewModel = new SecondControlViewModel(this.FilterSettings, this.FilterCommand);
}
}
public class FirstControlViewModel : ObservableObject
{
//...
}
public class SecondControlViewModel : ObservableObject
{
//...
}
In the main control XAML you will bind sub-controls DataContext to the appropriate View Models. Whenever a sub-control changes filter setting or executes a command other sub-control will be notified.
As others have said you have a couple of options.
Exposing DepedencyProperties on your user controls and binding to those properties provides a pure XAML solution in most cases but can introduce some UI dependencies in order for the bindings to see each other
The other option is a decoupled messaging pattern to send messages between ViewModels. I would have your user controls bind to properties on thier own VM's and then on the property change inside that VM it can "publish" a message that notifies other "subscribers" that something has happened and they can react to that message however they want to.
I have a blog post on this very topic if it helps: http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html
If you're using strict MVVM, then the user-control is a View and should only "talk", or rather, bind, to its ViewModel. Since your ViewModels most likely already implement INotifyPropertyChanged, as long as they have a reference to each other, they can use the PropertyChanged events to be notified when properties change, or they can call methods (better if it's through an interface) to communicate with each other.

Categories