MVVM - Controls versus Views - wpf

I've been doing a prototype in WPF without using MVVM. It's got to such a size now that I'm refactoring it to use MVVM.
When I started the project, I jumped straight in and created UserControls for lots of things.
I'm now breaking things in Views and ViewModels. But, I'm ending up with Views that contain UserControls; the UserControls have bindings to what are now objects in the Model.
So, is the notion of UserControls now dead in MVVM? What I mean is, in the past (WinForms, ASP.NET etc.) you'd have a project called 'Controls' and reuse these. Is the 'View' in MVVM a direct replacement of the typical UserControl?

A UserControl in WPF is little more than a ContentControl with a few tweaked default property values. A ContentControl is little more than a piece of content that can have a template applied to define its look.
The way I do MVVM skips the middleman and defines views as DataTemplates. Then you need only stick your VM into WPF's visual tree somewhere, and WPF will render it with your DataTemplate. For example:
<ContentControl Content="{Binding SomeViewModel}"/>
<ItemsControl ItemsSource="{Binding SomeViewModels}"/>

The way I see UserControls in the MVVM world is as a View. Rather than thinking of your WPF form as a single view, you can think of it as a composite of one or more views. So a UserControl can encapsulate a standard re-usable view that can be incorporated into multiple composite views. Great for re-usability and still they're still testable.

Mmmm... when I had user controls I just passed the DataContext from the View to the user control (the subinfo needed by that user control). But is true, that sometimes is hard to fit ViewModel with Views, UserControls, ...

Related

Binding control WPF break encapsulation

First of all, I use MVVM pattern in WPF.
I have a ViewModel which contains a grid. In order to render the grid in the view, I have to do the property of the grid public.
In this way the encapsulation of the control has been broken because if I want to use the control in other view models the grid is available for modifications.
Is there some solution about this problem?
I think Microsoft has screwed up, what is your opinion?
a viewmodel should not have a grid :) just the view. the viewmodel just have a collection for your grids itemssource.
edit: maybe what you want is some kind of usercontrol with Dependency Properties?

Xaml file in other Xaml file

I am basically new to WPF.I have 2 Xaml files.
WpfCurrentSessionViewer.xaml and MainWindow.xaml.
Say WpfCurrentSessionViewer acts as a control which has labels in it.
MainWindow is the xaml where we need to inscribe the control.
Say in Asp.Net applications , we have an aspx page and a master page.
In similar way I need to do that as WpfCurrentSessionViewer.xaml acts as a master page
and MainWindow.xaml acts as an aspx page .
Regards,
Sachin K
I think your question contradicts itself in terms of which way around the two controls are:
Say WpfCurrentSessionViewer acts as a control which has labels in it. MainWindow is the xaml where we need to inscribe the control.
WpfCurrentSessionViewer.xaml acts as a master page and MainWindow.xaml acts as an aspx page.
Either way, it sounds like you need to have one Window and one UserControl (or CustomControl, but if you're new to WPF you'll find a UserControl easier).
What you are talking about is UI composition, or view composition. This is usually achieved in WPF with a ContentControl which has a Content property which you can set to any type, in your case, an instance of your MainWindow type.
I would consider adopting the MVVM design pattern when building WPF applications, and using an MVVM framework such as Caliburn.Micro, which makes view composition very straightforward.
Are you talking about frames ? There's a very good article about using frames here :
http://www.paulstovell.com/wpf-navigation

How to create a "custom property" in WPF Style using pure WPF (no code-behind)?

Folks
I am working in UI design in a project where our team chose to decouple C# and XAML as much as possible.
I've been having trouble to create Styles for many common widgets (buttons, etc.) and some UserControls, specially because I don't-want/don't-know-how/am-not-supposed to use code-behind.
What I want to do is to be able to change properties of elements that are "deep within" the layout tree of my UserControls.
For example, suppose I have an UserControl that is a Border, which contains a StackPanel, which contains a colorful Ellipse and other things.
I want to be able to instantiate this user control and change only the color of the ellipse, like this:
<MyUserControl Background="Gray" EllipseColor="LightGreen" />
where "EllipseColor" would be some "custom" property defined in the UserControl.
I tried DependencyProperty within styles, but got no success, although I "feel" there must be a simple way to do this.
Any help (links, code snippets) would be much welcome.
Thanks for reading.
The "No Code Behind" rule in MVVM is for keeping the View and the ViewModel completely separate, and should not be used for view-specific code such as DependencyProperties. Its like saying "Build a house out of these square blocks, but I want a rounded roof and you can't create your own building blocks". The whole point of DependencyProperties is to create additional Properties for your Views that don't already exist.
The important bit is that the View doesn't directly reference the ViewModel, and vise versa.
In your case, I would either create a DependencyProperty in the Code Behind for your UserControl for EllipseColor, or use something like the Background property of the UserControl and bind my Ellipse fill color to that.

How does 2d canvas drawing based on an object model fit into MVVM, Caliburn & Silverlight (oh my)

I created a rough, non MVVM demo in Silverlight that drew various lines and other 2d objects on an Canvas, based on an object model.
I'm now porting the application over to MVVM (Caliburn Micro) and am now at the point where I have my objects in my ViewModel and need to draw them on the canvas in the View.
Is MVVM in this case the wrong tool for the job?
Where should I stick the 2d drawing code?
In code-behind of the View?
Let me know if you need any more info about my situation to help. Thanks!
In a situation like this, I would personally treat your Canvas as a custom, independent control.
Ideally, you'd want to make it a control (perhaps a UserControl) with a dependency property for the "objects". The user of this control would bind the objects to a collection inside their (parented control's) ViewModel, and just treat this as part of the View.
As such, it's 100% View - so the code can be implemented any way you choose. It kind of falls outside of MVVM, since it's entirely "view."

using MVVM and WPF for a realistic visualizations

I currently need to create a visual representation of a ferry system that displays the actual ferries their position on the sea and the state of their cargo. The ferries contain trucks and the trucks contain cars. I need to display the actual trucks and their xy postion on the deck. When the ferries are loaded the postions of the trucks are updated frequently so the look animated. Also I need to display the actual cars on the trucks. Trucks, cars and ferries have some states that need to be displayed too. So I have a hierarchical structure of data that I need to visualize in a rather realistic manner.
What would be a good way to implement this kind of stuff in WPF? Should I use MVVM with one TreeView control and create a HierarchicalDataTemplates for sea, ferry, truck and car and a ControlTemplate for the TreeView? Or should I better use UserControls and compose and update them in code instead of databinding to observable collections of the ViewModel. Do you have any experience with this? How would you do this? Could you sketch out class/control setup?
I'd recommend making a "lookless" control as opposed to making user controls. Generally I use user controls as glue/container for my lookless controls. An example of a lookless control is the Button class. It contains a default style and in Blend, you can modify the style all you like. It also supports the visual state manager so you can change how the presentation looks when states change. You can think of the codebehind of a lookless control as a mini ViewModel. Here it is ok to mix some presentation stuff and your domain classes.
If you follow this same design, you could create a Ferry lookless control. This control would have a set of it's own dependency properties (possibly listening to the OnChange of the DP).
Your Ferry control may have an ObservableCollection DP called "Trucks".
Then in your Themes\generic.xaml, create a default style for your Ferry control. Your default style may have an ItemsControl with an ItemsSource={TemplateBinding Trucks}. The ItemsControl panel template, could be your own custom panel for arranging the Trucks, or maybe you use a Canvas. For the ItemsControl items template, you would have something like this:
<DataTemplate>
<mynamespace:TruckControl/>
</DataTemplate>
You Truck control, would also be a lookless control with it's own default style, and it's data context will already be set, so you can directly do the {Binding Path=xyz}. Your Truck control could also set it's Canvas.Left/Top (if you chose to use a canvas in the pervious items control..or maybe it doesn't set its position at all if you made a custom panel for it) or a render transform as to put it at the correct X,Y. You could also use the items control in the truck's template to render out the cars in the same fashion you rendered out the trucks in the ferry control. Also its possible to create states for the VisualStateManager as to make it fully Blend supportable. So if a truck goes into a "problem state" you could easily style that state in blend to make it blink red, for instance.
I know it sounds like a lot to digest, but in the end having stylable controls all supporting an MVVM model will make your life 1000000x easier.
I'd suggest studying Microsoft's silverlight toolkit to get a good idea how to do lookless controls and such. Try looking at a simple control, like the DatePicker ( http://silverlight.codeplex.com/SourceControl/changeset/view/25992# ) One caveat is ignore DatePicker.xaml file (it's just a mirror of what gets put in generic.xaml and nothing bad would happen if you just deleted it).
The things you should pay close attention to are:
1.) The attributes on the class. These help Blend know how to deal with your control.
2.) The OnApplyTemplate override. This is where you can pull out specific elements from your template. These are known as "parts" and you will see the parts tab in Blend. The attributes in #1 can define what "parts" are in the template and what type they are expected to be.
3.) The DefaultStyleKey = typeof(...) in the constructor. This tells Silverlight what default template to use in the generic.xaml
4.) Look at Themes\generic.xaml. This is a special hardcoded file location that stores all your default templates. Search for the DatePicker style and you will get the idea :)
Good luck!
I just wanted to let you know, how I actually implemented it. It turned out that it was not necessary at all, to write custom controls or UserControls for this. All I did, was writing datatemplates for the car, ship, ferry, truck etc ViewModels. For example the datatemplate for the FerryViewModel contained an ItemsControl with a ItemsPanel of type Canvas (to be able to position the trucks) and an ItemTemplate that was a DataTemplate for TruckViewModel. A very simple and fast approach.
I'd suggest having one user control handle all the drawing. Otherwise you can get lost the the hierarchy of objects. Also it makes it easier if another item was added, say people in cars, trucks and ferries.
If your model is hierarchical then you can just pass in the top level into the control, and let the control sort itself out.
MVVM works well for existing controls, but existing WPF controls only work if there's a control that's close to what you need, and with a few tweaks would work. I can't think of a standard control in WPF that's close to what you need, so it's time to write a new control.
WPF works really really well with view models. If you can keep code behind away until specifically needed then you can separate ui from data so much more easily. It will allow your ui's to be some much more upgradeable if the data model doesn't change between different display.

Resources