Bulb Flash:- Some practical WPF MVVMLight tips!

One of our major projects recently used WPF 4.0 with MVVM pattern.We used the MVVM Light Toolkit for implementing the MVVM Pattern.

The MVVM Light Toolkit definitely has a lot to offer to make your life easier but the documentation is not exemplary!

Few things we learnt down the road as we came to a close on the project are

1. You are better off using the ViewModalLocator. We didn’t use it initially and realized that our ViewModels are not getting Disposed, multiple view models are getting created especially when using the “Commanding” feature!

2. When using Commands , if you are not using the ViewModalLocator, try not to set the IsDataSource property as it will change the DataContext of your screen to the new ViewModel and there will be inconsistency during commanding as previously set variables will not be available in the new VM. Or if you do need to set the IsDataSource property send all data needed by the command handler as arguments( because previously set data will not be available to the new VM)

3. You need a default empty constructor in all your ViewModels or your XAML screens commands won’t work(They instantiate the empty construtor)

4. You can pass event args parameters in commands using PassEventArgsToCommand="True" in your EventToCommand XAML

5. When using messaging use the method overload Send<TMessage>(TMessage message, object token).Using the token to register and send messages ensures it is delivered only to valid subscribers!

6. Every time you register for an event using the Messenger.Default.Register….ensure you Unregister also using the Messenger.Default.Unregister or else you might have memory leaks!!

Will try to write more elaborate posts detailing out these and more issues .Meanwhile drop a note at anshulee@cennest.com if you have any queries/ need more tips related to MVVM…

Until then!

Cennest!

Code for Keeps:- Store Retrieve image to/from Database

One of our early blogs was about extracting images from databases, websites and showing them on the screen.

The blog(see it here) dealt with

a) Retrieving images from the www

b) Retrieving images from the database when retrieved as a binary.

We realized there are some more scenarios to take care of here

c) Save Image to the database as a byte[]

public Byte[] BufferFromImage(BitmapImage imageSource)
     {
         MemoryStream memStream = new MemoryStream();
         JpegBitmapEncoder encoder = new JpegBitmapEncoder();
         encoder.Frames.Add(BitmapFrame.Create(imageSource));
         encoder.Save(memStream);
         return memStream.GetBuffer();
         
     }

d) Retrieve Image from byte[]( When you use Entity Framework with the Image database type you would get it back as a byte[])

public BitmapImage ConvertToImage(byte[] rawImageData)
  {
      MemoryStream stream = new MemoryStream(rawImageData);
      stream.Position = 0;
      BitmapImage bi = new BitmapImage();
      bi.BeginInit();
      bi.StreamSource = stream;
      bi.EndInit();
      return bi; 
  }
If you see any more scenarios do add comments and lets complete this list…
Cennest!

WPF/Silverlight Canvas Vs Single Cell Grid

I’ve often been asked the question of when should we use a Canvas and when a Single Celled Grid….

This is a snapshot of the an MSDN article . Our inputs are marked as [Cennest:]. The source can be read at  http://msdn.microsoft.com/en-us/magazine/ff646962.aspx

A single-cell Grid is just like a regular Grid except without any row or column definitions. If the Grid has only one cell, you can put multiple elements into the Grid cell and you don’t use any of the Grid’s attached properties to indicate rows or columns.

Initially, using a Canvas or a single-cell Grid seems very similar. Regardless which one you use for vector graphics, Line, Polyline, Polygon and Path elements will be positioned relative to the upper-left corner of the container based on their coordinate points.

The difference between the Canvas and the single-cell Grid is in how the container appears to the rest of the layout system. WPF and Silverlight incorporate a two-pass, top-down layout where every element interrogates the size of its children and is then responsible for arranging its children relative to itself. Within this layout system, the Canvas and the single-cell Grid are very different:

  • To its children, the Grid has the same dimensions as the dimensions of its own parent. These are usually finite dimensions, but the Canvas always appears to have infinite dimensions to its children.
  • The Grid reports the composite size of its children to its parent. 
However, the Canvas always has an apparent size of zero, regardless of the children it contains.

[Cennest:- This has an impact when you try to put the canvas in a Scrollviewer and think that the ScrollViewer will automatically show Scrollbars if the canvas starts exceeding the height and width. However you are zapped when the scroll bars just don’t show up…this is because the canvas notified its height and width as 0 to the scrollviewer which then happily did not show any scrollbars!!.

A workaround for this if you still want to use the scrollbar is to create a Custom Canvas control and override its MeasureOverride property. See this sample]

Suppose you have a bunch of Polygon elements that form some kind of cartoon-like vector graphics image. If you put all these Polygon elements in a single-cell Grid, the size of the Grid is based on the maximum horizontal and vertical coordinates of the polygons. The Grid can then be treated as a normal finite-sized element within the layout system because its size properly reflects the size of the composite image. (Actually, this works correctly only if the upper-left corner of the image is at the point (0, 0), and there are no negative coordinates.)

Put all those polygons in a Canvas, however, and the Canvas reports to the layout system that it has a size of zero. In general, when integrating a composite vector graphics image into your application, you almost certainly want the behavior of the single-cell Grid rather than the Canvas.

So is the Canvas entirely useless? Not at all. The trick is to use the peculiarities of the Canvas to your advantage. In a very real sense, the Canvas doesn’t participate in layout. Hence, you can use it whenever you need to transcend layout—to display graphics that break the bounds of the layout system and float outside it. By default the Canvas doesn’t clip its children, so even if it is very small, it can still host children outside its bounds. The Canvas is more of a reference point for displaying elements or graphics than it is a container

 

Hope this makes things a bit clearer!

Till next time!

Cennest!

Commanding within DataTemplates in MVVM!

A quick post about setting commands within DataTemplates when using the MVVM pattern!

When you are inside a DataTemplate the DataContext is changed to the  the current item, so to access the command you will need to use the “relative source”

Something like

 <Button Content="Delete" Width="Auto" 
Command="{Binding DataContext.RemoveCommand, 
RelativeSource={RelativeSource FindAncestor,
 AncestorType={x:Type ItemsControl}}}" 
CommandParameter="{Binding}">

Hope this real quick note helps save you some time!!

Until next time!

Cennest!

Multiple Level Master Detail Binding in WPF(XAML)

I’ve seen a couple of developers fumble with a LOT of Code when asked to implement a 2-3 level Master –detail form.

So we put together a bit of code to showcase how easily it can be done with virtually no code (alteast no code behind!!) in WPF

Consider the following problem statement:

Create a form which lists a set of families in a dropdown.(Level 1)

Depending on the family selected list the members of the family. List the sons and daughters in a dropdown(Level 2)

 

Depending on the son or daughter selected, list their friends in a dropdown(Level 3)

So your form should look like

To make things more interesting, all this information about the families comes from this XML Document. Family.xml

So how do we do this in WPF?.

The following 4 Step process should suffice!!

1.       Create an XML Data provider for the XML  Document and set the XPath to the Family Node

<XmlDataProvider x:Key=”dataSource” Source=”Family.xml” XPath=”/Families/Family”></XmlDataProvider> 

2.       Create the UI in 2 layers  i.e there should be 3 grids let’s call them the  FamilyGrid, Son Grid and Daughter Grid

So the structure is

<Grid x:Name=”FamilyGrid”>

<..Place the Level 1 controls here…i.e Family combobox, Father and Mother text blocks–>

                <Grid  x:Name=”SonGrid”>

<.. Place the Level 2 and Level 3 controls here..i.e the “Son” Combo box followed by the Son’s friends..>

                </Grid>

<Grid  x:Name=”DaughterGrid”>

<.. Place the Level 2 and Level 3 controls here..i.e the “Daughter” Combo box followed by the Daughter’s friends..>

</Grid>

                </Grid>

3.       Set the DataContexts of the Grids

a.       Family Grid: Set the DataContext to the Family Node

<Grid x: Name=”FamilyGrid” DataContext=”{Binding Source={StaticResource  dataSource}}”>

b.      Son Grid: Set the DataContext to the “Son” Node within the current Binding

<Grid x:Name=”SonGrid” DataContext=”{Binding XPath=Children/Sons/Son}”>

c.       Daughter’s Grid: Set the DataContext to the “Daughter” Node within the current Binding

<Grid x:Name=”DaughterGrid” DataContext=”{Binding XPath=Children/Daughters/Daughter}”>

4.       Bind the Comboboxes to the required fields and set the IsSynchronizedWithCurrentItem= true

 As Highlighted above the key points here are

·         The DataContexts of the Grids which are set to the level of information which we want to show. Whenever a control does an “ItemSource= {Binding…}, the compiler will travel up the UI Heirarchy to find the first not- null data context.So it helps to set the datacontext at the “container” level if mutiple controls need to refer to a common data source.

 

 Since we have a hierarchy of grids and the family grid refers to the /Families/Family Node, we just need to keep setting the DataContext={Binding , XPath= <the XPath to the Node following the family node>}. DataContext={ Binding…} will take you to the /Families/Family node and the XPath will take you to your desired node

 

·         The Property IsSynchronizedWithCurrentItem which is being set to true in the comboboxes is the key here.When you bind a set of data to a value select control and set IsSynchronizedWithCurrentItem = true, what you are saying is “From this point onwards consider this data item as the selected item and refer to it for data for the ensuing controls”

 

So when you select a family in the family combobox, and make it the “Current Selected” data item, the other comboboxes will refer to the data present in the selected family at the specified path , so Family/Son will search for the Son node within the selected Family

 So using a combination of DataContexts to refer to different levels of data and IsSynchronizedWithCurrentItem to set the currently selected data you can go upto n levels of master details binding,and you wudn’t have written a single line of code in you .cs fileJ

  You can find the solution for the above example here MasterDetailBinding.zip.

 Happy Detailing!

Cennest