Brendan Enrick

Daily Software Development

Wire up your ViewModels using a Service Locator

No MVVM solution is complete without having the DataContext bound to a ViewModel, but this wouldn’t be a fun development community if there were not some disagreement on the specifics of how to achieve certain goals. I will be recommending how I like to wire up ViewModels. There are other ways of doing this, but I will explain some of the reasons I use this method.

You can start by building a View that needs to have certain traits in its ViewModel and then create a well-tested ViewModel separately. This ViewModel should have all of the properties and data required by the View. Make sure you also have any commands or other functionality the View will require. It is then your job to make the connection between these two objects. The way I like doing this is by using a Service Locator to give my View the ViewModel it needs. This also gives me a good centralized location where I can make sure that my ViewModels are wired up the way I need them to be.

To create our service model we are going to need to create a class which has methods returning the ViewModels we are using in our Views. We should have one getter per ViewModel to be requested. I tend to use names matching the name of the ViewModel for the getters. The service locator will look a bit like this when you’re done. (You can also use an IoC container in the service locator, which is what I do in all of my production code. In that case you would just use the IoC container rather than instantiating the object as is done in this example.)

Code Listing 1 – The Service Locator:

public class ServiceLocator
{
public AwesomeViewModel AwesomeViewModel
{
get { return new AwesomeViewModel(); }
}
}

Notice that I can pass in any parameters needed for the ViewModel constructor so my ViewModel can depend on abstractions. The service locator can be more complicated than this if other work needs to be done to create these ViewModels. An example of such a situation is if I have shared dependencies or I am using an IoC container to create my objects.

Now that we have our code written to get us our ViewModel object we need to make this class available to all of our Views. This can be achieved by creating an instance of one of these as a static resource in our App.xaml file. Static resources defined here are easily accessible.

Code Listing 2 – Declaring the Service Locator as a Resource in App.xaml:

<Application x:Class="Awesome.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Awesome="clr-namespace:Awesome"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Awesome:ServiceLocator x:Key="SvcLoc" />
</Application.Resources>
</Application>

The key that we have assigned to this resource is how we will reference it when we access it later. In other parts of our code we will just specify in our bindings that we are accessing this static resource and calling its properties to get the data that we need. In fact this is exactly how we can get our ViewModel into our View. When we bind our DataContext we will tell it that our source is going to be this ServiceLocator instance and that we are binding our DataContext to a specified path, which is a property of the ServiceLocator.

The binding can be done either of these two ways. I don’t really prefer one or the other. These are effectively the same things, so it really comes down to preference.

Code Listing 3 – Binding the DataContext to the ServiceLocator:

<Window.DataContext>
<Binding Path="AwesomeViewModel"
Source="{StaticResource SvcLoc}"/>
</Window.DataContext>

Code Listing 4 – Binding the DataContext to the ServiceLocator Inline:

DataContext="{Binding AwesomeViewModel, Source={StaticResource SvcLoc}}"

Now we can access this DataContext throughout our View by just binding to different paths on it.

I like this approach because it keeps the binding in the XAML and not in the code. It is also nice because we are able to bind easily to properties and have these properties do dependency injection for our ViewModels. The centralization of all of this ViewModel creation is also very convenient. We are able to visit this one class to make adjustments for how the entire application handles its ViewModel initialization.

Making Text Clickable in Silverlight for Windows Phone 7

I’ve seen a lot of snippets of code online where people are trying to make text clickable in Windows Phone 7, and plenty of them are using the OnMouseLeftButtonDown event to do it. Well to put this lightly, this is not the best way of handling a click in the Windows Phone 7 environment. The reason is that we have to put the “left button” down in order to scroll. The “left button” is our finger, so if we try to scroll down and press our finger on the text we will be activating the event by mistake.

In order to resolve this we need to have the click event. Well, the click event is on the Button not on the TextBlock. In this example I will be using the MVVM Light toolkit and showing how I can wire up a Click event to a command on my ViewModel.

This example is a DataTemplate being used to display a list of colors each one as a bound item in a ListBox. I will be setting the text of each item to be the name of the color and I will be handling the click event by binding it to a command on my ViewModel the command will take in the color’s ID as a parameter. Notice that since I am in a DataTemplate I have to access the ViewModel for this view by accessing my view. While in the DataTemplate my current DataContext is the Color item I am binding in the list. Read more about accessing the ViewModel from a DataTemplate.

<DataTemplate x:Key="colorListTemplate">
<Grid>
<Button>
<Button.Template>
<ControlTemplate>
<TextBlock Text="{Binding Name}" FontSize="64" />
</ControlTemplate>
</Button.Template>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand
Command="{Binding DataContext.PickColor, ElementName=TheView}"
CommandParameter="{Binding Path=ID}"/>
</i:EventTrigger>
<i:Interaction.Triggers>
</Button>
</Grid>
</DataTemplate>

Notice that I set the ContentTemplate of the Button. This means that I am telling the control to not display how it would normally display and instead to display how I want it to. I do this so that I can display text as normal so that it looks like a have a regular list of items, and I am able to make this text handle the event when someone clicks on it. Keep in mind that a click and a scroll are two different operations in the Windows Phone, so non one is going to accidentally click on my item when they are trying to scroll. If I had done this with a MouseLeftButtonDown event as I’ve seen shown in the past it will cause the command to happen when someone is trying to scroll the list on the phone.
 
Remember that a button can look like anything in Silverlight. You have a ContentTemplate you can define for the button, so you have the power to always have a Click event. So if you need to make something clickable, make a button and put your control as the template for the button.

Accessing the ViewModel Inside a DataTemplate in Silverlight

I’ve been doing a lot of Windows Phone 7 Development, which means that I have also been doing a lot of Silveright development, so here is a tip for accessing your ViewModel when you’re in a DataTemplate.

In Silveright, DataTemplates are used when binding data to a control. For example if I want to list users I will define the DataTemplate, which will define the XAML that will be bound to for each of the users in the list. When I do this, the data context for the DataTemplate is my user and no longer the VM. I have a few options here, I can modify the user to have what I need, I can access some global class which has what I need or can access my ViewModel, or I could do what I prefer doing, which is just to name my View.

I give my name a view, and I can then create a binding which accesses an element by name instead of by using its current data context. To do this I can just name my View like this.

<Views:ViewBase
...
x:Name="TheView"
DataContext="{Binding BarViewModel, Source={StaticResource SL}}">

 

Then in my binding I can access it using the ElementName property like this. This example is wiring up a Click event using MVVM Light Toolkit’s EventToCommand.

<Custom:Interaction.Triggers>
<Custom:EventTrigger EventName="Click">
<Command:EventToCommand
Command="{Binding DataContext.DoSomething, ElementName=TheView}"
CommandParameter="{Binding}" />
</Custom:EventTrigger>
</Custom:Interaction.Triggers>

 
This allows me to access the commands on my ViewModel while I am using a DataTemplate. Without doing the “ElementName=TheView”, I would not easily be able to access the command from my ViewModel. I would only be able to access the commands from the User object.

Quick Silverlight Tip: Looking at the code

Silverlight is a great technology, and one thing that really makes it a treat to work with is the ease with which one can access the code inside the XAP file. Yes, this means that someone can look at your code,  SO DON’T PUT ANYTHING SECURE IN THERE! I took Jeff Blankenburg’s Click the Button contest.

So for a while I though Jeff had tricked me on that puzzle until I opened up the XAP file and looked at the source code. On the last page of the Silverlight you see this screen.

Level 12

So what’s the big deal? Well, the level before it was titled “Level 10”, so I figured Jeff was trying to pull a fast one and there was more to this seemingly innocent page. So I tried to find how to get beyond this level 12 to the real one. I eventually took the smart route, and I opened .NET Reflector and pointed it at the DLL file for the contest.

How did I do that you ask? Here are some quick steps for looking at the source code of a Silverlight application.

Step 1: Download the .xap file. View the source of the HTML page or look at the NET tab in FireBug to get the .xap file and download it.

Step 2: Rename the file to .zip and open it. Yes, a .xap is really a .zip neat huh?

Step 3: Unzip the file and find the dll you’re looking for. In my case it is called “ClickTheButton.dll”

Step 4: Open up .NET Reflector and open up that dll file.

NewDllInReflector

Step 5: After examining the dll you’ll be able to see all of the code. In this case I can see that Jeff actually has 13 levels he created for this application.

You now have a choice to make. You can ask Jeff Blankenburg what happened to the other puzzles or just go and take a look at the code and see which levels are missing.

Expression Blend Issue with Abstract Base Classes

Earlier, I wrote a post about using inheritance with Silverlight UserControls. The post shows really quickly how one can have their UserControl inherit from another class. One tip I’ll mention is that the base class can be abstract, but not if you plan on using Expression Blend. Generally if you have a class which shouldn’t ever be instantiate, you should make it abstract.

The issue is one that I discovered, much to my annoyance, the hard way. As it turns out Expression Blend is currently unable to give a preview of a UserControl that is inheriting from an abstract base class. When you open one of these in Blend you’ll get the Red Box of Death and in it is a message stating, “Exception: Cannot create an instance of “MyClass”.

Not exactly very helpful, but it does at least point you to the fact that there is something wrong with your base class. If you run into this make sure you know that you cannot use a base class. I believe that Blend requires a default constructor, and an abstract class has no constructors.

Solution 1

If you have control of the abstract class, you probably just want to make it a concrete class and hope no one is dumb enough to use it as a concrete class. This is actually a good place for a comment so you have a reminder of why the class is not abstract. Otherwise you might make it abstract again. The comment will also tip someone off that they can make it abstract if Blend ever supports this.

Solution 2

If you don’t have control of the abstract class, perhaps because it is in a class library you’re referencing, you will want to place a concrete class between your class and the abstract. This new class will be the one you specify in your XAML and is thus used by Expression Blend. This one adds an extra layer which really adds nothing and could cause confusion, so I would lean towards the other solution.

Silverlight UserControl Inheritance

One way in which we object-oriented developers try to achieve code reuse is by using inheritance. This allows us to have shared functionality in one place. Awesome we all know how to do this and it’s easy right? Try it in Silverlight for your UserControls. It is a little bit more challenging.

The problem we have is that we’re working with partial classes and these classes are trying to make things difficult for us. One of them is the noticeably declared one in the code behind file. The other one is created from the XAML file. The XAML file declares the base class it is inheriting from. In this instance it is the UserControl class.

Here are the steps required to use a different base class for your UserControls in Silverlight.

1. Create a class inheriting from UserControl and add your desired extras to the class.

2. Create a normal UserControl class and change the base class in the XAML file. You will need to declare an xml namespace for the namespace your base class is in, and use that namespace when declaring the base class.

<UI:MyBaseClass x:Class="MyProject.UI.UserControls.ConcreteImplementation"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:UI="clr-namespace:MyProject.UI" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
 
    </Grid>
</UI:MyBaseClass>

3. Change the inheritance in the code behind (.cs or .vb) file so that it is using the new base class. [Optional – Because of the way partials work you don’t need to declare this one as inheriting from the base class, but it does make things more obvious for someone using the code.]

Enjoy using your base class in Silverlight.

Working with the Default Layout of Silverlight RadCharts

The default layout for a RadChart works for most situations. It has a ChartArea, a ChartLegend, and a ChartTitle. These are easy to work with, and if you want you can break from the norm and create your own custom Silverlight Rad Chart layout. If you’re sticking with the default you almost certainly have some settings and properties to which you will want to make adjustments. In order to do that you might define these in the XAML.

<UserControl x:Class="MyApplication.UI.Charts.SuperSweetChart"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:telerikChart="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Charting" 
    xmlns:chart="clr-namespace:Telerik.Windows.Controls.Charting;assembly=Telerik.Windows.Controls.Charting" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <telerikChart:RadChart x:Name="Chart1" 
                               Loaded="Chart1_Loaded">
            <telerikChart:RadChart.DefaultView>
                <chart:ChartDefaultView>
                    <chart:ChartDefaultView.ChartArea>
                        <chart:ChartArea LegendName="CustomLegend" NoDataString="">
                            <chart:ChartArea.DataSeries>
                                <chart:DataSeries x:Name="DataSeries1" >
                                    <chart:DataSeries.Definition>
                                        <chart:PieSeriesDefinition 
                                            LabelOffset="0.6d" 
                                            ShowItemToolTips="True" 
                                            ItemToolTipFormat = "#XCAT" 
                                            DefaultLabelFormat = "#%{p0}" />
                                    </chart:DataSeries.Definition>
                                    <chart:DataPoint YValue="35" />
                                    <chart:DataPoint YValue="15" />
                                    <chart:DataPoint YValue="55" />
                                </chart:DataSeries>
                            </chart:ChartArea.DataSeries>
                        </chart:ChartArea>
                    </chart:ChartDefaultView.ChartArea>
                    
                    <chart:ChartDefaultView.ChartLegend>
                        <chart:ChartLegend x:Name="CustomLegend" 
                                           UseAutoGeneratedItems="True" />
                    </chart:ChartDefaultView.ChartLegend>
                    
                    <chart:ChartDefaultView.ChartTitle>
                        <chart:ChartTitle>
                            <TextBlock Text="Traffic Sources"/>
                        </chart:ChartTitle>
                    </chart:ChartDefaultView.ChartTitle>
                    
                </chart:ChartDefaultView>
            </telerikChart:RadChart.DefaultView>
        </telerikChart:RadChart>
    </Grid>

Notice the three parts are the ChartArea, the ChartLegend, and the ChartTitle. Use the properties of these to make your adjustments. If you don’t want to change these in the XAML then don’t include them. If you’re going to work from the code behind it doesn’t hurt to have these here, but it can be useful.

You can access these in the code behind by either declaring their x:Name property or by referencing them from the RadChart’s x:Name like this. Chart1.DefaultView.ChartArea.

Plus keeping things in here keeps designers happy, and we design-challenged people really appreciate happy designers willing to assist us.

How to Add a ToolTip to a RadGridView

So I was using a RadGridView to display some data and I wanted to add a tooltip with more information. Shouldn’t be too difficult. I of course checked through intellisense to see if there were any obviously named properties for setting a tooltip.

I checked on the RadGridView tag for the properties and I also checked the GridViewDataColumn for it. Didn’t come up with anything so I Binged until I found a potential solution. It didn’t really make sense to me and the solution had me doing a lot of what seemed like extra stuff. It was adjusting the tooltip using the styles for the cell. So, then it hit me that I was thinking about this the wrong way. Since I just wanted text and a tooltip why don’t I just add that in?

So I took control of things and I just used a template for the column instead. Here is the quick and easy way to add a tooltip into a RadGridView.

<grid:RadGridView x:Name="RadGridView1" AutoGenerateColumns="False">            
    <grid:RadGridView.Columns>
        <grid:GridViewColumn Header="Person">
            <grid:GridViewColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding NickName}" 
                       ToolTipService.ToolTip="{Binding FullName}" 
                       VerticalAlignment="Center" />
                </DataTemplate>
            </grid:GridViewColumn.CellTemplate>
        </grid:GridViewColumn>
        <grid:GridViewDataColumn Header="Place" 
          DataMemberBinding="{Binding Place}" />
        <grid:GridViewDataColumn Header="Thing" 
          DataMemberBinding="{Binding Thing}" />
    </grid:RadGridView.Columns>
</grid:RadGridView>

 

And there you have a tooltip on the text of a cell in a RadGridView. You can obviously add different content items into the DataTemplate so that you can support more advanced templates. Just throw the tooltip on the root element inside the DataTemplate and you’ll be set.

String Formatting BoundFields in Silverlight

Hi my name is Brendan E. While working with a Bindable Silverlight control I ran into a little bit of trouble because I have a dependence commonly found among Visual Studio developers. I am addicted to intellisense. When a property isn’t in intellisense I make the failing assumption that it does not exist.

So even though I have posted specifically about how we developers should be smart enough to know that we can’t always trust intellisense, I still make the mistake of trusting it.

I am binding to a control and it slipped my mind to use the DataFormatString property, because it didn’t show up in intellisense for me. So of course I look around for what else I might use. I bing a few times about what I am trying to do. When I find the answer I feel like an idiot once again. This must be how all addicts feel. I just need my intellisense.

So I was trying to format my bound field as a percentage. To do that I just needed to add the following code.

DataFormatString="{}{0:P}" 

 

Hooray! I’ve got working code now. So I repeat again. Don’t trust intellisense. Just because it says it isn’t there doesn't mean it isn’t there.

Silverlight 3 Out of the Browser

Running a Silverlight application out of the browser is very powerful. This lets users install a Silverlight application locally with a quick right click on the app in the browser. In earlier versions of Silverlight this was still pretty easy, but now you don’t even have to open up an xml file to do it.

So here is my simple Silverlight application running in the browser.

InitialMessageInBrowser

After I click that Button the app makes a web service call to change the text, which isn’t that important to this demo. I figured it was better than having it do nothing.

AfterClickInBrowser

Hooray we have a working Silverlight application. Now in order to get it running out of the browser we have only a couple of steps to take. None of which involve going into the AppManifest.xml file like was required in previous versions. Now we simply right-click on the Silverlight project in Visual Studio and select Properties.

SilverlightProperties

After enabling the ability to run out of the browser you just need to change the Out-of-Browser Settings. Doing this will create a file in the properties folder of the Silverlight application which has XML defining all of the settings configured here. This GUI just makes it easy to set up.

OutOfBrowserSettings

I like how simple this is. Not overloaded with tons of options. Just easy to use.

Now when we run the app we can right-click on the application and we are able to install the app locally.

RightClickInstall

When we click on the Install option we get a nice installation wizard with no complexity.

InstallApp

All the user has to do is decide where to put a shortcut. Once they click this the app will be installed and running. The application will look a little bit like this.

InitialMessageOutOfBrowser

And when we click out button we get another web service call and this time we pass a different parameter to the service call and get a different message. Take a look.

AfterClickOutOfBrowser

So how easy was that? Say that the user wants to uninstall the application now. That is also easy. All they have to do is right-click on it and select the option to remove the app and it is gone. They can do this in or out of browser.

RemoveApp

So now you know how easy it is to set up an out of browser Silverlight application.