Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

Silverlight TreeView: MVVM and editing [5 – Add]

In the previous post, we enabled editing for our TreeView. The last operation we need to implement is adding a new item to the hierarchy. With our tree item editor in place, there’s not so much left to do…

The only change we need to make with the View is add an Add button, right next to the Edit button. We’ll wire it to the Add command, which already exists.

The next stop is the ViewModel. We need to change the existing OnAddTopicExecuted handler to add a new child to the HelpTopic, passed into the method through CommandParameter:

private void OnAddTopicExecuted(object sender, ExecutedEventArgs e)
{
    HelpTopic topic = new HelpTopic();
    HelpTopic parent = e.Parameter as HelpTopic;
    if (parent == null)
    {
        HelpTopics.Add(topic);
    }
    else
    {
        parent.SubTopics.Add(topic);
    }
    topic.BeginEdit();
}

Note: when CommandParameter is not set to a valid HelpTopic (when it’s null), we’re adding a child to the root.

There is something wrong with the code above. I’m assuming that the SubTopics collection was already initialized when I created a new HelpTopic class instance. I this case, I assumed wrong and the above code would throw a nasty error.

I need to assure that SubTopics property is never null as this puts the HelpTopic in an invalid state. I’ll do that by inserting the collection initialization code in its constructor:

public HelpTopic()
{
    SubTopics = new ObservableCollection<HelpTopic>();
}

Better. But we’re not done yet. There is no way for user to cancel the newly added item. Sure, she can press the Cancel button when editing, but the node will not be removed from the tree.

This is the time to provide the HelpTopic class with an unique identificator field. When working with the database, the type of this field would align with whatever your database table primary key type is. For simplicity, I’ll use Guids here, just because their generation results in more unique results than a number randomization would.

The logic behind is this: when a new HelpTopic is being added, its Id is set to null. If the item is confirmed, the new Id is set, otherwise the item is removed from the hierarchy. Here’s how modified OnEndEditTopic and OnCancelEditTopic now look like:

private void OnEndEditTopic(object sender, ExecutedEventArgs e)
{
    HelpTopic topic = e.Parameter as HelpTopic;
    if (!topic.Id.HasValue)
    {
        topic.Id = Guid.NewGuid();
    }
    topic.EndEdit();
}

private void OnCancelEditTopic(object sender, ExecutedEventArgs e)
{
    HelpTopic topic = e.Parameter as HelpTopic;
    if (!topic.Id.HasValue)
    {
        topic.RemoveFromStructure(HelpTopics, item => { return item.SubTopics; });
    }
    topic.CancelEdit();
}

Wait! Before we end this, let me just put another button in a TreeView to enable user to add a new HelpTopic to the root of the tree. This is the modified template with a new button in place (added lines in bold italic):

<ControlTemplate TargetType="slt:TreeView">
    <Grid x:Name="Root" >
        <Grid.Resources>
            <SolidColorBrush x:Key="BorderBrush" Color="#FF000000" />
        </Grid.Resources>
        <Border x:Name="Border" BorderBrush="{StaticResource BorderBrush}" 
            BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"> <Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}" Margin="1"> <ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Auto"
                    VerticalScrollBarVisibility="Auto" Background="{x:Null}" BorderBrush="Transparent"
                    BorderThickness="0" IsTabStop="False" TabNavigation="Once"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Button HorizontalAlignment="Left" ToolTipService.ToolTip="Add Topic" input:CommandService.Command="AddTopic"> <Image Source="/EditableTreeView;component/Resources/add.png" Stretch="None" /> </Button> <ItemsPresenter x:Name="TreeItems" Grid.Row="1" Margin="5" /> </Grid> </ScrollViewer> </Border> </Border> </Grid> </ControlTemplate>

Editable TreeView

OK, we’ve got our TreeView to allow basic inline editing now, but not in very realistic scenario and it lacks usability. I’m going to end this series with this post and spin off to more general topics posts, covering more MVVM, LOB scenarios and Silverlight in general. A taste of things to come: improving, extending and expanding on the current state of this sample, going over the wire, testing and user experience.

The source code for this sample is available:

Silverlight TreeView: MVVM and editing [4 – Edit]

In the fourth post in this series we’ll get to actually edit an item in the TreeView.

First, we have to make our HelpTopic class editable. Well, yes, it is editable now, but we’ll make it even more editable :) by

a] implementing the IEditableObject interface. IEditableObject is defined as:

public interface IEditableObject
{
    void BeginEdit();
    void CancelEdit();
    void EndEdit();
}

The method names in the interface are so straightforward that I shouldn’t need to explain them here. However, one method which we benefit most from when our business object implements this interface, is CancelEdit. Why? Well, let’s say you have your TextBox twoway-bound to some object’s property. When you change the value in this TextBox and tab out, the changes are committed to your object and you have no options to undo this change. If you wanted to provide the OK/Cancel button pair for user to either confirm or undo her changes, you have a slight problem.

The IEditableObject interface is here to help. The CancelEdit method is responsible for reverting your object to the state it was before BeginEdit was called.

One of the Silverlight controls that supports this interface is DataGrid, so making your objects implement this interface will make them work consistently with DataGrid scenarios too.

Let’s see how our HelpTopic would implement the interface:

public class HelpTopic : IEditableObject
{
    private string nameCopy;

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

    public HelpTopic()
    {
    }

    public void BeginEdit()
    {
        nameCopy = this.Name;
    }

    public void CancelEdit()
    {
        Name = nameCopy;
    }

    public void EndEdit()
    {
    }
}

I’ve introduced a new private variable to store the value of the name property in case the CancelEdit is called. When dealing with complex objects, you would want to store a deep clone of your object instead of storing each and every (sub)property in a separate variable.

b] creating a new property, which would indicate that the object is in edit mode. We would set this property within these three new methods. It is important that changes to this property are propagated to the UI, so we also need:

c] implementing the INotifyPropertyChanged interface. This interface is not new, our PageViewModel already implements it. When implementing this interface, we can also change the Name property implementation to support notifications.

The full HelpTopic class now looks like:

public class HelpTopic : IEditableObject, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool isEditing;
    private string name;
    private string nameCopy;

    public ObservableCollection<HelpTopic> SubTopics { get; set; }

    public string Name
    {
        get { return name; }
        set
        {
            if (name == value)
            {
                return;
            }

            name = value;
            OnPropertyChanged("Name");
        }
    }

    public bool IsEditing
    {
        get { return isEditing; }
        private set
        {
            if (isEditing == value)
            {
                return;
            }

            isEditing = value;
            OnPropertyChanged("IsEditing");
        }
    }

    public HelpTopic()
    {
    }

    public void BeginEdit()
    {
        nameCopy = this.Name;
        IsEditing = true;
    }

    public void CancelEdit()
    {
        Name = nameCopy;
        IsEditing = false;
    }

    public void EndEdit()
    {
        IsEditing = false;
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

[Edit: changed IsEditing setter above to private; the property should be set from within the class only]

Moving upwards to the ViewModel, we need another three commands for invoking the new methods – BeginEditTopic, EndEditTopic and CancelEditTopic commands. Their ViewModel implementation is, again, pretty simple and straightforward:

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

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

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

All three methods just call their corresponding method on the HelpTopic item, passed into the method as a command parameter.

Now for the UI part… I guess I *could* do this with Xaml only, but I decided on building a new content control to pose as an View/Edit item switcher. The main reason for doing this is that I didn’t want end up with every item in the tree carry its own editor within its template. Instead, this new control will be responsible for loading the editor when one is needed.

In short, things are set up like this: I have this new control called EditableItemControl, pushed to somewhere near the top of the TreeViewItem’s visual tree with its contents set to what original item would look like. EditableItemControl has a property called EditorTemplate, which should be set to what the tree item should look like in edit mode. This is the EditorTemplate I used:

<Grid >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <TextBox Text="{Binding Name, Mode=TwoWay}" 
        input:CommandService.Command="EndEditTopic"
        input:CommandService.CommandParameter="{Binding}" 
    />
    <Button Name="saveButton" ToolTipService.ToolTip="OK" Grid.Column="1"
        input:CommandService.Command="EndEditTopic"
        input:CommandService.CommandParameter="{Binding}">
        <Image Source="/EditableTreeView;component/Resources/ok.png" Stretch="None" />
    </Button>
    <Button Name="closeButton" ToolTipService.ToolTip="Cancel" Grid.Column="2"
        input:CommandService.Command="CancelEditTopic"
        input:CommandService.CommandParameter="{Binding}">
        <Image Source="/EditableTreeView;component/Resources/cancel.png" Stretch="None" />
    </Button>
</Grid>

When editing is initialized, control’s original content is preserved and replaced with the above editor template, just to be switched back when editing is over. There are two ways to commit the changes – one is to press the saveButton, and the other is to press the Return key focused on the TextBox. Note that the TextBox is also wired to the EndEditTopic command, and TextBox control being one of the actionable elements in the SLExtensions framework, this simply works.

The key to make the switch between view and edit states is EditableItem’s IsEditing dependency property – the control goes to edit state when this property is set to true, and returns to its normal state when its value is set back to false. Ok, but how is this property set? Remember that our HelpTopic class also implements a property with the same name? They fit perfectly together:

<local:EditableTreeViewItem Grid.ColumnSpan="3" 
       IsEditing="{Binding IsEditing}" 
       HorizontalContentAlignment="Stretch">
    ...
</local:EditableTreeViewItem>

To tie all the ends together – when the Edit button is pressed, BeginEdit command is executed. ViewModel handles that command by calling the BeginEdit method on the HelpTopic item, for which the command was executed. IsEditing property gets set for this item and at the same time picked up by the EditableItemControl, which does the switch and display the editor for it. It’s like playing The Incredible Machine!

OK, we made the TreeView control editable. However, there are a few visual issues – one of them is that a mouse-over in a subitem shows the edit/delete commands for its ancestors all the way up to the root. I don’t know whether this is a default behavior for the TreeView or a bug of some sort, but until I find out, I’m leaving it as it is. I did use a TreeViewItem’s MouseOver state which wasn’t in the original template, so it may be that this state is not (properly) supported. Anyway, I’ll definitely get back to this, but first we have some adding to do.

About to edit an item

Editing an item

Next in the series: adding an item

The source code for this sample is available:

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.