What’s new in Expression Blend for visual studio?
Intro
With the release of Windows 8 Customer Preview came the release Visual Studio 11 Beta. This beta release van with a new version of Expression Blend. To get it, just download the Visual Studio 11 Beta and install the Ultimate, Premium of Professional version. If you don’t have installed or don’t want to install Windows 8, you can install Visual Studio on Windows 7 now. It runs side by side with any previous installation of that.
There is one downside of running the Beta on Windows 7: you can’t develop WinRT applications. The file->new Project windows is even completely empty in this release. But that doesn’t mean you can’t work on Silverlight projects. You’ll just have to create them with Visual Studio for now, and than open them in Blend.
Unfortunately Windows Phone or WPF development seems not to be possible with this release, but please correct me if I’m wrong…
I’ve made a small list of changes when using Expression Blend for Visual Studio on Windows 7 when working on Silverlight projects.
Changes
The first thing to notice when Blend is started are the changed icons, they’re a bit smaller too. They’re styled in the same way as the icons in Visual Studio 11.
The toolbar has only a few minor changes. The basics are the same, but there are a few controls that are removed or added to it.
The various panes look pretty much the same as in previous version of blend. There are a few rounded ‘corners’ removed. The changes are very minor, but somehow the UI feels different.
A new feature is the possibility to change the sorting of the properties in ‘Properties’ pane. You can now arrange them by ‘Category’, ‘Name’ or ‘Source’. If you’re used to “designing” ;) XAML applications in Visual Studio 2010 this feature might be familiar. Category is what was the way Expression Blend used to sort the properties and still is the default. Arranging by Name does what it says, sorting by name. The last option is also very useful. Arranging by Source groups properties that have their value set together, which makes it very easy to find these. ![]()
One other small change is that ‘View XAML’ is renamed to ‘View Code’ in various context menus.
A similar feature is added to the ‘advanced-options-peg’, the little square behind the properties. You can now jump directly to the XAML to where the value is defined.
At some point I noticed one of the pegs to be blue, instead of white, green or yellow. The tooltip revealed it was set with an ‘ambient’ value. You can’t do anything with it at this point, but I assume it indicates the value is set by some other resource. In this case by the Style.
Editing of grids is changed a little to. It has become a lot easier to add, move and changes columns and row of a grid. Just hover and click in the designer to change the settings of the column or row. When moving rows or columns around, the contents move along…
Wrap up
Well, that’s about that at this point. There aren’t that many changes in the Silverlight scenario, but at least there’s some improvement. A couple of features came over from visuals studio, a couple are entirely new. I guess most of the new features are focused at Metro and running Expression Blend on Windows 8. Let’s hope improvement will continue and more features will become available with future releases…
Customizing Silverlight properties for Visual Designers
When building custom or user controls you probably end up with a large amount of properties on that control. When using the control in a visual designer like Blend or the Visual Studio designer these properties just show up. Adding a bit of structure in this can be done very easily by adding a couple of attributes to the properties.
The attributes to let the visual design know what to do can be found in the System.ComponentModel namespace. There’s a WPF version of this namespace also.
For the sake of simplicity I’ve created a UserControl and set the background color of the LayoutRoot grid to red to be able to spot it in the designer. I’ll add properties with attributes to that control and show you what happens in Visual Studio and Expression Blend.
Categorizing
By default all properties on UserControls are grouped together in the Miscellaneous section at the bottom of the properties Panels in Blend and or in the Others section in Visual Studio.
The first property I’ve named CategoryDemo1 and it’s of type string. It doesn’t have an attribute to go with it.
When adding the control to the MainPage the properties look like this:
To add a property to an existing category add a Category Attribute to the property and give it the name of the category you would like to have you property added too.
For example, this adds the property Category2 to the Layout category:
[Category("Layout")]
public string CategoryDemo2 { get; set; }
Your property might need a category of its own. This can be done just as easily as adding to an existing category. Just use a category name that doesn’t exist yet.
[Category("CustomCategory")]
public string CategoryDemo3 { get; set; }
You might have noticed that some categories are named differently in Visual Studio and Blend, there might even be some localization used. Take for example the Common category in Visual Studio. It is called Common Properties in Expression Blend. The CategoryAttribute class contains a couple of static properties that return the CategoryAttribute for a default category. Unfortunately the static properties can’t be used when placing an attribute on a property. In part 2 of this tutorial I’ll talk about how this can be done. In the meantime you’ll have to guess a little.
The common properties category can be used like this:
[Category("Common Properties")]
public string CategoryDemo4 { get; set; }
Description
Often you might want to add a description to a property, like you would do in code. You can use the DescriptionAtrribute for this purpose.
[Category("CustomCategory")]
[Description("This is a description")]
public string DescriptionExample { get; set; }
Default Value
Often you would like to set a default value for a property. Numeric or a string or whatever. When the value is reset in the designer the property should show the default value. You can accomplish this by adding a DefaultValueAttribute to the property.
[Category("CustomCategory")]
[DefaultValue("Hello")]
public string DefaultExample { get; set; }
Hide properties
There are situations where you have properties that you do not want to expose through the UI. In cases like this you can set the BrowsableAttribute to false.
[Browsable(false)]
public string NotBrowsable { get; set; }
(intentionally left blank: can’t make a screenshot of something that’s not there)
AlternateContentProperty
The last thing I would like to show is the AlternateContentPropertyAttribute. I’m still not sure what it is used for, but it lets Expression Blend know to display the property in a different way. The property is shown in the Objects and Timeline panel. The charting controls in the Silverlight Toolkit do this too. Visual Studio doesn’t seem to do anything with this property.
[Category("CustomCategory")]
[AlternateContentProperty]
public string AlternateExample { get; set; }
Wrap up
As you can see there are various possibilities on how to display your properties in the design surfaces. But there is more. Have you ever notices the .design.dll files that came with Silverlight and the Silverlight Toolkit? I’ll continue this article in part 2 about these.
To be the first to know when it’s done, please subscribe to the RSS feed or follow me on twitter (@sorskoot).
Dependency Injection, MVVM, Ninject and Silverlight
Intro
The MVVM patterns is pretty popular these days. In Silverlight and WPF it is used a lot. Dependency Injection is also used very often. In this tutorials I would like to show you how to use Dependency Injection when building a Silverlight application using the MVVM pattern.
There are numerous Dependency Injection Frameworks. For this tutorial I’ve chosen Ninject. The main idea on how to implement DI in your application is pretty much the same for all frameworks. In this tutorial I hope I can give you a small introduction in using Ninject in you projects.
Ninject is an open source project which can be found at www.ninject.org. Ninject is also available through the NuGet tool in Visual Studio. Have look at my NuGet tutorial on how to get it through that.
Demo project
The demo project is a very simple game. The objective of the game is to guess a number. There will be a web service that can be requested to provide a random number. The game consists of three screens or Views. The first, StartView, asks the player for the maximum number. The second screen, GameView, ask the player to guess a number between 0 and the maximum number given on the first screen. The last screen, ResultView, shows whether the guess number equals the randomly chosen number and provides the user with two options, try again or restart. These views are displayed inside a fourth view, ShellView, that handles the navigation.
Each view contains one or more commands and one or more properties to handle interaction with the user. The views contain only the most basic controls to interact. On the StartView there’s a textbox to set the maximum number to guess for and a button to start playing. The GameView contains a textbox to get the guess from the user and a button that triggers navigation to the ResultView. The ResultView contains a styled checkbox to show if the guess was correct and two buttons. One to navigate to the GameView, to try guessing again, and one to navigate to the StartView, to start the game all over.
The generation of a random number takes place on the server. A proxy class is placed between the calls to the service and the caller of the methods. This implementation of the custom IProxyService interface will be replaced when unit testing to be able to use a dummy implementation.
The navigation works by calling a method on shared class between the viewmodels.The INavigator interface contains the method. It also contains an event the ShellViewModel is listening to. Calling the method would fire the event and causes the ShellViewModel to update the visible view.
Setup the IOC
Ninject uses a Kernel to setup the Inversion of Control, or IOC, container. The IOC container is filled with classes and interfaces that go together. We the program asks the Kernel for a specific type, this will be returned by the container. By default you can instantiate the StandardKernel class. The constructor of the StandardKernel class takes a NinjectModule as a parameter.
To separate the construction of the Module and the construction of the Kernel, the NumberGameModule class is created. The class inherits from the NinjectModule class. It has to implement the abstract Load method.
private IKernel Kernel;
...
Kernel =
new StandardKernel(new NumberGameModule());
The binding of classes together for the IOC container happens in the Load method of the NumberGameModule class. The method is called automatically when the Kernel is created.
public class NumberGameModule : NinjectModule
{
public override void Load()
{
//todo: Inititialize the IOC.
}
}
Often an interface is bound to a class that implements that interface. This way alternative uses of that interface can be used if needed, when Unit Testing for example. The binding uses a fluent syntax and looks like this:
this.Bind<IServiceProxy>().To<ServiceProxy>();
This literally Binds the IServiceProxy interface To the ServiceProxy class. This means that every time you need a ServiceProxy you call the Get method on the kernel, like this:
kernel.Get<IServiceProxy>();
In this case the kernel instantiates a new ServiceProxy for you. If, in case of testing for example, you bind a TestServiceProxy to the IServiceProxy interface. The TestServiceProxy will be returned, without changing the call to the Get method. In the next section you will see the true power of this.
Sometimes you don’t want to use an interface for a class. You just want to have an instance when asking for it. In situations like this you can bind a class to itself. The syntax for this is straight forward again:
this.Bind<GameViewModel>().ToSelf();
This sounds pretty useless, but to get all the nice features of dependency injection you’ll have to let the framework instantiate your classes, and never use the new keyword.
Lifetime
One of these features is using singletons. There a lot’s of reasons not to use the singleton pattern, they are hell to unit test for example. When using dependency injection you can have the framework manage the singletons. Which means that every time you ask the kernel to give you a specific type, you always get the same instance. But, in case of unit testing you can have it return a new instance every time. Without any changes to the code under test. For example, say you want to bind the INavigator interface to the Navigator class using a Singleton scope:
this.Bind<INavigator>().To<Navigator>()
.InSingletonScope();
Without specifying a scope the InTransientScope() variation is used. If you need it, you can also have Ninject instantiate a new instance once every thread by using the InThreadScope() method.
Context
Often you find the need to use different implementations of classes in different contexts. For example, when using Expression Blend to create your views. You don’t want to call web services and do complex calculations, but only a simple implementation to work with. You can have Ninject create different instances based on the context. In this example the normal implementation is created in Singleton scope. When using this class in a designer, like Blend, a new instance is created on every call. A delegate method is used. The method should return a boolean. In the example below a lambda is used to shorten the syntax.
bool designContext =
DesignerProperties.GetIsInDesignMode(
App.Current.RootVisual);
this.Bind<IGame>()
.To<Game>()
.When(x => !designContext)
.InSingletonScope();
this.Bind<IGame>()
.To<AlternativeGame>()
.When(x => designContext);
Constructor Injection
When having Ninject instantiate your classes Ninject automatically resolves the parameters of the constructor. This means that if your constructor takes two interfaces and Ninject knows how to resolve these, the implementation of the interfaces is injected into the constructor. For example, the constructor of the ResultViewModel takes two parameters. The IGame interface and the INavigator interface. Both these interfaces are known to Ninject and therefore can be resolved when a ResultViewModel is created.
public ResultViewModel(IGame game,
INavigator navigator)
{
...
}
Without using Dependency Injection you probably would new a game and a navigator inside the constructor, and thus create a dependency on these classes. When using injection you only have a dependency on an interface, and can use different implementations when needed. Which makes testing a lot easier.
There are occasions however where you want to have control over which constructor is used for injection. Ninject looks for the constructor that takes the most known parameters and tries to use that when resolving the class. If it can’t find any it will use the default parameterless constructor. You can mark a constructor with the Inject attribute to force Ninject to use that one when resolving. Marking multiple constructors with the attribute will result in an exception.
Binding the VM to the V
The last step would be to glue it all together. The kernel must be build and filled somewhere, and the viewmodels must be bound to the Views somehow. To do all this one could use the View Model Locator pattern. The ViewModelLocator class contains properties that represent the viewmodels used. The class has a static constructor so it can be constructed in Xaml. By doing this the ViewModelLocator can be defined a resource and be used throughout the application. The implementation of the constructor is described earlier. Only a null-check is added. The ViewModelLocator looks like this:
public class ViewModelLocator
{
public ShellViewModel ShellViewModel
{
get {
return Kernel.Get<ShellViewModel>();
}
}
// other ViewModels are defined
// the same way.
private static readonly IKernel Kernel;
static ViewModelLocator()
{
if (Kernel == null)
{
Kernel = new StandardKernel(
new NumberGameModule());
}
}
}
To get the ViewModelLocator known in Xaml you’ll have to define it as a resource. The best place to do this is directly in your App.xaml. In the Resources section define a new resource with and use a key like “ViewModelLocator”, like this:
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Common="clr-namespace:NumberGame.Common"
x:Class="NumberGame.App">
<Application.Resources>
<Common:ViewModelLocator
x:Key="ViewModelLocator"/>
</Application.Resources>
</Application>
When the application is started the resource is created, and the static constructor is executed. You can use the ViewModelLocator as a StaticResource now.
To get the right viewmodel in a view the DataContext of that particular view has to be bound to a property of the ViewModelLocator resource. In case of the ShellView you would like use the ShellViewModel property of the ViewModelLocator. Add a line like below to the definition of your view in xaml:
DataContext="{Binding ShellViewModel,
Source={StaticResource ViewModelLocator}}"
All this is saying that you would like to set the path of the binding to the ShellViewModel property of the ViewModelLocator StaticResource.
Wrap up
There are a lot of situations where you might want to have Ninject do more than what is explained in this tutorial. Ninject can do a lot more, which is left out for the sake of simplicity. Sometimes you’ll need specific custom factory methods to create your objects or you might have separated your classes into a different assembly. Ninject can be used in situations like this too. If something isn’t supported right out of the box, Ninject is extensible and open source.
You can find the demo project that goes with this tutorial here.
If you have any questions, suggestion or just want to leave a comment you can use the area below, feel free to send me an email or contact me through twitter. To be the first to know when there’s a new tutorial online you can also subscribe to the RSS feed.
NuGet
If you often use open source libraries you probably have a large library with various tools, like I do. NuGet is an extension for visual studio that enables you to install, uninstall and upgrade open source packages into your application very easily. Say for example you want to use MvvmLight or Ninject in your project, with NuGet it’s nothing more that tell it to add the package to your project.
NuGet
NuGet (formerly known as NuPack) is a free, open source developer focused package management system for the .NET platform.
You can download the .vsix extension at http://nuget.codeplex.com.
After installing it you can start adding packages to your project in two ways. The first is by right clicking in the Solution Explorer and selecting the Add Library Package Reference… option.
This will present you with a dialog where you can find and install a package. To see the package available, select the Online option from the list on the left. You can use the text box on the top right to filter the list to get to the package you want to use. Hit the install button to add the package to your project.
To remove a package, go to the same window. The installed packages are shown on the first page. Hit the uninstall button next to the package you would like to remove from your project.
Another way of managing packages is thru a powershell like interface, using the keyboard. You can get to the console window by going to the View menu and selecting Other Windows –> Package Manager Console.
The following window will show up (the coloration might be different based on your personal color scheme settings in Visual Studio).
You can manage your packages by using a few simple commands.
-
- List-Package
- Install-Package
- Update-Package
- Uninstall-Package
These do exactly what can be expected. The Install, Update and Uninstall need at least the name of the package as parameter. You can type help before each of these commands to get information on the other parameters.
One last thing. You can use the Tab key to auto-complete commands and even parameters.
Using Visual States in custom controls in Silverlight
Intro
Visual States are an easy way to change the looks of your controls based on certain states. This state can be something like a mouse hover, some invalid state or any state you need in a control.
For this tutorial I chose a traffic light control that can be one of four states. Green, Orange, Red and Inconclusive (blinking orange). In the end I show you how to use behaviors on buttons to set the state of the traffic light. This makes the use of visual states perfectly suitable for use in MVVM projects.
Part 1 – Setting up the project
Start by creating a new Silverlight project in Visual Studio 2010 and add a new Item to the project by right clicking on the project in the Solution window and click Add –> New Item… or hit Ctrl+Shift+A.
Select the Silverlight Templated Control item template from the list of Silverlight templates
Add a folder named Themes to the Silverlight project. Add a ResourceDictionary to the project by using the Add->New Item… on the project folder and name this dictionary Generic.xaml. Add the following style to the dictionary:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VsmDemo="clr-namespace:VsmDemo">
<Style TargetType="VsmDemo:TrafficLight">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate/>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</ResourceDictionary>
Add a reference to the dictionary in App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Build the solution to see I there aren’t any mistakes so far.
Part 2 – Drawing in Blend
Start Expression Blend and load the solution.
The template is still empty. To start editing the style for the TrafficLight control, go to the Resource pane, look for the generic.xaml entry, open it and click on the button on the right of the style entry.
To edit the template in the style, right click the style in the Objects and Timeline pane and select Edit Template –> Edit Current.
Now draw a traffic light like this.
If you don’t like/want/know how to draw the light, just copy-past the xaml below into the xaml editor. It’s basically just a border with a grid containing three ellipses.
<ControlTemplate>
<Border d:DesignHeight="200.00" BorderBrush="#FFCACACA"
BorderThickness="3"
Background="#FF333333" CornerRadius="40"
d:DesignWidth="110">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Ellipse x:Name="GreenLight"
Grid.Column="1" Grid.Row="1"
Fill="Black" Margin="2"
Stretch="Uniform"/>
<Ellipse x:Name="OrangeLight"
Grid.Column="1" Grid.Row="2"
Fill="Black" Margin="2"
Stretch="Uniform"/>
<Ellipse x:Name="RedLight"
Grid.Column="1" Grid.Row="3"
Fill="Black" Margin="2"
Stretch="Uniform"/>
</Grid>
</Border>
</ControlTemplate>
Instantly the traffic light should show up in the designer.
Time to save your work again. Switch back to Visual Studio, and reload the files if you’re asked to.
Part 3 – Code… Finally
The selection of the different states will be based on an enum. Add a new enum to the Silverlight project.
public enum TrafficLightStates
{
Inconclusive = 0,
Green = 1,
Orange = 2,
Red = 3
}
The state of the traffic light will be stored in the control in a dependency property. The property will be set to TrafficLightStates.Green by default. A method must be called when the property changes to notify the state manager to change the state of the traffic light.
public TrafficLightStates State
{
get { return (TrafficLightStates)GetValue(StateProperty); }
set { SetValue(StateProperty, value); }
}
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register(
"State",
typeof(TrafficLightStates),
typeof(TrafficLight),
new PropertyMetadata(TrafficLightStates.Green,
OnLightStateChanged)
);
To get the code to build, add a basic implementation of the OnLightStateChanged method. The OnLightStateChanged method calls the non-static SetState method. This way there will be only one method in which the visual state will be changed. The SetState method is empty for now.
private static void OnLightStateChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
((TrafficLight)d).SetState();
}
private void SetState(){}
To make the four different visual states known to the application you’ll have to use the TemplateVisualState attribute. This attribute takes the name of the state and the name of the group the visual state belongs to. Add an instance of the TemplateVisualState attribute for each of the four states to the TrafficLight class.
[TemplateVisualState(Name = "Green",
GroupName = "TrafficLightStates")]
[TemplateVisualState(Name = "Orange",
GroupName = "TrafficLightStates")]
[TemplateVisualState(Name = "Red",
GroupName = "TrafficLightStates")]
[TemplateVisualState(Name = "Inconclusive",
GroupName = "TrafficLightStates")]
Now the states are named it is time to set the visual states based on the state of the traffic light. This is done by a simple switch block in the SetState method.
Changing the visual state of a control is done though a static method on the VisualStateManager class. Calling the GotoState method with the name will change the current visual state to a new one. Any transitions will be played automatically, if the useTransitions parameter is set to true. The GotoState method also needs a control of which the visual state needs to be sit. For this example we can just pass this to the method.
private void SetState()
{
switch (State)
{
case TrafficLightStates.Green:
VisualStateManager.GoToState(this, "Green", true);
break;
case TrafficLightStates.Orange:
VisualStateManager.GoToState(this, "Orange", true);
break;
case TrafficLightStates.Red:
VisualStateManager.GoToState(this, "Red", true);
break;
default:
VisualStateManager.GoToState(this, "Inconclusive", true);
break;
}
}
The last thing that has to be done in code is setting the initial state by calling the SetState method once. You can override the OnApplyTemplate method for that.
public override void OnApplyTemplate()
{
SetState();
base.OnApplyTemplate();
}
Build to see if there are any mistakes made in the code… After that, switch back to Expression Blend.
Part 4 – Visual States
The last part of this tutorial will take place in Expression Blend. Every state of the traffic light has to have a corresponding visual state. The green light must be green, etc.
Go to the template of the TrafficLight control as shown before and open the States pane. Click on the Add State Group button on the right side of the pane.
Rename the VisualStateGroup group to TrafficLightStates.
Add four states to the group by clicking the Add state button right of the TrafficLightStates group header four times.
Rename the states to Green, Orange, Red and Inconclusive.
With the Green visual state and the GreenLight Ellipse selected, change the fill of the ellipse to green, like #FF2AFF00. Notice the red border around the drawing area indicating changes to the properties will be recorded. A small red light with a caption is shown at the top of the drawing area letting you know which state is recorded too, in this case “Green state recording is on”
This process needs to be repeated for the orange and red ellipses too. In the example I’ve used #FFFFAA00 for the orange ellipse and #FFFF0000 for the red one.
The last state, Inconclusive, needs an animation so the orange light blinks. Select the Inconclusive visual state on the States pane. Show the animation timeline by clicking on the Show Timeline button on the Objects and Timeline pane.
Move the time slider to 0,5 seconds. Change the color to Orange (#FFFFAA00). Move the time slider to 1 second and change the color to black.
Click on the first key frame and set its easing function to cubic out.
Repeat the same for the second key frame. Set its easing function to cubic out also.
Select the storyboard by clicking on Inconclusive in the Objects and Timeline pane.
In the properties pane, set the Repeat Behavior of the storyboard to Forever.
That’s it for the visual states. Try compiling the application.
Part 5 – Testing the control
Open MainPage.xaml in Expression Blend.
Add the TrafficLight control to the LayoutRoot grid and give it a width of 110 and a height of 200.
To navigate to the four different states of the traffic light, add four buttons to the LayoutRoot grid and set their content to Green, Orange, Red and Inconclusive. Like this:
To change to State property of the traffic light you can use a ChangePropertyAction. You can find this in the Behaviors group on the Assets pane.
Drag-‘n-drop this action on the first button.
Select the Action in the Objects and Timeline pane. To set the TargetObject of action to the traffic light just click on the Artboard element picker and than on the traffic light.
Select State from the PropertyName combobox.
Select Green from the Value combobox.
Repeat the same process for the other three buttons. You can clone the behavior from element to element by selecting the behavior and drag-‘n-drop it to another element while holding down the Ctrl key.
Done!
Hit F5 to admire your work
You can download the source of the project here.
If you run into any issues or if you have comments or questions, please let me know. To be the first to know if there’s a new post on my blog, please subscribe to the RSS feed or follow me (@sorskoot) on twitter.
PivotViewer and MVVM
PivotViewer series
- Building your first PivotViewer application
- Runtime PivotViewer collection creation
- PivotViewer – Working with Facets
- Handling PivotViewer events
- PivotViewer – Custom actions
- PivotViewer and MVVM
Intro
The MVVM patterns is a commonly used pattern in Silverlight. Because of databinding MVVM suits perfectly for WPF and Silverlight. But use it only if appropriate. Often the pattern is used when it isn’t necessary. The usage of any pattern should be a helping tool, not an enforced law. Having that of my chest, lets look at the Silverlight PivotViewer control in combination with the MVVM pattern.
To make a long story short, the PivotViewer control isn’t suitable for use in MVVM out of the box. But there are a few ways you can make it work.
Wrapping the PivotViewer in a UserControl
The most simple way to get the control to work in an MVVM application is to place the control in a UserControl. You can use this control in your View and bind to properties you add to the UserControl. You’ll have to add dependency properties to the UserControl for each property you want to data bind to. The downside of wrapping the PivotViewer control in a UserControl is that you will have to add code to the CodeBehind of the UserControl.
For example a URL where the .CXML file is located. If this value changed you would like to load the collection. In the current version of the PivotViewer the only way to do this is to call the LoadCollection method on the PivotViewer control. By adding a dependency property to the UserControl you can bind a property of the ViewModel to this and have it load a collection on changes.
This dependency property with its “OnChange” method might look something like this:
public string UrlSource{
get { return (string)GetValue(UrlSourceProperty); }
set { SetValue(UrlSourceProperty, value); }
}
public static readonly DependencyProperty UrlSourceProperty =
DependencyProperty.Register("UrlSource",
typeof(string),
typeof(PivotViewerUserControl),
new PropertyMetadata(string.Empty,
OnUrlSourceChanged));
private static void OnUrlSourceChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (!DesignerProperties.GetIsInDesignMode(d))
{
var userControl = (PivotViewerUserControl) d;
userControl.Pivot.LoadCollection((string) e.NewValue,
string.Empty);
}
}
A logical next step would be to add a dependency property for the ViewerState parameter of the LoadCollection method and call it only when both are set or if the UserControl is Loaded.
To get notified when the selected item changed you can use an ICommand. Add a dependency property of type ICommand to the UserControl to be able to bind an implementation of the ICommand from the ViewModel to it. The property changed event on the PivotViewer control is handled. When the “CurrentItemId” property changes, thus the selected item changes, the event is executed. As a small extra feature the item is looked up on the PivotViewer and the whole PivotItem is passed as a parameter to the execute method.
public PivotViewerUserControl()
{
InitializeComponent();
Pivot.PropertyChanged += Pivot_PropertyChanged;
}
public ICommand SelectedItemChangedCommand
{
get { return (ICommand)GetValue(SelectedItemChangedCommandProperty); }
set { SetValue(SelectedItemChangedCommandProperty, value); }
}
public static readonly DependencyProperty SelectedItemChangedCommandProperty =
DependencyProperty.Register("SelectedItemChangedCommand",
typeof(ICommand),
typeof(PivotViewerUserControl),
new PropertyMetadata(null));
private void Pivot_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "CurrentItemId")
{
if (this.Pivot.CurrentItemId == null)
{
// deselection
this.SelectedItemChangedCommand.Execute(null);
}
else
{
// selection
PivotItem item = Pivot.GetItem(Pivot.CurrentItemId);
this.SelectedItemChangedCommand.Execute(item);
}
}
}
Extending the PivotViewer control itself
Another way to get to PivotViewer to work in an MVVM application is to extend the PivotViewer itself. The dependency properties you’ll be adding to the control are pretty much the same as the ones shown in the previous section, with the extend that you have better access to the guts of the PivotViewer control. This way you have access to the Custom Actions for example.
Where to go next
You could start by implementing all properties of the PivotViewer control as dependency properties and add a ICommands to event handlers. Maybe you can find constructions where you can extend the control with your own needs
I just hope that in the next version of the PivotViewer Microsoft did this boring work for us so we don’t have to.
I don’t have plans for a next tutorial on the PivotViewer, yet. If you have question or requests just let me know and I’ll see if I can help you. If you want to be the first to when a new tutorial is available, you can subscribe to the RSS-Feed or follow me on twitter.
PivotViewer – Custom Actions
PivotViewer series
- Building your first PivotViewer application
- Runtime PivotViewer collection creation
- PivotViewer – Working with Facets
- Handling PivotViewer events
- PivotViewer – Custom actions
- PivotViewer and MVVM
Intro
In this tutorial about the Silverlight PivotViewer control I would like to explain how to make use of Custom Actions. Small labels are placed on top of items in the viewer and clicking them will trigger an event. They look something like this:
![]()
The only downside of these actions is that they aren’t fully implemented. So you’ll have to extend the PivotViewer control yourself. If you haven’t worked with the PivotViewer before, you might want to have a look at the Building your first PivotViewer application tutorial I wrote earlier first. This tutorial continues on that.
Extending the control
Start by adding a new class to a Silverlight project and naming this PivotViewerEx. Make this class inherit from PivotViewer. Create an override of the GetCustomActionsForItem method. This method is called by the PivotViewer when it is in need of some custom actions. The id of the item the user is hovering is passed to this method. You can do some filtering of the actions based on that. In this example no filtering takes place and the whole collection of custom actions is returned.
The list of custom actions is defined as property of this class. It is instantiated by the constructor.
public class PivotViewerEx:PivotViewer
{
public List<CustomAction> CustomActions { get; set; }
public PivotViewerEx()
{
CustomActions=new List<CustomAction>();
}
protected override List<CustomAction> GetCustomActionsForItem(string itemId)
{
return CustomActions;
}
}
Using the control
The extended PivotViewer control works in the same way as the original. It can be added to the XAML like below. The event that handles the clicks on the actions is added too.
<UserControl x:Class="PivotViewerCustomActions.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:PivotViewerCustomActions="clr-namespace:PivotViewerCustomActions"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<PivotViewerCustomActions:PivotViewerEx x:Name="Pivot"
ItemActionExecuted="CustomActionClicked"/>
</Grid>
</UserControl>
In the code behind, in the constructor of the page, the custom actions itself are added to the PivotViewer. The constructor of the CustomAction class takes four parameters:
- Name => is the text shown in the PivotViewer
- Icon => a URI to an image to show next to the text. You can use NULL to omit an image
- ToolTip => some text that is shown when the user hovers the mouse over the CustomAction
- Id => a unique ID to identify the action
public MainPage()
{
InitializeComponent();
Pivot.CustomActions.Add(
new CustomAction("Add to cart",
new Uri("http://localhost:49000/112_Plus_Green_32x32_72.png"),
"Add to cart","Add"));
Pivot.CustomActions.Add(
new CustomAction("Details",
new Uri("http://localhost:49000/Info.png"),
"Details","Details"));
Pivot.LoadCollection("http://localhost:49000/ElectronicsPivot.cxml",
string.Empty);
}
Handling the event
When the user clicks on the actions the CustomActionClicked event is fired. The event gets an instance of the ItemActionEventArgs class as event arguments. This class contains two properties. ItemId contains the the ID of the item the action was placed over. You can get the actual item by calling the GetItem method on the PivotViewer control with this ID.
The second property of the ItemActionEventArgs class is CustomActionId. This is the ID of the custom action that was clicked.
In the example below one of two a message boxes is shown depending on the action clicked. It won’t be hard to extend this further to your needs.
private void CustomActionClicked(object sender, ItemActionEventArgs e)
{
PivotItem item = Pivot.GetItem(e.ItemId);
if (e.CustomActionId == "Add")
{
MessageBox.Show(string.Format("Add {0} to Cart", item.Name));
if (e.CustomActionId == "Details")
{
MessageBox.Show(string.Format("Show details of {0}", item.Name));
}
}
Wrap-up
CustomActions provide a great way to add some extra functionality to the PivotViewer control. Too bad they aren’t fully implemented (yet?). The simple method shown in this tutorial uses code behind to add the actions. It would be great to be able to add these actions in XAML one day.
The next tutorial will be about using the Silverlight PivotViewer control in an MVVM application. If you want to be the first to know when it is available, you can subscribe to the RSS-Feed or follow me on twitter.
Handling PivotViewer events
PivotViewer series
- Building your first PivotViewer application
- Runtime PivotViewer collection creation
- PivotViewer – Working with Facets
- Handling PivotViewer events
- PivotViewer – Custom actions
- PivotViewer and MVVM
Intro
Today I would like to go into a little detail about the events used in the PivotViewer control for Silverlight. If you haven’t worked with the PivotViewer yet you might want to read the getting started tutorial I wrote earlier first.
CollectionLoadingCompleted
The CollectionLoadingCompleted event is fired when loading of the collection is completed.
CollectionLoadingFailed
The CollectionLoadingFailed event is raised when an error occurs when loading a collection. The event uses gets an instance of the CollectionErrorEventArgs class when it is fired. This class contains two properties.
The first is ErrorCode. This property is of the enum type CollectionError and contains two values: DownloadError and ParsingError.
ErrorCode equals DownloadError when there was an error downloading the collection. For example if the URL used in the LoadCollection method is wrong. The ErrorCode contains the ParsingError value when there is an issue with the .CXML file which prevents it from being parsed. For example a typing error in the .CXML.
The second property used in the CollectionErrorEventArgs class is Exception. This property contains the exception thrown by he PivotViewer control. This exception can provide very useful information when building runtime collections.
ItemDoubleClicked
This event is fired when an item in the PivotViewer is double clicked. The event is given a ItemEventArgs object. The ItemEventArgs class contains 1 property, ItemId. This string contains the ID of the items that is clicked. You can use this ID to get the whole item by calling the GetItem method on the PivotViewer control.
private void Pivot_ItemDoubleClicked(object sender, ItemEventArgs e)
{
PivotItem item = Pivot.GetItem(e.ItemId);
// insert something useful to do with the item here
// like showing a popup with more info.
}
LinkClicked
When the end-user click on a facet of the link type this event is fired by the PivotViewer control. The URL is passed to the event through the LinkEventArgs. The navigation itself isn’t performed by the PivotViewer. You’ll have to handle that yourself. The code below shows an example of that. It checks if the URL that is clicked ends with .CXML. In that case the URL is used to load a new collection. Otherwise the user will be directed to the target URL.
private void Pivot_LinkClicked(object sender, LinkEventArgs e)
{
Uri targetUrl = e.Link;
if (targetUrl.LocalPath.EndsWith(".cxml",
StringComparison.InvariantCultureIgnoreCase))
{
//If the link is to CXML, show it in this PivotViewer.
Pivot.LoadCollection(targetUrl.AbsoluteUri, string.Empty);
}
else
{
//Otherwise open the URL in a new window
HtmlPage.Window.Navigate(targetUrl, "_blank");
}
}
ItemExecutedEvent
The ItemExecutedEvent is raised when the end-user clicks on a Custom Action. Support for this isn’t fully implemented in this version of the PivotViewer control. In the next tutorial I’ll show you how to use custom actions and how they are handled using this event.
Wrap-up
There aren’t that many events in the PiverViewer control. But it’s good to know which ones are there and how to use them.
The next tutorial will be about Custom Actions. To be the first to know when it is released you can subscribe to the RSS-feed or follow me on twitter.
PivotViewer – Working with Facets
PivotViewer series
- Building your first PivotViewer application
- Runtime PivotViewer collection creation
- PivotViewer – Working with Facets
- Handling PivotViewer events
- PivotViewer – Custom actions
- PivotViewer and MVVM
Intro
In this next tutorial about the Silverlight PivotViewer control I would like to give a little more depth on Facets. What are facets, and how are they used in runtime generation of collections using the PivotServerTools library.
This tutorial continues on techniques from last tutorial about runtime collection creation. If you are just getting started using the PivotViewer control, you might want to have a look at the Getting Started Tutorial first. This tutorial is centered around the methods build in the last tutorial: MakeCollection and MakeItem.
Facets
Facets are basically the properties on the PivotViewer that allow the visitor to sort and filter. Facets are also shown when viewing the details of an item.
Facets are added to the collections by calling the Collection.AddItem() method. This method takes a couple of parameters. The first is the Name of the item being added. The second is a URL. This can be used to navigate to more details about the item for example. This URL is used when clicking on the Name of the item in the details panel. Then there’s the Description of the item. This text is shown on the details panel. The fourth parameter is the image shown in the DeepZoom part of the control. The ItemImage type from the PivotServerTools. Its constructor is used, to which a URL to the image is given. All parameters after that, from the fifth on are Facets. You can add as many as you need. A call to AddItem might look something like this:
collection.AddItem(
id,
url,
description,
new ItemImage(new Uri(image)),
new Facet("String value", FacetType.Text, id),
new Facet("Integer Value", FacetType.Number, intValue),
new Facet("Double Value", FacetType.Number, doubleValue),
new Facet("Date value",FacetType.DateTime,date),
new Facet("Url Value",FacetType.Link, new FacetHyperlink("Url Value", urlValue)),
new Facet("Names", names),
new Facet("FormattedValue",formattedValue)
);
Facets are grouped in Facet Categories. Every item in the collection can contain one or more facet categories and every category can contain one or more facets. Facet categories are created when a they are used for the first time while adding items to the collection.
The PivotServerTools library is used to generate the .CXML. It uses 4 types of facets categories:Text, Number, DateTime and Link. The type of facet category determines how facets are displayed in the PivotViewer control. Each facet in the category must be of this type.
Text:
The text type is used to display anything of type string. If the type is omitted and the type can’t be determined automatically the Text type is defaulted to.
To create a facet of type text you can use its constructor with a category name, the type of facet and its tag. For example:
Facet stringFacet = new Facet("Names", FacetType.Text, name);
This might look something like this in the PivotViewer control.
Number:
This facet type is used to display numbers. It allows the end-user to make selections on ranges of this tag. This tag value can also be formatted which I’ll explain later.
Again, to create a facet of this type, use its constructor and pass in a different FacetType this time:
Facet integerFacet = new Facet("Integer Value", FacetType.Number, intValue);
Facet doubleFacet = new Facet("Double Value", FacetType.Number, doubleValue);
DateTime:
Dates are displayed like in the image below. You can select a date by era, the actual value or select a custom range.
The date facets are added the same way as numbers or text, but with a different FacetType.
Facet dateFacet = new Facet("Date value",FacetType.DateTime, date);
Link:
Hyperlinks are not shown in the filter list. Only the name given to the URL is shown in the details list. Clicking on a link does not navigate by default. You’ll have to implement the navigate yourself. An event is fired when an item on the details panel is clicked though.
To create a facet of type link you can use its constructor again. Only the third parameter is different this time. It takes a value of type FacetHyperLink. The type uses a description and a URL together. In the code below both are passed into the constructor of FacetHyperLink. Both parameters are strings.
Facet linkFacet = new Facet("Url Value", FacetType.Link,
new FacetHyperlink("Displayed Name", urlValue));
One last thing to notices about adding items to the collection. As I mentioned earlier, every facet category can be used zero or more times. The constructor of Facets takes one or more values for a value for each tag. You could, for example, add an array of strings to a category at once just by passing that array to the constructor. All values will be shown in that category on the details panel.
string[] myNames = {"Timmy Kokke", "Sorskoot"};
Facet namesFacet = new Facet("My Names",FacetType.Text, names );
More on categories
After the items are added to the collection you can fine-tune the categories a little further. Often it is necessary to make facet categories visible in only the details panel or enable filtering for a particular category but disable text search on them. The Collection class has a method to set these properties.
The SetFacetDisplay method takes the name of the category and 3 booleans. The first of the three booleans indicated whether or not the category is shown in the list of filters. The second enables or disables the category showing up in de info panel. When the last is set to false the category is excluded from the text search.
Here are a few examples.
collection.SetFacetDisplay("Integer Value", true, false, false);
collection.SetFacetDisplay("Double Value", false, true, false);
collection.SetFacetDisplay("Names", true, true, false);
The Integer Value category is shown in the list of filters, but hidden from the info panel and the text search. The Double Value category is hidden from the filters and the text search, but is visible on the info panel. The Names category is visible in both filters and info panel, but isn’t used for text search.
The Collection class has one other method of interest concerning facets. The SetFacetFormat is used to set format of a category in which it is displayed. It uses standard .NET string formatting. For example, to display a double as a floating point with 3 decimals you can use the following code:
collection.SetFacetFormat("FormattedValue", "F3");
Wrap-up
The code that goes along with this tutorial can be downloaded here. The next tutorial will be about the events of the PivotViewer control. To be the first to know when it is released you can subscribe to the RSS-feed or follow me on twitter.
Technorati Tags: Silverlight,PivotViewer


