Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

Silverlight TreeView: MVVM and editing [2 – Commanding]

This post is about commanding. In MVVM application context, one way to describe commanding would be to call it a ‘declarative way of connecting Actionable Elements with some Actions by the means of Commands’.

Right… First things first – what’s an ‘Actionable Element’? Actionable elements are all elements (or controls), that can respond to some action from the user by raising an appropriate event. For example: when you click on a button, it raises the Click event. By this definition, all clickable controls are actionable elements. Let’s take a look at the TextBox – is it an actionable control? Of course it is! There are many cases you want for something to happen when you press an enter key when inside the TextBox. And thinking of a ListBox – sometimes it’s its SelectionChanged event you want to respond. Now you get the idea…

So what’s an ‘Action’? Putting it in a well-known terms, it’s simply an event handler. So instead of writing this in Xaml:

<Button Click="Button_Click" />
 
and then implementing the Click event handler in the code behind:
 
private void Button_Click(object sender, RoutedEventArgs e)
{
    // Do stuff
}
 
you would write something like:
 
<Button Command="DoSomeStuff" />
 
and instead of writing the event handler in your Xaml’s code behind, you would write it there where it belongs to. With MVVM application, this place is usually the ViewModel.

And now we get to the ‘Command’. Think of it as a some kind of a delegate to your action – your one and only event handler, which will handle that one command. Many actionable elements can then be assigned this exact command to perform when acted upon.

Commanding is also one of the many things here Silverlight differ from WPF. WPF has a powerful commanding support built in the framework, while on the other hand, there is only a small trace of commanding that can be seen in Silverlight – the ICommand interface… and that’s it! Needless to say, in order to build a competent MVVM solution in Silverlight we need commanding.

One common approach to introduce commanding in Silverlight is by attached behavior. Attached behavior is a way to extend an element by attaching a ‘behavioral’ property to it - you create an attached property with custom logic and attach this property to an element, which is supported by this property.

There are several examples on how to create commanding support in Silverlight around the web, but from what I could gather, the implementation from the SLExtensions project (CodePlex) currently seems to be the most popular one. And that’s the also one going to be used in this series. In fact, the Input folder in this solution project is a copy from the one in the SLExtensions. The SLExtensions Command pattern is not exactly the same as in WPF, but it’s very close and adequate.

To get back to our case and use the new knowledge of commanding, we’ll create two commands – one for adding, the other for deleting our help topics:

public static class Commands
{
    static Commands()
    {
        AddTopic = new Command("AddTopic");
        DeleteTopic = new Command("DeleteTopic");
    }

    public static Command AddTopic { get; private set; }
    public static Command DeleteTopic { get; private set; }
}
 
then add two buttons to our page, pointing to that commands through an attach property, provided with the abovementioned Command pattern:
 
<StackPanel Orientation="Horizontal">
    <Button Content="Add Topic" input:CommandService.Command="AddTopic" />
    <Button Content="Delete Topic" input:CommandService.Command="DeleteTopic" />
</StackPanel>

The last thing we have to do  is create the command event handlers for the actual work. We’ll do that in the ViewModel because that’s where all action is. We’ll keep the logic behind both of commands very simple: AddTopic command will add a topic as the child of the first node in the tree, while DeleteTopic will remove the last child of the same node, if any children present:

private void OnAddTopicExecuted(object sender, ExecutedEventArgs e)
{
    HelpTopics[0].SubTopics.Add(new HelpTopic() { Name = "Custom Topic" });
}

private void OnDeleteTopicExecuted(object sender, ExecutedEventArgs e)
{
    if (HelpTopics[0].SubTopics.Count == 0)
    {
        return;
    }
    HelpTopics[0].SubTopics.RemoveAt(HelpTopics[0].SubTopics.Count - 1);
}

Observing a running application (source code below) shows how User Interface (the TreeView) reacts to changes in the underlying ViewModel, triggered by commands, attached to ‘actionable’ buttons. Still no code in our Page code behind, which is good…

To finish this post, I’ll show another feature of commanding: conditional invocation. You can prevent the command from being called if the criteria for command’s invocation is not met. With the current commanding implementation, we just have return a boolean, indicating whether the criteria for a command is met or not, as a response to a CanExecute event. To check on whether a topic can be deleted or not, we’d use:

private void DeleteTopic_CanExecute(object sender, CanExecuteEventArgs e)
{
    e.CanExecute = HelpTopics[0].SubTopics.Count > 0;
}

In this post I introduced commanding and show a very basic example on how it’s used in a MVVM application.

Next in the series: moving to the TreeView [finally :)]

The source code for this sample is available:

Silverlight TreeView: MVVM and editing [1]

This is the first post in a series with a simple, yet specific goal: to add editing capabilities to Silverlight Toolkit’s TreeView control and build a MVVM (Model-View-ViewModel) pattern application with it.

This introductory post will deal with really basic stuff. Nothing new and fancy, we’re just going to set up the grounds for a simple application that displays a hierarchical collection of some help topics in a TreeView.

We’ll begin with finding the suitable hierarchical structure to put in the TreeView. For the purpose of this sample, I copied some content from Silverlight SDK documentation:

Silverlight Help Topics

First, we’ll need a data generator that will create the data structure. In a real world scenario, you would call a web service to get such data, but we’ll get to that a bit later. For now, this dummy data generator will have to do:

public static class DataGenerator
{
public ObservableCollection<HelpTopic> GetHelpTopics()
{
return new ObservableCollection<HelpTopic>()
{
new HelpTopic() { Name = "Debugging, Error Handling, and Exceptions", SubTopics =
                new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Debugging Overview", SubTopics =
                    new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Walkthrough: Setting Up Remote Debugging on the Macintosh"}
}},
new HelpTopic() {Name = "Error Handling"},
new HelpTopic() {Name = "Exceptions", SubTopics=new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Exception Class and Properties"},
new HelpTopic() {Name = "Exception Hierarchy"},
new HelpTopic() {Name = "Exception Handling"},
new HelpTopic() {Name = "Best Practices for Handling Exceptions"}
}}
}},
new HelpTopic() { Name = "Deployment and Localization", SubTopics =
                new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Creating Globally Aware Applications"},
new HelpTopic() {Name = "Localizing Silverlight Applications"}
}},
new HelpTopic() { Name = "Performance", SubTopics = new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Performance Tips"},
new HelpTopic() {Name = "How To: Use a Background Worker"},
new HelpTopic() {Name = "Threading", SubTopics = new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Managed Threading Overview"},
new HelpTopic() {Name = "Best Practices for Managed Threading"},
new HelpTopic() {Name = "Threading Objects and Features"}
}},
}}
};
}
}

Looks ugly, but there is really just one entity class involved – here is the HelpTopics class:

public class HelpTopic
{
public string Name { get; set; }
public ObservableCollection<HelpTopic> SubTopics { get; set; }

public HelpTopic()
{
}
}

The name property will hold the text to be displayed in a tree, and SubTopics is a collection of child items. ObservableCollection plays a significant role in MVVM applications because of its ability to inform potential listeners that the collection has changed in some way (item was added, changed, or list was cleared, etc.). With MVVM, one potential listener is the User Interface (visual elements in your application), which can react to any changes, made in data which it’s bound to.
The HelpTopic class currently doesn’t hold any unique Id field. I intentionally left that out for the moment; it will be added when needed.

OK, we have our Model. What we need next is the ViewModel. A ViewModel is a bridge between the View and the Model and acts like a Model to the View. Hence the name :)

Since it’s going to serve the main page, we’ll call it – the PageViewModel:

public class PageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private ObservableCollection<HelpTopic> helpTopics;

public ObservableCollection<HelpTopic> HelpTopics
{
get { return helpTopics; }
private set
{
if (helpTopics == value)
{
return;
}
helpTopics = value;
OnPropertyChanged("HelpTopics");
}
}

public PageViewModel()
{
HelpTopics = DataGenerator.GetHelpTopics();
}

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{

handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

The ViewModel only has one property [HelpTopics] because that’s currently the only one we need. Notice its private setter – we’re allowing setting this property from within the ViewModel only. Also, until we implement a better method to retrieve our data, we’re initializing the HelpTopics data collection directly in ViewModel’s constructor.

The ViewModel implements the INotifyPropertyChanged interface to notify its listeners when one of its properties has changed. Similar to what ObservableCollection does, but this one’s for a single class.

To finish this, all we have left is to compose a View. We’ll populate it with a TreeView control, set it to up to display our topics and create an instance of our PageViewModel for the DataContext:

<Grid x:Name="LayoutRoot">
    <Grid.DataContext>
        <local:PageViewModel />
    </Grid.DataContext>
    <slt:TreeView VerticalAlignment="Stretch" Margin="20" Width="300" ItemsSource="{Binding HelpTopics}">
        <slt:TreeView.ItemTemplate>
            <slt:HierarchicalDataTemplate ItemsSource="{Binding SubTopics}">
                <TextBlock Text="{Binding Name}" />
            </slt:HierarchicalDataTemplate>
        </slt:TreeView.ItemTemplate>
    </slt:TreeView>
</Grid>

The PageViewModel instance is set as a DataContext of the topmost page element (Grid), which means it will serve all page’s elements. One of its consumers is the TreeView control, which takes whatever is in its HelpTopics property for its items source. The last thing we had to do is set up a HierarchicalDataTemplate, specifying the property holding the subitems, and the visual of the tree item – a simple TextBlock with its Text property bound to the HelpTopic class’ Name property will suffice.

Help Topics TreeViewThis is what our TreeView control looks now. Far from being editable or anything yet, but except coding the dummy data generator and a class with one property, we hardly did any coding; And that’s the power of the MVVM pattern.

Next in the series: modifying the data structure.

The source code for this sample is available:

Silverlight TreeView: MVVM and editing [1]

This is the first post in a series with a simple, yet specific goal: to add editing capabilities to Silverlight Toolkit’s TreeView control and build a MVVM (Model-View-ViewModel) pattern application with it.

This introductory post will deal with really basic stuff. Nothing new and fancy, we’re just going to set up the grounds for a simple application that displays a hierarchical collection of some help topics in a TreeView.

We’ll begin with finding the suitable hierarchical structure to put in the TreeView. For the purpose of this sample, I copied some content from Silverlight SDK documentation:

Silverlight Help Topics

First, we’ll need a data generator that will create the data structure. In a real world scenario, you would call a web service to get such data, but we’ll get to that a bit later. For now, this dummy data generator will have to do:

public static class DataGenerator
{
public ObservableCollection<HelpTopic> GetHelpTopics()
{
return new ObservableCollection<HelpTopic>()
{
new HelpTopic() { Name = "Debugging, Error Handling, and Exceptions", SubTopics =
                new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Debugging Overview", SubTopics =
                    new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Walkthrough: Setting Up Remote Debugging on the Macintosh"}
}},
new HelpTopic() {Name = "Error Handling"},
new HelpTopic() {Name = "Exceptions", SubTopics=new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Exception Class and Properties"},
new HelpTopic() {Name = "Exception Hierarchy"},
new HelpTopic() {Name = "Exception Handling"},
new HelpTopic() {Name = "Best Practices for Handling Exceptions"}
}}
}},
new HelpTopic() { Name = "Deployment and Localization", SubTopics =
                new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Creating Globally Aware Applications"},
new HelpTopic() {Name = "Localizing Silverlight Applications"}
}},
new HelpTopic() { Name = "Performance", SubTopics = new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Performance Tips"},
new HelpTopic() {Name = "How To: Use a Background Worker"},
new HelpTopic() {Name = "Threading", SubTopics = new ObservableCollection<HelpTopic>()
{
new HelpTopic() {Name = "Managed Threading Overview"},
new HelpTopic() {Name = "Best Practices for Managed Threading"},
new HelpTopic() {Name = "Threading Objects and Features"}
}},
}}
};
}
}

Looks ugly, but there is really just one entity class involved – here is the HelpTopics class:

public class HelpTopic
{
public string Name { get; set; }
public ObservableCollection<HelpTopic> SubTopics { get; set; }

public HelpTopic()
{
}
}

The name property will hold the text to be displayed in a tree, and SubTopics is a collection of child items. ObservableCollection plays a significant role in MVVM applications because of its ability to inform potential listeners that the collection has changed in some way (item was added, changed, or list was cleared, etc.). With MVVM, one potential listener is the User Interface (visual elements in your application), which can react to any changes, made in data which it’s bound to.
The HelpTopic class currently doesn’t hold any unique Id field. I intentionally left that out for the moment; it will be added when needed.

OK, we have our Model. What we need next is the ViewModel. A ViewModel is a bridge between the View and the Model and acts like a Model to the View. Hence the name :)

Since it’s going to serve the main page, we’ll call it – the PageViewModel:

public class PageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private ObservableCollection<HelpTopic> helpTopics;

public ObservableCollection<HelpTopic> HelpTopics
{
get { return helpTopics; }
private set
{
if (helpTopics == value)
{
return;
}
helpTopics = value;
OnPropertyChanged("HelpTopics");
}
}

public PageViewModel()
{
HelpTopics = DataGenerator.GetHelpTopics();
}

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{

handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

The ViewModel only has one property [HelpTopics] because that’s currently the only one we need. Notice its private setter – we’re allowing setting this property from within the ViewModel only. Also, until we implement a better method to retrieve our data, we’re initializing the HelpTopics data collection directly in ViewModel’s constructor.

The ViewModel implements the INotifyPropertyChanged interface to notify its listeners when one of its properties has changed. Similar to what ObservableCollection does, but this one’s for a single class.

To finish this, all we have left is to compose a View. We’ll populate it with a TreeView control, set it to up to display our topics and create an instance of our PageViewModel for the DataContext:

<Grid x:Name="LayoutRoot">
    <Grid.DataContext>
        <local:PageViewModel />
    </Grid.DataContext>
    <slt:TreeView VerticalAlignment="Stretch" Margin="20" Width="300" ItemsSource="{Binding HelpTopics}">
        <slt:TreeView.ItemTemplate>
            <slt:HierarchicalDataTemplate ItemsSource="{Binding SubTopics}">
                <TextBlock Text="{Binding Name}" />
            </slt:HierarchicalDataTemplate>
        </slt:TreeView.ItemTemplate>
    </slt:TreeView>
</Grid>

The PageViewModel instance is set as a DataContext of the topmost page element (Grid), which means it will serve all page’s elements. One of its consumers is the TreeView control, which takes whatever is in its HelpTopics property for its items source. The last thing we had to do is set up a HierarchicalDataTemplate, specifying the property holding the subitems, and the visual of the tree item – a simple TextBlock with its Text property bound to the HelpTopic class’ Name property will suffice.

Help Topics TreeViewThis is what our TreeView control looks now. Far from being editable or anything yet, but except coding the dummy data generator and a class with one property, we hardly did any coding; And that’s the power of the MVVM pattern.

Next in the series: modifying the data structure.

The source code for this sample is available:

Decimal separators in Silverlight

I run English Windows with regional settings set to Slovenian, which means I’m also using a comma (,) for my decimal separator character, not a dot (.), which is mostly used in English-speaking countries.

Silverlight sees my configuration as:

CultureInfo.CurrentCulture: sl-SI
CultureInfo.CurrentUICulture: en-US

And with my current setup I still have to use a dot for my decimal separator. To test this, I created a business object with numeric (decimal) property and use a TwoWay-bound TextBox on it.

Typing a comma-separated value into the box
 
and tabbing out of it, gets me

whereas entering a dot-separated value

leaves me with
 

Silverlight is clearly ignoring my regional settings so what can I do to make this work?

Rather than catching keystrokes and convert dots into commas etc., one simple solution comes in a form of a value converter, which would use a CurrentCulture when converting a number between string and decimal:

public class CultureNumberConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((decimal)value).ToString(CultureInfo.CurrentCulture);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
decimal returnValue;
if (decimal.TryParse(value.ToString(), NumberStyles.Any, CultureInfo.CurrentCulture, out returnValue))
{
return returnValue;
}
return value;
}
}

 
Here’s a full solution sample:

WLW: spell checker for your language

With the latest RC release, Windows Live Writer introduced a couple of new languages for spell checking, including Slovenian. But there’s a catch – you won’t get any of them when you install the English version of Windows Live Essentials(a fancy name for all Live products, available through the same installer). Installing the English version will only get you English dictionaries, namely Australia, Canada, UK & US.

To get your Writer’s spell check your posts against your preferred language dictionary file, you have two options:

1. Download and run the Live Essentials installer for the language you want, then browse to the c:\Program Files\Windows Live\Writer\Dictionaries\ folder and get the files for your language (mssp3SL.dll and mssp3SL.lex for Slovenian language or equivalents for other languages). I installed this on my testing laptop so I didn’t have to uninstall the current version on my working machine. If you don’t have a spare machine, you’ll have to do a bunch of installs/uninstalls on one single machine to get everything back to where it was, plus gain your new dictionary files.

2. If you’re using Microsoft Office and already have a spell-checking option for your wanted language (either you installed localized version of some Office product or you installed additional Office Language Packs), the chances are you already have the necessary dictionary files on your machine. Browse to the C:\Program Files\Common Files\Microsoft Shared\Proof\ and look for the dictionary files (mssp3SL.dll and mssp3SL.lex or equivalent for your language (last two letters of the filename represent the language code). Copy those to Writer’s Dictionaries folder (c:\Program Files\Windows Live\Writer\Dictionaries\), restart the Writer and you’re good to go.
Note: I’m not 100% certain this is the case for any language available, but I found that for Slovenian language, both Office and Writer’s dictionary files were exactly the same! I also tested this with a couple of other dictionary files from my Office Proof folder and had no problems using them.

Windows Live Writer 2009 is currently a RC; the final release will hopefully make the process of adding additional language dictionaries easier by either:

  • using Office dictionaries, if available
  • releasing separate language pack add-ons

UPDATE: Windows Live Essentials RC, released a month, became RTW/final yesterday. It's the same version, so no need to upgrade if you already installed RC.

Weight Watching

If you followed me on Twitter you’d know about my latest little “problem”. I decided not to wait another month for my New Year’s resolutions, but start losing that extra weight right away. To help me keep my score, I created a little Silverlight app, showing my progress visually, through a line chart. Since charts were introduced in recently released Silverlight Toolkit, this was a very simple task.

All I had to do was:

1. Create a SQL 2008 database to keep my weight history in. The key idea here ware daily updates…
2. Expose data as a service (WCF, what else)
3. Build a Silverlight front end, which would consume this data service and present the data using the Chart bits from Silverlight Toolkit.

After browsing through some of the enclosed samples, it all boiled down to just these few lines of Xaml:

<UserControl 
    x:Class="WeightWatch.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WeightWatch"
    xmlns:charting="clr-namespace:Microsoft.Windows.Controls.DataVisualization.Charting;
                    assembly=Microsoft.Windows.Controls.DataVisualization"
    Width="600" Height="300">
    <UserControl.DataContext>
        <local:ViewModel />
    </UserControl.DataContext>
    <Grid x:Name="LayoutRoot">
        <charting:Chart Title="Andrej's Weight Watch" LegendTitle="Legend">
            <charting:Chart.Series>
                <charting:LineSeries
                        Title="Running Weight"
                        ItemsSource="{Binding RunningWeight}"
                        IndependentValueBinding="{Binding Date}"
                        DependentValueBinding="{Binding Weight}" />
                <charting:LineSeries
                        Title="Target Weight"
                        ItemsSource="{Binding TargetWeight}"
                        IndependentValueBinding="{Binding Date}"
                        DependentValueBinding="{Binding Weight}" />
            </charting:Chart.Series>
        </charting:Chart>
    </Grid>
</UserControl>

With the exception of the ViewModel, which is responsible of fetching the data from the service, there was absolutely no additional code required for this to work. Simplicity at its best. There’s of course much more to this than just displaying static data lines in a box; I have a long way to lose those 10+ kilos, which will give me plenty of time to update this sample with some new features.

And here's my progress:

Creating splash screens with Expression Designer

Did you know you can create cool looking splash screens for your WPF application right there with the Expression Designer?

Of course you did. Expression Designer provides you with all you need to create free-shaped, part-transparent, drop-shadowed graphics and I bet the the WPF splash screen support is going to be baked into the next release of Expression Blend as well.

This is a quick walk through designing a splash screen with the Expression Designer.

1. With Expression Designer open, create a new rectangle and set its Corner Radius property to about 30px (depending your rectangle’s size).

2. Set rectangle’s color to match your application theme and make it a bit transparent by setting Opacity to around 70%.

Rectangle

3. Find the Effects property section and click the Add Effect button. Choose Effects | Drop Shadow.

Add Effect

4. Decrease Softness and Offset and increase Opacity properties to make the shadow more compact. You will end up with something like this:

Drop Shadow and Transparence

5. Create a new layer and put a new rectangle on it. Make it the same size as the first one and put it on the same spot to make them both aligned exactly.

6. Set its stroke to None and fill it with a transparent gradient: First Stop Alpha: 80%, Second Stop Alpha: 0%.

7. Move gradient’s origin more to the side and make it larger.

Gradient

Your rectangle should now look just a little bit more exciting:

Light source

8. Time for some text… With the Text tool, create your application title. I’ve chosen 36 pt Arial Rounded MT Bold font with white color fill. Applying some transparency to the text will make it absorb some background color for a more glassy look. You could add some Outer Glow Effect to make it even cooler.

9. Add all other text you want to show in your splash screen. Here’s what I got so far:

Title & Text

10. If you have any graphics that could communicate to the user what your application is all about, you could use that as well. It might also be a screenshot from the actual application if you can’t find anything better. I used a screenshot of my sample Live Europe Weather Map application. Adding a bitmap to the existing Expression Design project is really easy – just select File | Import… and open your graphics - it will get added to the current layer so you will probably want to create a new layer before doing that. And don’t forget to set some transparency to that as well:

Bitmap

11. Almost done. To break out of dull symmetric rectangly shape, you can mix in some additional decorations, like I did to point out that this is a whole new version of the application [the yellow badge is from the bittbox badges collection:

 Final Splash

And this is the final result for now. We’ve got transparency, irregular shape, drop shadow… Of course, this works for a sample, but for a real-world application I would have to put some additional work into it; pay more attention to the details, colors, gradients, etc.

12. When satisfied with your work, just select all objects, select File | Export… and choose PNG as your target format. After the file is saved on your disk, all you need is incorporate it in your WPF application.

Expression Design offers a lot more effects and options that were shown in this quick walkthrough. I am particularly happy to see how easy it is to play with different effects, mixing and layering them in different combination. There is, of course, also export to different Xaml instances, which makes it even more sweet.

While writing this post, I noticed that the WPF team published a new WPF Splash Screen Item Templates for Visual Studio 2008 SP1. This gives you additional option to add a splash screen to your WPF application – a new (Splash Screen (WPF)) item will be available in your templates window when adding a new item. Selecting that will insert a default graphics to your project and set it as the splash screen. You’ll have to customize the graphics yourself though. This is a nice option, although I’d like to see some form of a wizard with some styling options, font/title selections, etc… In the next version of Visual Studio perhaps…

Splash Screen in WPF 3.5 SP1

Besides improving application startup time, .NET Framework 3.5 SP1 also allows developers to add a splash screen to WPF applications. The splash screen is shown using native code, even before WPF application starts to load. In reality this means the splash screen would show immediately when application is started, and fade away a couple of seconds later, when application is fully loaded and main screen displayed.

WPF Splash screen is just and nothing more than a plain bitmap image. Common formats are supported, and if you use a PNG format with a specified alpha channel, transparent areas will be shown accordingly. Just remember to keep it small. Choosing a couple of megabytes large bitmap for your splash screen won’t reduce the loading time. Adding additional information to the image during runtime (title, version number) is also not possible; everything you want to show should be designed in advance and incorporated into a single image.

WPF splash screens can be added to an application in two ways:

Showing splash screen manually

1. Create a new PNG image, which will be your splash screen.

2. Start your Visual Studio 2008 SP1 and create a new WPF project. [make sure .NET 3.5 is specified as the target FX]

3. Choose Project | Add Existing Item… Find and select your splash screen image.

4. Open App.xaml file in design view and look in the properties window ;)

Events in VS2008 WPF designer

Yes, there’s an event panel in WPF designer! And properties/events sorting option buttons!

5. Create a Startup event handler:

   1: private void Application_Startup(object sender, StartupEventArgs e)
   2: {
   3:     SplashScreen screen = new SplashScreen("sp1splash.png");
   4:     screen.Show(true);
   5: }

6. Compile and run.

The SplashScreen constructor takes the name of the resource, which is a splash screen image. The boolean parameter in the Show() method specifies, whether the splash screen should fade out when application is fully loaded. False means you’ll have to hide the splash screen manually using the Close() method.

If you don’t like writing code, this gets even easier:

 

Showing splash screen declaratively

1. Create a new PNG image, which will be your splash screen.

2. Start your Visual Studio 2008 SP1 and create a new WPF project. [make sure .NET 3.5 is specified as the target FX]

3. Choose Project | Add Existing Item… Find and select your splash screen image.

4. Select the newly added image in the solution explorer and show its properties.

5. Change the Build Action to SplashScreen.

6. Compile and run.

The splash screen shows immediately upon the application startup and fades out when the main window is loaded and shown. How’s that for cool new user experience :)

 

Additional note: SplashScreen class works in WPF desktop apps only, XBAPs have their own mechanism for starting up.

Label.Target Pt.2: The return of the (not so) attached property

Following my previous example, this is another experiment with the Label.Target property.

Suppose you want to restrict user’s progression with data input on a form by disabling some crucial input fields, which input depends on some other fields on the form. There’s more than a couple of ways for doing this and the first solution that springs to mind would be doing it by employing business object data validation. But if you need a pure UI/XAML solution, this can be the alternative:

image 
[See it live – loose Xaml page ahead ]

What’s happening in the sample above – the second TextBox gets enabled only when the first TextBox is not empty. The same goes for the third box, except here’s the second box that has to have some text entered into it.

This was done with the help of data triggers:

   1: <Label Target="{Binding ElementName=firstBox}" Content="_1st:" />
   2: <TextBox Name="firstBox" Grid.Column="1" Margin="2" /> 
   3: <Label Target="{Binding ElementName=secondBox}" Content="_2nd:" Grid.Row="1" />
   4: <TextBox Name="secondBox" Grid.Column="1" Margin="2" Grid.Row="1">
   5:   <TextBox.Style>
   6:     <Style TargetType="{x:Type TextBox}">
   7:       <Style.Triggers>
   8:         <DataTrigger Binding="{Binding Path=Text.Length, ElementName=firstBox}" Value="0">
   9:           <Setter Property="IsEnabled" Value="false" />
  10:         </DataTrigger>
  11:       </Style.Triggers>
  12:     </Style>
  13:   </TextBox.Style>
  14: </TextBox>
  15: <Label Target="{Binding ElementName=thirdBox}" Content="3rd:" Grid.Row="2" />
  16: <TextBox Name="thirdBox" Grid.Column="1" Margin="2" Grid.Row="2"> 
  17:   <TextBox.Style>
  18:     <Style TargetType="{x:Type TextBox}">
  19:       <Style.Triggers>
  20:         <DataTrigger Binding="{Binding Path=Text.Length, ElementName=secondBox}" Value="0">
  21:           <Setter Property="IsEnabled" Value="false" />
  22:         </DataTrigger>
  23:       </Style.Triggers>
  24:     </Style>
  25:   </TextBox.Style>
  26: </TextBox>

There’s a lot of repetitive Xaml code above that can be put away by using a style and an attached property.

[Note: I’m going to hijack the Label.Target dependency property here just because it suits the needs for this sample - it’s not even registered as an attached property and this wouldn’t even compile in Visual Studio! In a real application you would want to produce a completely new attached property to avoid all potential troubles that may result from such (mis)use]

As mentioned in the previous post, a Label.Target property can hold a reference to another control on the page. We’re going to use the property to point to the dependency source control:

   1: <Label Target="{Binding ElementName=firstBox}" Content="_1st:" />
   2: <TextBox Name="firstBox" Grid.Column="1" Margin="2" /> 
   3: <Label Target="{Binding ElementName=secondBox}" Content="_2nd:" Grid.Row="1" />
   4: <TextBox Name="secondBox" Grid.Column="1" Margin="2" Grid.Row="1"
   5:   Label.Target="{Binding ElementName=firstBox}" />
   6: <Label Target="{Binding ElementName=thirdBox}" Content="3rd:" Grid.Row="2" />
   7: <TextBox Name="thirdBox" Grid.Column="1" Margin="2" Grid.Row="2" 
   8:   Label.Target="{Binding ElementName=secondBox}" />

The global style is applies the same principle, shown in the previous post:

   1: <Style TargetType="{x:Type TextBox}">
   2:   <Style.Triggers>
   3:     <DataTrigger Binding="{Binding Path=(Label.Target).Text.Length, RelativeSource={RelativeSource Self}}" Value="0">
   4:       <Setter Property="IsEnabled" Value="false" />
   5:     </DataTrigger>
   6:   </Style.Triggers>
   7: </Style>

The data trigger in the above style disables the target TextBox when its Length property is set to 0.

This looks good already, but something is not right… Hint: try the current example live and fill all three boxes, then clear the first one.

We need to fix this and we’ll do it by adding another data trigger, which disables the current TextBox whenever the source TextBox is disabled. Here’s slightly modified version of the style:

   1: <Style TargetType="{x:Type TextBox}">
   2:   <Style.Triggers>
   3:     <DataTrigger Binding="{Binding Path=(Label.Target).Text.Length, RelativeSource={RelativeSource Self}}" Value="0">
   4:       <Setter Property="IsEnabled" Value="false" />
   5:     </DataTrigger>
   6:     <DataTrigger Binding="{Binding Path=(Label.Target).IsEnabled, RelativeSource={RelativeSource Self}}" Value="false">
   7:       <Setter Property="IsEnabled" Value="false" />
   8:     </DataTrigger>
   9:   </Style.Triggers>
  10: </Style>
Well, that’s all, really… A simple example to show the power of WPF data binding through the attached properties. [A post on creating a proper attached property for this sample will follow as I move away from Xaml-only examples]

And this is the final result code for this post [See it in action – loose Xaml file]

Label.TargetProperty as a Source

One of probably most underused features in windows desktop UI development world is got to be the use of a Label as an accessor to its pair control. I rarely see developers using this possibility to enhance keyboard UI navigation.

A couple of things changed about this mechanism when going from Windows Forms to WPF:

  1. The escape character to mark the mnemonic (the letter/key for accessing related control) changed from ‘&’ to ‘_’;
  2. In Windows Forms, the control that received focus was always the one that was next in tab order. With WPF, the pair control is specified with the Label.Target dependency property.

A simple form with this feature enabled would look like:

   1: <Grid>
   2:   ...
   3:   <Label Target="{Binding ElementName=firstNameBox}" Content="_First name:"/>
   4:   <TextBox Name="firstNameBox" Grid.Column="1"/> 
   5:   <Label Target="{Binding ElementName=lastNameBox}" Content="_Last name:" Grid.Row="1" />
   6:   <TextBox Name="lastNameBox" Grid.Column="1" Grid.Row="1"/> 
   7:   ...
   8: </Grid>

The best thing about Label's Target property is not only it sets focus to its pair control, but can also pose as a bridge back to the Label when we need to provide some feedback from the target control. For example, when a TextBox gets disabled,  we would want the associated Label render disabled as well. This is fairly easy to achieve through binding. All we need is a simple style for a label:

   1: <Style TargetType="{x:Type Label}">
   2:   <Setter Property="IsEnabled" Value="{Binding Path=Target.IsEnabled, RelativeSource={RelativeSource Self}}" />
   3: </Style>

The key is in binding's path, which queries target's IsEnabled property and sets it accordingly.

This opens up a range of possibilities. One of my favorite UI tricks is to visually differentiate the focused control from the others by slightly contrasting the label, associated with the focused control.  Label.Target is perfect for this.

I built on my previous example and the result now looks like this:

And here's the Label style I used:

   1: <Style TargetType="Label">
   2:   <Setter Property="Foreground" Value="{StaticResource LabelTextBrush}" />
   3:   <Style.Triggers>
   4:       <DataTrigger Binding="{Binding Path=Target.IsFocused, RelativeSource={RelativeSource Self}}" Value="True" >
   5:           <Setter Property="Control.Foreground" Value="{StaticResource FocusedLabelTextBrush}" />
   6:       </DataTrigger>
   7:   </Style.Triggers>
   8: </Style>

It's similar to the previous one, it just uses a DataTrigger to set Label's foreground color instead of direct property mapping.

I also added a short animation to make TextBoxes flash for a moment when they receive focus.

You can see all this in action by downloading and executing this Loose Xaml page.