Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

Silverlight TreeView: MVVM and editing [3 – Delete]

After the first two introductory posts, we're ready to move into the TreeView control itself. We’ll begin by implementing the easiest of the three update commands (insert/update/delete) – to delete an item in a TreeView.

This one actually looks very simple, all we need is to redefine TreeView’s ItemTemplate by adding a delete button we’ve created in the previous post:

<slt:TreeView.ItemTemplate>
    <slt:HierarchicalDataTemplate ItemsSource="{Binding SubTopics}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}" VerticalAlignment="Center" />
            <Button ToolTipService.ToolTip="Delete Topic" Margin="2,0,0,0" 
                    input:CommandService.Command="DeleteTopic" 
                    input:CommandService.CommandParameter="{Binding}">
                <Image Source="/EditableTreeView;component/Resources/delete.png" Stretch="None" />
            </Button>
        </StackPanel>
    </slt:HierarchicalDataTemplate>
</slt:TreeView.ItemTemplate>

As we’ve seen in the previous post, associating the delete Button with the DeleteTopic command will invoke the same command when the button is pressed. What’s new is that we’re now passing the current item as a CommandParameter. By ‘current item’ I don’t mean the currently selected item, but the item, which button was clicked.

In order to get this working, we have to change the ViewModel as well:

private void OnDeleteTopicExecuted(object sender, ExecutedEventArgs e)
{
    HelpTopic topic = e.Parameter as HelpTopic;

    bool isRemoved = topic.RemoveFromStructure(HelpTopics, item => { return item.SubTopics; });
    if (!isRemoved)
    {
        throw new InvalidOperationException(string.Format("Topic '{0}' couldn't be removed.", topic.Name));
    }
}

OnDeleteTopicExecuted now deletes the element, passed as the invoked command’s parameter. To delete an element from a hierarchical collection structure, we somehow need to find its parent. Because the HelpTopic class doesn’t know about its parent, I used a simple hierarchical query to help me out. The generic RemoveFromStructure() extension method finds an item in the passed structure and deletes the item, if found.

TreeView

Now we’re able to delete individual items in the tree, but all those distractive buttons scattered around the screen introduced a lot of noise to the view. We should be somehow able to hide them.

There’s a couple of ways to do this. For now, we’ll just modify the TreeViewItem’s style a bit and set it as TreeView’s ItemContainerStyle. TreeViewItem’s style also contains the TreeViewItem’s template, defining the overall look of the items in the TreeView – how the items looks selected, when mouse-over etc. Don’t confuse it with the ItemTemplate – this one basically defines TreeViewItem’s content. To not complicate this further, here’s our TreeViewItem style modification [only modified parts shown here, the whole style is defined in project’s App.Xaml]:

<StackPanel Orientation="Horizontal"> <ContentPresenter x:Name="content" Cursor="{TemplateBinding Cursor}" Content="{TemplateBinding Content}"
  ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="Left"
        Margin="{TemplateBinding Padding}" /> <Button x:Name="commands" ToolTipService.ToolTip="Delete Topic" Margin="4,0,0,0" Opacity="0" input:CommandService.Command="DeleteTopic" input:CommandService.CommandParameter="{Binding}"> <Image Source="/EditableTreeView;component/Resources/delete.png" Stretch="None" /> </Button> </StackPanel>

 
and this is the added animation for the pressed state, showing the button when mouse is over the item:
 
<DoubleAnimation Storyboard.TargetName="commands" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />

The current TreeView overall styling and chosen mouse-over behavior might not be the best suiting for any type of application. We’ll worry about making it look pretty after we get it working right.

The TreeView definition now looks like:

<slt:TreeView VerticalAlignment="Stretch" Grid.Row="1" ItemsSource="{Binding HelpTopics}"
    ItemContainerStyle="{StaticResource TreeVireItemContainerStyle}">
    <slt:TreeView.ItemTemplate>
        <slt:HierarchicalDataTemplate ItemsSource="{Binding SubTopics}">
            <TextBlock Text="{Binding Name}" VerticalAlignment="Center" />
        </slt:HierarchicalDataTemplate>
    </slt:TreeView.ItemTemplate>
</slt:TreeView>

The delete button is now visible only when mouse hovers over each TreeView item. Pressing it deletes the same node, which is what we wanted to finish this post with anyway. And we still didn’t write any serious code… We’ll get more into the code in the next part of the series.

Next: item editing

The source code for this sample is available:

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:

I put a Tag on you…

This blog has been tagged.

Tag

Microsoft Tag Reader is available for a range of mobile devices, including iPhone. This is the second (I think) Microsoft app available in the iTunes Store - a way for Microsoft to introduce and promote their latest technologies to the Apple crowd.

I snapped a few tags I could find online. The results were at 100%, showing that the technology is quite stable and reliable... Just wondering how long until these “visual URLs” appear in the real life…

Sing a Songsmith

US_Prd_Bx_Tilt_L_Song_SmithBeen playing with a Songsmith a little today. It’s a music generation software, but with additional twist: you’re doing the vocals and Songsmith stands in as your backing band. It’s actually following your singing by choosing the right chords to match your voice in real time! Using it really gets as easy as pressing the record button and starting singing. There’s plenty of musical styles to choose from and even more can be downloaded. You can also fiddle with instruments, used in your song - e.g. replace acoustic guitar with a distorted electric one.

What can I say… it sounds great. It should provide countless of hours of fun with your young one, providing that she/he likes to sing of course… but which kid doesn’t. And if you really suck at singing, it may make you look… well, not so bad :) If it was also available for a mobile device, you could turn your life into a musical...

Guys from Microsoft Research made this a great app for a v1. More style, arrangement and instrument tweaking should make it into the next version to make it more interesting for non-beginners. And a MIDI support would be great.

Oh, did I mention it's a WPF application?

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.

This blog’s address changed

I broke most of the external referrals to my blog posts when moving to a new blog engine, so why not take this opportunity to change my blog’s address as well?

From now on, the official address of this blog is http://tozon.info/blog/ The old address will remain functional and I will do my best to catch and properly redirect all referring links to my blog posts that now end up in an error page.

The main RSS feed remains the same, again, thanks to FeedBurner.

ICEing the Nativity Scene

In my previous post I briefly described the process of creating a large Deep Zoom image with Microsoft Image Composite Editor. This post is going to present the steps I took with ICE in a little bit more detail, just to show its power.

As I mentioned in that post, I shot the scene with 24 (6x4) - kind of - detailed photos, which gave me the following set (arranged with the Deep Zoom Composer):

It doesn’t take a very detailed examination to notice how partial set photos are not distributed evenly, bear different lighting and some of them even being way out of focus. Now let’s see how ICE works it’s magic…

The ICE UI is simple as it is with Deep Zoom Composer. One thing I don’t get though is that I have to start it twice before the app actually appears on my desktop. Anyway, here’s how it looks when started:

image

The instructions couldn’t be simpler – I just had to drop all part photos onto editor’s main space and let it process them. After a minute or so, I got this:

image

Notice the perspective corrections? Camera motion setting was set to Rotating motion, which obviously hinted the processor that the scene was set from one single spot (like panorama). There is an option to adjust perspective and projection, which I simply didn’t need to do in this case.

Next were the crop settings – Automatic crop selects the optimal rectangle to exclude empty spaces:
 image

The Export sections offers a couple of options: your creation is exportable in a number formats, which selection varies depending on a scale setting. With the largest scale (100%), available formats are: TIFF Image, HD View Tileset and Deep Zoom Tileset. Smaller thumbnail creation is optional. Deep Zoom Tileset was the one I wanted, but before hitting the Export button, I took some more time to adjust the selection rectangle on the left to exclude an unimportant part of the scene:
 image

After clicking the Export Button, I was asked for a target directory and the project name. After that, the processor took over for a few minutes to render the output, which resulted in a ready-to-publish Deep Zoom folder.

Talking about publishing Deep Zoom/Silverlight content, here’s a little trick: if your hosting provider doesn’t have MIME types for Silverlight apps set up correctly, you can rename your XAP file to ZIP (including any references to it in accompanying files) and your app should still work.

The final result can be seen in the original post.

Deep Zoom Christmas Nativity Scene 2008

Setting up the nativity scene for the Christmas holidays has been my family tradition going back way before I was born. Most figures are dated back to my grandparents era, while the others (mostly sheep) were gathered over the years.

Each year, the scene setup is determined by a couple of factors, like the current inspiration/mood, the place to set it up and starting this this year – accessibility; we really don’t want our little munchkin do some redecoration on her own :) So this year I set it up on the less accessible place and made it a little bit smaller than usual.

At the same time, I wanted to try out the Microsoft ICE (Image Composite Editor), an amazing (free) piece of software, coming from Microsoft Research, which is doing a brilliant job at stitching your partial photos of the same subject into one really big photo, preserving the original resolution. The latest version has an option to export the final scene as a Silverlight Deep Zoom image, and this was the one that I was interested in trying out.

First, I tried to shoot a large number of really small and detailed photos (like 20 photos in one row by 10 rows), but soon realized that the place wasn’t getting enough light and/or my lenses were not up for the job. Also, this was an experiment rather than a professional job, so instead of bringing in more light, I decided to go smaller (6x4 photos only). Much less time consuming, I tell you… Anyway, I was very doubtful about the final result, because the exposure settings were not consistent throughout all photos and I left the autofocus on. I did try to keep the aperture small and constant for a decent DoF, but the shutter speed value kept going through the roof :)

Now, given the fact that I wasn’t really trying that hard, the final result looks very good for convincing me to give some more time and effort into my next panoramic photo projects.

And here it is – our Deep Zoom-ed Christmas Nativity Scene 2008:

Side note 1: with SeaDragon technology (the one behind Deep Zoom) coming to iPhone [Seadragon Mobile], I can now carry this image with me in my pocket :)

Side note 2: and how’s that for an original nativity scene? :)