When I created Zune account for my brand new WP7 device, I selected the US region – mine was not supported at that moment. Few months later, tired from not being able to buy any apps or games (my card was not accepted by the US marketplace), I decided to switch to my local region. Thankfully, Microsoft has added support for new markets prior to the Mango update.

The process if migrating your account is not so obvious. You won’t find anything related at Zune or Live websites. That can only by done through the Xbox account management (in case you didn’t know – your account is shared between Xbox Live and Zune services).

So go to your account page at https://live.xbox.com/en-US/Account, find the Manage Account Region link.

Manage account region

You will be noted that you can change the region once in 12 months and that you will not be able to re-download all your Xbox Live or Zune content, however it will not be deleted from your devices, so you can back it up.

Read that information carefully and ensure that you understand the consequences. Click Next and select the new region, then keep moving through the confirmation pages.

If everything is fine, your account will be switched to another region. Note that it may take some time to update your Zune account.

MVVM + TPL + Unit tests

Posted on Sep 27, 2011 in and tagged ,

UPD: This implementation didn’t work as well as expected, please read the follow-up article.

Recently I’ve faced an issue with writing unit tests for view model commands that use Task Parallel Library for asynchronous operations. Searching over the web was not really helpful, so I spent some time designing the approach to handle such cases.

The most common way to start tasks with TPL is by using one of the static Task.Factory.StartNew(…) methods. If you are mockist TDD guy, this should already raise an alert in your head. Static members are not test-friendly and do not allow you to inject mock dependencies into your module. One may say that using tasks is just an implementation details and should not be concerned when testing the behavior. I would agree if we were speaking about a regular async method that allows you to perform some action when its execution completes (in a form of callback or event, doesn’t really matter).

That simply doesn’t work for me because the asynchrony is used inside the command handler, so there is no way to specify the continuation outside of the view model.

My first (and probably the bad one) idea was to create a service for running the tasks. Then it would be easy to mock it and run tasks synchronously. Hopefully, I rejected this solution – creating another dependency just didn’t sound right.

I decided to create a special ICommand implementation instead that would notify me when the execution completes. This should do the trick because you can always use the thread sync primitives in the test environment to wait on the asynchronous task.

For simplicity’s sake I just created the wrapper around RelayCommand from MVVM Light Toolkit (you could use your favorite library or implement the command from scratch yourself).

public class AsyncDelegateCommand: ICommand
{
    private readonly RelayCommand _innerCommand;

    public event EventHandler ExecuteCompleted;

    public event EventHandler CanExecuteChanged
    {
        add { _innerCommand.CanExecuteChanged += value; }
        remove { _innerCommand.CanExecuteChanged -= value; }
    }

    public AsyncDelegateCommand(
        Action<AsyncDelegateCommand> executeMethod,
        Func<bool> canExecuteMethod)
    {
        _innerCommand = new RelayCommand(
            () => executeMethod(this),
            canExecuteMethod);
    }

    public void Execute(object parameter)
    {
        _innerCommand.Execute(null);
    }

    public bool CanExecute(object parameter)
    {
        return _innerCommand.CanExecute(null);
    }

    public void NotifyCompleted()
    {
        var handler = ExecuteCompleted;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

Sample application

The test harness application is fairly simple. The single button starts a ‘long-running’ asynchronous task. The button is disabled while the task is running.

public class MainViewModel : ViewModelBase
{
    private bool _isRunning;

    public bool IsRunning
    {
        get { return _isRunning; }
        set
        {
            if (_isRunning != value)
            {
                _isRunning = value;
                RaisePropertyChanged("IsRunning");
            }
        }
    }

    public AsyncDelegateCommand StartLongOperationCommand 
    { 
        get; 
        private set; 
    }

    public MainViewModel()
    {
        StartLongOperationCommand =
            new AsyncDelegateCommand(OnStartLongOperation,
                () => true);
    }

    private void OnStartLongOperation(AsyncDelegateCommand command)
    {
        IsRunning = true;

        Task.Factory
            .StartNew(() => Thread.Sleep(5000))
            .ContinueWith(task =>
            {
                // update UI

                IsRunning = false;
                command.NotifyCompleted();
            }, TaskScheduler.FromCurrentSynchronizationContext());
    }
}

The command handler starts the main task and specifies its continuation that updates the UI properties and notifies when the command is completed. Note that I used the UI task scheduler for the continuation. In this particular case it doesn’t make much sense because WPF automatically dispatches INotifyPropertyChanged events on the UI thread, but our ‘update UI’ logic could be more sophisticated (i.e. ObservableCollection modifications).

Unit Tests

[TestClass]
public class MainViewModelTests
{
    [TestMethod]
    public void CommandShouldNotifyAboutCompletion()
    {
        var context = new SynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(context);
            
        bool notified = false;

        var sync = new ManualResetEvent(false);

        var target = GetTarget();

        target.StartLongOperationCommand.ExecuteCompleted += (s, e) =>
        {
            notified = true;
            sync.Set();
        };

        target.StartLongOperationCommand.Execute(null);
        sync.WaitOne();

        Assert.IsTrue(notified);
    }

    private MainViewModel GetTarget()
    {
        return new MainViewModel();
    }
}

Points of interest:

  • Using ManualResetEvent as a thread synchronization primitive. The main test thread awaits until the sync is set to signaled state on the delegate handler completion.
  • Setting current SynchronizationContext value. UI update continuation task is scheduled on the TaskScheduler, acquired from the current synchronization context. When TaskScheduler.FromCurrentSynchronizationContext is called in the test environment, it throws an exception by default (TaskScheduler.Current and TaskScheduler.Default are both set to null). So we explicitly create and set a new task scheduler.

Download sources (TaskCommands.zip)

I work at several projects at a time, and I have different settings/requirements concerning the code style for each of them. The main issue is ‘Tabs vs. Spaces’ option – the first project requires using tabs, the second – spaces. It’s obvious that going Tools -> Settings -> … is not an option for everyday use. Sounds like a good task for the automation macros, right?

  1. Navigate to Tools -> Macros -> Macros IDE (or use Alt+F11)
  2. Create new macros in Project Explorer (Project – Add Module)
  3. Write a method that changes the indentation settings:
Public Module TabsModule
    Public Sub ToggleTabs()
        Dim currentSetting As Boolean = DTE.Properties("TextEditor", "CSharp").Item("InsertTabs").Value
        DTE.Properties("TextEditor", "CSharp").Item("InsertTabs").Value = Not currentSetting
    End Sub
End Module

Now you can use Macros Explorer (Alt+F8, also you can dock it as one of your panels) to quickly change settings (by double-clicking on the corresponding item name in the macros tree)

Macros Explorer displaying the created macros

Building advanced MVVM commands, Part 1

Posted on Nov 24, 2010 in and tagged , ,

If you follow the MVVM pattern while developing your WPF/Silverlight applications, then you are probably familiar with DelegateCommand (or RelayCommand, as it is called sometimes) model. In brief: it is an implementation of WPF/Silverlight ICommand that allows you to specify what the command should do by passing some delegate that performs execution logic (instead of using CommandBindings). Pretty simple, but powerful pattern.

Dealing with MVVM a lot, I’ve build my own implementation of this pattern that lets you simplify its usage.

Here are some common features, that you have to handle on your own by using classic DelegateCommand:

  • Support for asynchronous execution (usually solved by generating additional code in ViewModel that handles async calls and free/busy indicator).
  • Different command states (Free/Busy/Failed with exception) + UI reactions for those states.
  • Support for execution cancellation and progress tracking (required for asynchronous commands)

Before we start, I offer you to imagine a common command execution timeline. In my opinion it looks like:

  1. Initialize some data (generally, UI settings – clear collections, set some indicators,…)
  2. Perform main execution logic (can be synchronous or asynchronous)
  3. Perform some actions after execution (update UI based on execution result)

And don’t forget about exception handling and correct cross-thread calls for asynchronous commands (all UI changes have to be performed through Dispatcher).

Let’s start with a little helper class, that I called PropertyChangedNotifier. It’s just a wrapper around IPropertyChangedNotifier that has OnPropertyChanged(string propertyName) method. This method raises underlying IPropertyChangedNotifier.PropertyChanged event. Also this class has VerifyPropertyName method that verifies if specified string corresponds to the actual property (this method is marked with [Conditional(“DEBUG”)] attribute and is only used while debugging your applications to find out possible bugs with invalid property names)

public abstract class PropertyChangedNotifier : INotifyPropertyChanged
{
    protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        VerifyPropertyName(propertyName);

        var handler = PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    [Conditional("DEBUG")]
    [DebuggerStepThrough]
    private void VerifyPropertyName(string propertyName)
    {
        if (String.IsNullOrEmpty(propertyName))
        {
            return;
        }

        if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        {
            string msg = "Invalid property name: " + propertyName;
            if (ThrowOnInvalidPropertyName)
            {
                throw new Exception(msg);
            }
            Debug.Fail(msg);
        }
    }
}

Let’s start our DelegateCommand with this classic imlementation:

public sealed class DelegateCommand<T>: PropertyChangedNotifier, ICommand where T: class
{
    public Action<DelegateCommand<T>, T> ExecuteAction
    {
        get;
        set;
    }

    public Predicate<T> CanExecutePredicate
    {
        get;
        set;
    }

    public DelegateCommand(Action<DelegateCommand<T>, T> execute, Predicate<T> canExecute)
    {
        ExecuteAction = execute;
        CanExecutePredicate = canExecute;
    }

    public void Execute(object parameter)
    {
        //blank
    }

    public bool CanExecute(object parameter)
    {
        //blank
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}

As I’ve mentioned, we may need to execute this command asynchronously, so I added property IsAsync that lets you specify whether the call will be asynchronous or not. Also as have been discussed earlier, we need delegates for pre-execute, post-execute and error actions.

public Action<T> PreExecute
{
    get;
    set;
}

public event Action<DelegateCommand<T>> Executed;

public Action<Exception> OnException
{
    get;
    set;
}

public bool IsAsync
{
    get;
    set;
}

public bool DisableOnExecution
{
    get;
    set;
}

The last property, DisableOnExecution, tells command to report False to CanExecute calls when it is executed asynchronously.

Remember the command state I’ve told about? Create an enum named CommandState

public enum CommandState
{
    Succeeded,
    Failed,
    IsExecuting
}

and add State property of type CommandState to DelegateCommand.

private CommandState _state;
public CommandState State
{
    get { return _state; }
    set
    {
        if (_state == value)
        {
            return;
        }

        _state = value;

        //if command was executed asynchronously, there may be some issues with correct CanExecute checks,
        //so we force CommandManager to perform that check.
        lock (this)
        {
            if (IsAsync && DisableOnExecution)
            {
                InvokeOnUIThread(CommandManager.InvalidateRequerySuggested);
            }
        }

        OnPropertyChanged("State");
    }
}

This one is a bit tricky. For now, there are some issues with WPF that prevent CanExecute checks when command is executed asynchronously. So when async execution is completed, we tell CommandManager to update all the bindings and re-evaluate CanExecute by calling CommandManager.InvalidateRequerySuggested. Note that is has to be called on UI thread. InvokeOnUIThread adds specified action to the UI dispatcher queue.


public void InvokeOnUIThread(Action action) { Dispatcher.Invoke(action); }

Here Dispatcher is a local variable that is initialized in the constructor.

#if SILVERLIGHT
    Dispatcher = Deployment.Current.Dispatcher;
#else
    Dispatcher = Dispatcher.CurrentDispatcher;
#endif

And if we speak about async calls, let’s add a method that will invoke specified delegate asynchronously:

private static void InvokeAsync(Action task, AsyncCallback executed)
{
    task.BeginInvoke(executed, null);
}

private static void InvokeAsync(Action task)
{
    InvokeAsync(task, x => { });
}

Also you may want to store some exception information if the command execution failed.

private Exception _commandException;
public Exception CommandException
{
    get { return _commandException; }
    set
    {
        if (_commandException == value)
        {
            return;
        }

        _commandException = value;
        OnPropertyChanged("CommandException");
    }
}

Command cancellation? Yes, add IsCancellationPending property. With all this things set up, we are ready to implement Execute and CanExecute methods.

public void Execute(object parameter = null)
{
    var typedParameter = parameter as T;

    Action action = () =>
    {
        try
        {
            CallExecute(typedParameter);
            if (State != CommandState.Failed)
            {
                State = CommandState.Succeeded;
            }
        }
        catch (Exception ex)
        {
            State = CommandState.Failed;
            CommandException = ex;
            CallOnException(ex);
        }
    };

    IsCancellationPending = false;
    CommandException = null;
    State = CommandState.IsExecuting;

    CallPreExecute(typedParameter);

    if (IsAsync)
    {
        var handler = Executed;
        if (handler == null)
        {
            InvokeAsync(action);
        }
        else
        {
            InvokeAsync(action, x => handler(this));
        }
    }
    else
    {
        action();
        CallExecuted();
    }
}

public bool CanExecute(object parameter)
{
    if (CanExecutePredicate != null)
    {
        try
        {
            return !GetIsBusy() && CanExecutePredicate(parameter as T);
        }
        catch
        {
            return false;
        }
    }
    return !GetIsBusy();
}

Methods that are named like CallXXX are just wrappers around corresponding delegates that check if they can be called.

private void CallPreExecute(T arg)
{
    if (PreExecute != null)
    {
        PreExecute(arg);
    }
}

private void CallExecute(T arg)
{
    if (ExecuteAction != null)
    {
        ExecuteAction(this, arg);
    }
}

private void CallExecuted()
{
    var handler = Executed;
    if (handler != null)
    {
        handler(this);
    }
}

private void CallOnException(Exception ex)
{
    if (OnException != null)
    {
        InvokeOnUIThread(() => OnException(ex));
    }
}

GetIsBusy method is pretty simple.

private bool GetIsBusy()
{
    return DisableOnExecution && (State == CommandState.IsExecuting);
}

Note that Execute method can perform both synchronous and asynchronous calls based on IsAsync value. Pre-execution, post-execution and error handling delegates are called on UI thread, so when you use the command, you don’t have to think about.

Building test application

It will be pretty simple. User selects a directory, application lists all the files in this directory and its sub-directories. I’ll start with FileModel class that will represent one list entry

public class FileModel
{
    public String Name
    {
        get;
        set;
    }

    public String Extension
    {
        get;
        set;
    }

    public String Size
    {
        get;
        set;
    }

    public String FullPath
    {
        get;
        set;
    }
}

Next to the ViewModel. It will have Files property (the collection of FileModel) and LoadFilesCommand (implemented as our DelegateCommand)

public sealed class MainWindowViewModel: PropertyChangedNotifier
{
    public MainWindowViewModel()
    {
        Files = new ObservableCollection();
    }
        
    public ObservableCollection Files
    {
        get;
        private set;
    }

    private DelegateCommand _loadFilesCommand;
    public DelegateCommand LoadFilesCommand
    {
        get
        {
            return _loadFilesCommand ?? (_loadFilesCommand = new DelegateCommand(LoadFiles)
            {
                DisableOnExecution = true,
                IsAsync = true
            });
        }
    }

    private void LoadFiles(DelegateCommand cmd, String loadFrom)
    {
        cmd.InvokeOnUIThread(() => Files.Clear());

        Action addFile = file =>
        {
            var model = new FileModel
            {
                Name = Path.GetFileNameWithoutExtension(file),
                FullPath = Path.GetFullPath(file),
                Extension = Path.GetExtension(file),
                Size = GetFileSize(file)
            };
            cmd.InvokeOnUIThread(() => Files.Add(model));
        };

        Action fileLoader = null;
        fileLoader = path =>
        {
            if (cmd.IsCancellationPending)
            {
                return;
            }

            foreach (var file in Directory.GetFiles(path))
            {
                addFile(file);
            }

            foreach (var dir in Directory.GetDirectories(path))
            {
                if (cmd.IsCancellationPending)
                {
                    return;
                }

                try
                {
                    fileLoader(dir);
                }
                catch {}
            }
        };

        fileLoader(loadFrom);
    }

    private static String GetFileSize(String fileName)
    {
        try
        {
            using (var stream = File.OpenRead(fileName))
            {
                return (stream.Length/1024).ToString();
            }
        }
        catch
        {
            return "?";
        }
    }
}

Some comments:

  • We use recursive lambda-function to get all the files in the specified folder.
  • At each loop step we have to check if the user decided to cancel operation.
  • Empty catch are blocks are not good! I used them only to keep things simple. Normally you will have to log all the errors.
  • All actions that change UI state must be performed on UI thread (I use cmd.InvokeOnUIThread(…))
  • Pre-execute, post-execute and error handling are not covered in this sample. I will show how they can be used in the next part.

The application window markup

private void StopButton_Click(object sender, RoutedEventArgs e)
{
    (DataContext as MainWindowViewModel).LoadFilesCommand.IsCancellationPending = true;
}

Event handler in the code-behind file (we will get rid of this in the following parts, so that cancellation will be available from markup)

private void StopButton_Click(object sender, RoutedEventArgs e)
{
    (DataContext as MainWindowViewModel).LoadFilesCommand.IsCancellationPending = true;
}

Run the application. Enter any path in the text box and click Start button. It will be disabled and application will start to fill the list with file information. Clicking Stop will cancel this operation.

Sample application that uses async commands

That’s all for now. With this implementation we can keep ViewModels clean and perform async operations practically the same way that we would perform the usual ones.

Download sources

In the next parts I will show how the progress tracking can be added, how we can improve command initialization with fluent extensions and how it all can be combined with visual states via DataTemplates techniques I’ve described earlier. Good luck =)

Consider a common task – you need to switch between different screens in your application, that represent various states (e.g. Normal/Loading/Error). How are you going to implement this?

You can start with VisualStateManager and define appropriate visual states. Well, this will surely do the thing, but you will have to create lots of controls and manage their Visibility or Opacity. And what if you have a complex markup? And I suppose that switching the state will not remove invisible items from the visual tree. And even more, with VisualStateManager you are bound to Expression Blend, because, you know, it’s not very convenient to edit VSM settings by hands in XAML (which I prefer, but it is a topic for another article). The second option that may fit well, if you just need something like “I’m busy!” overlay is Silverlight Activity Control. Works like a charm with RIA services, but I find it limited for complex scenarios (and it’s not available for WPF).

I’ve found another approach (it becomes especially useful with MVVM and improved DelegateCommand implementations – I will blog about this in a few days). The idea behind this technique is quite simple. You define different templates for different page/window/control states. Yeah, that’s it. Let’s start with our implementation.

Our application will have only one page with 2 different states:

  1. A welcome screen, that hosts a button to start ‘the heavy’ calculation.
  2. Busy window” that shows information about the current processing progress.

I decided to create a simple ViewModel as a backing storage for our UI properties. It has two properties – IsBusy that says whether some hard work is executing now, and Progress – simple execution progress indicator. Method StartCalculation runs a new thread executes a number of loop steps. On each step the executing thread is suspended for 100ms (to imitate a slow operation). Normally you will create a DelegateCommand that will handle all the execution logic, but I decided to keep things simple.

public sealed class MainWindowViewModel: INotifyPropertyChanged
{
    public const string IsBusyProperty = "IsBusy";
    private bool _isBusy;
    public bool IsBusy
    {
        get { return _isBusy; }
        set
        {
            if (_isBusy == value)
            {
                return;
            }

            _isBusy = value;
            OnPropertyChanged(IsBusyProperty);
        }
    }

    public const string ProgressProperty = "Progress";
    private int _progress;
    public int Progress
    {
        get { return _progress; }
        set
        {
            if (_progress == value)
            {
                return;
            }

            _progress = value;
            OnPropertyChanged(ProgressProperty);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(String property)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(property));
        }
    }

    public void StartCalculation()
    {
        IsBusy = true;
        ThreadPool.QueueUserWorkItem(_ =>
        {
            for (int i = 0; i <= 50; i++)
            {
                int i1 = i;
                Deployment.Current.Dispatcher.BeginInvoke(() => Progress = i1);
                Thread.Sleep(100);
            }

            Deployment.Current.Dispatcher.BeginInvoke(() => IsBusy = false);
        });
    }
}

Let’s build a simple user interface (for now, without any states, just to check if our threading logic works)

<UserControl 
    x:Class="DataTemplateStateApplication.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModels="clr-namespace:DataTemplateStateApplication.ViewModels"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">

    <UserControl.DataContext>
        <ViewModels:MainWindowViewModel/>
    </UserControl.DataContext>

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
		    
            <Button Width="60" Height="24" Content="Test">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <ei:CallMethodAction MethodName="StartCalculation" TargetObject="{Binding}"/>
                    </i:EventTrigger>
               </i:Interaction.Triggers>
            </Button>
		    
            <ProgressBar 
                Minimum="0" Maximum="50"
                Value="{Binding Progress}" 
                Height="24" Width="250" 
                Grid.Row="1" Margin="0,8,0,0"/>
        </Grid>
    </Grid>
</UserControl>

Note that if you use Visual Studio, you will have to manually add references to Microsoft.Expression.Interactions.dll and System.Windows.Interactivity.dll

I added a simple event trigger that calls StartCalculation method of our ViewModel when user clicks the button.

Now let’s move to the article subject. Define two DataTemplates in UserControl.Resources section:

<UserControl.Resources>
    <DataTemplate x:Key="NormalTemplate">
        <Button Width="60" Height="24" Content="Test">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:CallMethodAction MethodName="StartCalculation" TargetObject="{Binding}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </DataTemplate>
    <DataTemplate x:Key="BusyTemplate">
        <ProgressBar Minimum="0" Maximum="50" Value="{Binding Progress}" 
                     Height="24" Width="250"/>
    </DataTemplate>
</UserControl.Resources>

These templates describe two different presentations for a single MainWindowViewModel. Now we just have to provide some logic for switching between these templates when IsBusy property changes. Remove old layout markup (Button and Progressbar) and replace it with ContentPresenter with Content property bound to MainWindowViewModel:

<ContentPresenter Content="{Binding}">
    <i:Interaction.Triggers>
        <ei:DataTrigger Binding="{Binding IsBusy}" Value="True">
            <ei:ChangePropertyAction PropertyName="ContentTemplate" Value="{StaticResource BusyTemplate}"/>
        </ei:DataTrigger>
        <ei:DataTrigger Binding="{Binding IsBusy}" Value="False">
            <ei:ChangePropertyAction PropertyName="ContentTemplate" Value="{StaticResource NormalTemplate}"/>
        </ei:DataTrigger>
    </i:Interaction.Triggers>
</ContentPresenter>

Those DataTriggers from Microsoft.Expression.Interactions assembly do all the magic. They analyze the current value of IsBusy property and change the ContentPresenter.ContentTemplate value to the appropriate template.

That’s it. This technique can easily be used with more than 2 states, just declare new templates and triggers. Works with WPF too.

Download sources

WPF Explorer TreeView with SelectedPath binding

Posted on Nov 18, 2010 in and tagged

While working on one of my projects, I had to implement a control for displaying file system. I found pretty good articles over the web (“A Simple WPF Explorer Tree” by Sacha Barber and some replies to it), but they were all about displaying folders.

It was pretty easy to track currently selected folder, but there were some issues with its dynamic changes. So I decided to build my own control from scratch that will have some property like SelectedPath that will allow you to use TwoWay bindings to get and set selected folder at the tree.

Explorer-like tree view

When user selects a node from the TreeView, text in the address bar is updated. When user enters address and clicks Update, TreeView selection gets updated. I have started with a simple CustomControl and inherited it from WPF TreeView:

public class ExplorerTreeView: TreeView
{
    public const string SelectedPathPropertyName = "SelectedPath";

    public static readonly DependencyProperty SelectedPathProperty = DependencyProperty.Register(
        SelectedPathPropertyName,
        typeof (String),
        typeof (ExplorerTreeView));

    public String SelectedPath
    {
        get { return (String) GetValue(SelectedPathProperty); }
        set { SetValue(SelectedPathProperty, value); }
    }
}

We will use some lazy-loading techniques to fill our TreeView with data. When control is loaded, it will display only drives on the user machine. Let’s write a method for creating initial drive nodes:

public void InitExplorer()
{
    Items.Clear();

    foreach (var drive in DriveInfo.GetDrives())
    {
        Items.Add(GenerateDriveNode(drive));
    }
}

private static TreeViewItem GenerateDriveNode(DriveInfo drive)
{
    var item = new TreeViewItem
    {
        Tag = drive,
        Header = drive.ToString()
    };

    item.Items.Add("*");
    return item;
}

GenerateDriveNode method takes DriveInfo argument and builds TreeViewItem for it. Note that we are adding a dummy child node (the one with ‘the star’ header text). If we don’t do this, then the user will not see a small button for expanding/collapsing for generated tree view item (it may look like ‘+’ character that is replaced with ‘-‘ when the node is expanded or like an arrow that changes it direction).

InitExplorer method is pretty straight-forward. It just enumerates all the drives and populates Items collection with corresponding TreeViewItems.

Now we just have to handle TreeViewItem.ExpandedEvent to react to user interaction. When node is expanded, it will display all the sub-folders of the selected folder.

Put this line to control constructor:

AddHandler(TreeViewItem.ExpandedEvent, new RoutedEventHandler(OnItemExpanded));

Then create OnItemExpanded handler

private void OnItemExpanded(object sender, RoutedEventArgs e)
{
    var item = (TreeViewItem)e.OriginalSource;
    item.Items.Clear();
    DirectoryInfo dir;
    if (item.Tag is DriveInfo)
    {
        var drive = (DriveInfo)item.Tag;
        dir = drive.RootDirectory;
    }
    else
    {
        dir = (DirectoryInfo)item.Tag;
    }

    foreach (var subDir in dir.GetDirectories())
    {
        item.Items.Add(GenerateDirectoryNode(subDir));
    }
}

GenerateDirectoryNode method will look like

private static TreeViewItem GenerateDirectoryNode(DirectoryInfo directory)
{
    var item = new TreeViewItem
    {
        Tag = directory,
        Header = directory.Name
    };
    item.Items.Add("*");

    return item;
}

Everything was rather simple so far. Now lets move towards the more complex stuff. We have to synchronize our tree view selection state and SelectedPath value. I created 2 helper methods for accessing and changing current tree view item selection (GetSelectedPath and SetSelectedPath).

private String GetSelectedPath()
{
    var item = (TreeViewItem)SelectedItem;
    if (item == null)
    {
        return null;
    }

    var driveInfo = item.Tag as DriveInfo;
    if (driveInfo != null)
    {
        return (driveInfo).RootDirectory.FullName;
    }

    var directoryInfo = item.Tag as DirectoryInfo;
    if (directoryInfo != null)
    {
        return (directoryInfo).FullName;
    }

    return null;
}

private void SetSelectedPath(String value)
{
    InitExplorer();

    if (String.IsNullOrEmpty(value))
    {
        return;
    }

    var split =
        Path.GetFullPath(value).Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar },
            StringSplitOptions.RemoveEmptyEntries);
    var drive = new DriveInfo(split[0]);

    foreach (TreeViewItem driveItem in Items)
    {
        var name = ((DriveInfo)driveItem.Tag).Name.ToLower();
        if (name == drive.Name.ToLower())
        {
            Expand(driveItem, 1, split);
            break;
        }
    }
}

private void Expand(TreeViewItem item, int index, string[] pathParts)
{
    if (index > pathParts.Length)
    {
        return;
    }

    if (index == pathParts.Length)
    {
        item.IsSelected = true;
        return;
    }

    if (!item.IsExpanded)
    {
        item.IsExpanded = true;
    }

    var name = pathParts[index].ToLower();

    foreach (TreeViewItem folderItem in item.Items)
    {
        var directoryInfo = (DirectoryInfo)folderItem.Tag;
        if (directoryInfo.Name.ToLower() == name)
        {
            Expand(folderItem, index + 1, pathParts);
            break;
        }
    } 
}

I have to make some remarks here:

  1. GetSelectedPath just returns information from selected DriveInfo or DirectoryInfo.
  2. SetSelectedPath splits target path to array of folders and uses recursive lambda-function to traverse down the tree and expand all the nodes on the way to the target folder. I had to put InitExplorer() call at the first line of this method. There were some issues with tree view selection system and SelectionPath dependency property value changes handling that didn’t allow to select a correct item, so the only work-around that I found was to rebuild the tree. Since we use lazy-loading and setting SelectedPath by code is not a common task, it works well.

Don’t forget to add handler for SelectedItemChanged event:

SelectedItemChanged += (s, e) => SelectedPath = GetSelectedPath();

We’re almost done – we have just to handle SelectedPath changes to update the UI:

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
    base.OnPropertyChanged(e);

    if (e.Property == SelectedPathProperty)
    {
        var newValue = (String)e.NewValue;
        if (IsSelectionUpdateRequired(newValue))
        {
            SetSelectedPath(newValue);
        }
    }
}

IsSelectionUpdateRequired method is used to prevent infinite loops (user selects a node => SelectedPath changes –> TreeView.SelectedItem changes –> SelectedPath changes –> …..) and unnecessary calculations – it compares current SelectedPath value with new one:

private bool IsSelectionUpdateRequired(String newPath)
{
    if (String.IsNullOrEmpty(newPath))
    {
        return true;
    }

    var selectedPath = GetSelectedPath();
    if (String.IsNullOrEmpty(selectedPath))
    {
        return true;
    }

    return !Path.GetFullPath(newPath).Equals(Path.GetFullPath(selectedPath));
}

The source code of the sample app is rather trivial and is not listed here, but you can find it in the archives.
Download sources and sample app

Note: attached project contains improved version that supports error reporting via custom event and UnloadItemsOnCollapse property that lets you specify whether node content will be unloaded when it is collapsed, or not, and images for disks and folder (implemented with custom value converter).