... a journey through WPF, MVVM and .NET4 RSS 2.0
# Saturday, February 06, 2010

I cannot count how many times people have requested the source code to the ATAPI.NET or ITAPI3 projects.  My response has always been that I was unable to release it due to ownership issues (it was developed under contract for a client).  I am pleased to announce this morning that I have worked through those issues and have been granted permission to release the project in it’s entirety as source code on CodePlex!

Here’s their new homes:  http://atapi.codeplex.com/ and http://itapi3.codeplex.com

I’ll open up discussion board access there as well for Q&A.  If you would like to contribute to the project, shoot me an email and we’ll see about getting you access!

Saturday, February 06, 2010 11:56:38 AM (Central Standard Time, UTC-06:00)  #    Comments [1] -
.NET | Code | Tapi
# Friday, February 05, 2010

In the last post, I referred to the DragPositionBehavior in the JulMar MVVM library.  This behavior allows any UIElement to be dragged and repositioned using the mouse without requiring any code logic on your part.  It’s easy to apply – using the traditional Blend syntax (easiest done by dragging the behavior onto an element):

    <Interactivity:Interaction.Behaviors>

        <julmar:DragPositionBehavior />

    </Interactivity:Interaction.Behaviors>


This is the simplest way to use this, however it doesn’t work when the behavior is to be applied with a Style – in my example in the prior post, we need to drag around the ListBoxItem container, not just the content.  So I showed an alternative syntax to apply the same behavior:

    <ListBox.ItemContainerStyle>

        <Style TargetType="ListBoxItem">

            <Setter Property="julmar:DragPositionBehavior.IsEnabled" Value="True" />


Here, the behavior is being applied by setting the IsEnabled attached property onto the ListBoxItem.  Here’s the implementation for that:

public static DependencyProperty IsEnabledProperty =

    DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
        typeof(DragPositionBehavior),

        new FrameworkPropertyMetadata(false, OnIsEnabledChanged));

 

public static bool GetIsEnabled(DependencyObject uie)

{

    return (bool)uie.GetValue(IsEnabledProperty);

}

 

public static void SetIsEnabled(DependencyObject uie, bool value)

{

    uie.SetValue(IsEnabledProperty, value);

}


This is a boilerplate example of an attached property – nothing to see here.  The magic happens in the PropertyChange callback:

private static void OnIsEnabledChanged(DependencyObject dpo,

                                       DependencyPropertyChangedEventArgs e)

{

    UIElement uie = dpo as UIElement;

    if (uie != null)

    {

        var behColl = Interaction.GetBehaviors(uie);

        var existingBehavior = behColl.FirstOrDefault(b => b.GetType() ==
              typeof(DragPositionBehavior)) as DragPositionBehavior;

        if ((bool)e.NewValue == false && existingBehavior != null)

        {

            behColl.Remove(existingBehavior);

        }

        else if ((bool)e.NewValue == true && existingBehavior == null)

        {

            behColl.Add(new DragPositionBehavior());

        }

    }

}


Let’s break this down a little.  When we have the IsEnabled property set onto an element, first we verify it’s a UIElement (we cannot drag it on anything that isn’t because the mouse events are defined at this level).  Next, we check the behaviors collection on that element – if an existing behavior is there and we are setting the property to “false”, then we remove the existing behavior from the collection.  If there is no behavior, and we are setting the property to “true”, then we add a new DragPositionBehavior instance to the collection here.  This, in effect, is exactly what the first block of XAML is doing, and it’s what we do as well here in code – so the Style setter works as expected.

This isn’t really a trick – I’m sure others have thought of it as well, but it’s a useful thing to add into your behaviors so they can be universally used, both by Blend as well as by developers directly wanting to apply it in places where Blend cannot today.

Friday, February 05, 2010 5:01:51 PM (Central Standard Time, UTC-06:00)  #    Comments [2] -
.NET | MVVM | WPF

In this post, we will look at the IUIVisualizer, and bring together some of the concepts we’ve talked about already through a new sample – a simple picture viewer:

image

The application grabs all the images from the user’s photo folder and then displays each one onto the surface of a corkboard.  You can change the properties of an image, remove an image or add additional images.  It’s not designed to be a true image application ala photoSuru, it’s really more of a sample of MVVM practices with the helper library.  Here’s some of the coding examples present in the sample:

  • It registers a ISelectFile service and implements it as an OpenFileDialog.
  • It displays a “Picture Properties” dialog using the IUIVisualizer service.
  • It maps mouse DoubleClick on an image into a command in the ViewModel to display the properties.
  • It provides drag support through a behavior on the style.

Let’s look at this four features in particular.  Download the sample from here:

PictureViewer

Open the project in Visual Studio 2008 SP1, it should build and run without any issues.  The project structure is pretty much like all the other samples I’ve blogged about – I’m trying to keep to a consistent model:

image

Service Registration

If you look at the App.xaml.cs code behind, you’ll find the registration work being done in the constructor:

public App()

{

    // Register the typical services (UI, Error, etc.) for this application.

    ViewModel.RegisterKnownServiceTypes();

 

    // Register the file selector service.

    ViewModel.ServiceProvider.Add(typeof(ISelectFile), new OpenFileDialogSelector());

 

    // Register the UI dialogs.

    var uiVisualizer = ViewModel.ServiceProvider.Resolve<IUIVisualizer>();

        uiVisualizer.Register("ShowElementProperties", typeof(PropertyWindow));

}


First, note that it registers the standard services – that’s something I always do, even if I don’t anticipate needing them all, it doesn’t hurt to have them there. Next, it adds the file selector service by calling ServiceProvider.Add on the ViewModel class.  The interface is defined as a single method:

namespace PictureViewer.Interfaces

{

    public interface ISelectFile

    {

        string SelectFile(string fileFilters);

    }

}


The registration ties this interface to an implementation that displays the OpenFileDialog, for testing purposes, that would be replaced with a minimum of two implementations: one that returns null/empty and one that returns a valid filename to test both cases.

The final line in the app.xaml.cs file registers a UI dialog to display the properties of the image.  This is done through the IUIVisualizer interface which is defined in the helper library:

namespace JulMar.Windows.Interfaces

{

    public interface IUIVisualizer

    {

        void Register(string key, Type winType);

        bool Unregister(string key);

        bool Show(string key, object state, bool setOwner,

                  EventHandler<UICompletedEventArgs> completedProc);

        bool? ShowDialog(string key, object state);

    }

}


Notice the Register and Unregister methods take a string defined as a “key”.  This is the key that invokers will use to display the UI visually; I often use the typename of the View, but you can use any string here as long as you are consistent in registration vs. invocation.  In this sample, I’ve used the key “ShowElementProperties” – we’ll see in a moment how it is displayed.  The second parameter for the Register method takes the Type to display.  The type must be a WPF Window-derived type (i.e. NavigationWindow or Window) and will represent the View in our MVVM pattern.

Displaying a UI with IUIVisualizer

In the PictureViewModel type, there is an ICommand that is used to drive the Property window:

/// <summary>

/// Command to show the image properties.

/// </summary>

public ICommand ShowPropertiesCommand { get; private set; }


The default constructor fills that in with a DelegatingCommand to jump to a method of the ViewModel:

public PictureViewModel()

{

    _picture = new PictureInfo();

    ShowPropertiesCommand = new DelegatingCommand(ShowProperties);

    SelectNewImageFile = new DelegatingCommand(OnSelectNewFile);

    RemovePicture = new DelegatingCommand(

                  () => SendMessage(MainViewModel.RemovePictureMessage, this));

}

 

/// <summary>

/// Display the UI associated with this picture

/// </summary>

internal void ShowProperties()

{

    var uiVisualizer = Resolve<IUIVisualizer>();

    if (uiVisualizer != null)

    {

        uiVisualizer.ShowDialog("ShowElementProperties", this);

    }

}


The handler method is marked as internal because the MainViewModel forwards it’s own command to this same method handler (from the menu and toolbar).  Notice that the method first gets the IUIVisualizer service; you must use the same service instance where you registered the UI view.  Next, it calls ShowDialog to display a modal view.  It takes two parameters – the view key, and the view model.

A modal view is one that forces the user to interact and dismiss the dialog before they can continue working with the other elements in the application.  It is what, as an example, applications often use for Options dialogs.  ShowDialog will display the View associated with the given string key (“ShowElementProperties”).  The second parameter is the ViewModel you want to associate to it – in this case we are passing the associated picture we want to work with.  The dialog is then displayed and allows the user to edit the picture properties:

image

The XAML code for this view is contained in the PropertyWindow.xaml file – it has a couple of interesting elements to it which you will see when you interact with this dialog:

1. Watermarked Text display: if you remove the title, it will display some grayed out text in it’s place “Enter the Title Here”:

image

2. Numeric TextBox:  if you move your mouse cursor over the X/Y/Width/Height boxes you will see a sizing arrow that allows you to drag and change the values without typing.  You can also double-click to change the values and it enforces numeric text box behavior.

image

Both of these are accomplished with Blend Behaviors. There are plenty of resources on the web about these so I won’t go into detail on their creation – check the library source code if you want to see how they work, but using them involves taking a dependency on two assemblies:

  1. System.Windows.Interactivity.dll
  2. JulMar.Wpf.Behaviors.dll

Both of these are included in the Dependencies folder.  The first comes from the Blend SDK and is freely redistributable with your project.  To use them, you add the behavior to the visual element in question, for example, the watermarked textbox behavior gets applied like this:

<TextBox Text="{Binding Title}">

    <Interactivity:Interaction.Behaviors>

        <julmar:WatermarkTextBoxBehavior Text="Enter the Title Here"/>

    </Interactivity:Interaction.Behaviors>

    <TextBox.Style>

        <Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">

            <Setter Property="FontStyle" Value="Normal" />

            <Style.Triggers>

                <Trigger Property="julmar:WatermarkTextBoxBehavior.IsWatermarked"

                        Value="True">

                    <Setter Property="FontStyle" Value="Italic" />

                    <Setter Property="Foreground" Value="LightGray" />

                </Trigger>

            </Style.Triggers>

        </Style>

    </TextBox.Style>

</TextBox>


I’ve also applied a Trigger to change the font/colors when the TextBox is watermarked.

The numeric behavior looks like this:

<TextBox Grid.Row="5" Text="{Binding Width, UpdateSourceTrigger=PropertyChanged}">

    <Interactivity:Interaction.Behaviors>

        <julmar:NumericTextBoxBehavior AllowMouseDrag="True" />

    </Interactivity:Interaction.Behaviors>

</TextBox>


Notice that I’ve changed the Binding.UpdateSourceTrigger to be PropertyChanged – this is so the dragging effect works properly and updates the value in the underlying view model.

Ways to invoke commands in the view

So let’s look now at how we get the command executed.  Switching to the MainWindow.xaml you will find three places where the Show Properties command is wired up.

First, it can be invoked using a keyboard accelerator. This requires using a BindableCommand from the library, placing it into resources and then binding against that.  The command we will be executing is the one on the MainViewModel so it requires the actual picture element as a parameter:

<Window.Resources>

    <julmar:BindableCommand x:Key="propsCommand" Command="{Binding ShowPropertiesCommand}"

                           CommandParameter="{Binding SelectedPicture}" />

</Window.Resources>

 

<Window.InputBindings>

    <KeyBinding Key="r" Modifiers="Ctrl+Alt" Command="{StaticResource propsCommand}" />

</Window.InputBindings>


The MainViewModel simply forwards this command onto the PictureViewModel using a typed DelegatingCommand:

ShowPropertiesCommand = new DelegatingCommand<PictureViewModel>(

                    p => p.ShowProperties(), p => p != null);


Next, we can invoke the command using the menu and toolbar:

    <MenuItem Header="_Edit">

        <MenuItem Header="Add _New Picture" Command="{Binding AddNewCommand}" />

        <MenuItem Header="_Remove Picture" Command="{Binding RemoveCommand}"

                  CommandParameter="{Binding SelectedPicture}" />

        <Separator />

        <MenuItem Header="P_roperties" Command="{Binding ShowPropertiesCommand}"

                  CommandParameter="{Binding SelectedPicture}" />

    </MenuItem>

 

   ...

 

<ToolBar DockPanel.Dock="Top">

        <Button ToolTip="Add New Picture" Command="{Binding AddNewCommand}"

                Content="+" FontWeight="Bold" />

        <Button ToolTip="Remove Picture" Command="{Binding RemoveCommand}"

            CommandParameter="{Binding SelectedPicture}" Content="-" FontWeight="Bold" />

        <Button ToolTip="Properties" Command="{Binding ShowPropertiesCommand}"

            CommandParameter="{Binding SelectedPicture}" />

   ...

 

Note that here we are also binding to the MainViewModel command – so we must supply the parameter using the CommandParameter.  The final invocation place is when you double-click on the picture itself.  This is done a little differently if you’ve not done much WPF work. 

A quick segway – View code behind vs. View Models

First, the display of images is actually housed in a ListBox.  It turns out that anytime you need to display multiple things grouped somehow, and allow the user to select one or more of those things, a ListBox is almost always the way to go.  WPF allows us to customize the visuals however we like, so here the panel has been replaced with a Canvas (allowing pixel positioning), and each item is drawn as a DataTemplate.  The template decides how to render each item in the ListBox – the PictureViewModel in this case.  In the sample, it is rendering an image and an optional TextBlock that is turned on and off through a property (and can be changed through the tool bar).  I encourage you to look at the code to see how all that is done. 

One of the core things necessary in MVVM is the ability to interact with visuals and then sometimes push notifications of that interaction back to the view model.  I say “sometimes” because it’s perfectly acceptable to place code into the code behind for the XAML as well. Where you put the logic depends on whether it is view-specific and whether you want to test it independently of the view.  If it’s not view specific OR you want to test it, then move it into the view model.  An example of something that we probably don’t care about is closing the application – I’ve wired it up to a command here just to show that you can, but it’s completely unnecessary to do that.  The view model isn’t doing any closing logic, so it would be fine to wire a handler into the MainWindow.xaml.cs and just call “this.Close()” in there.

Ok, so back to the double-click implementation.  In the DataTemplate assigned to the ListBox.ItemTemplate property you will find the definition for the image itself:

<Image x:Name="imageHolder" Width="{Binding Width}" Height="{Binding Height}"

      Source="{Binding Image}" Stretch="Fill"

       HorizontalAlignment="Center" VerticalAlignment="Center">

    <Interactivity:Interaction.Triggers>

        <julmar:DoubleClickTrigger>

            <julmar:InvokeCommand Command="{Binding ShowPropertiesCommand}" />

        </julmar:DoubleClickTrigger>

    </Interactivity:Interaction.Triggers>

</Image>


Note the use of the Interaction.Triggers tag – this is also part of the Blend behavior implementation.  In this case, we are triggering off something (property change, event, etc.) and then performance some action.  In the JulMar.Wpf.Behaviors assembly you will find a whole bunch of triggers, behaviors and actions.  In this case, I am using the DoubleClickTrigger which monitors for a quick double tap of the left mouse button.  When that happens, it runs the list of actions associated with it – in this case, it invokes the ShowPropertiesCommand.  Now, here we are defining the trigger behavior on the UI that is bound to an actual PictureViewModel (note the property bindings on the image and you will see that I’m telling you the truth!) So here the command being invoked is the PictureViewModel command – so no parameter is necessary.

Drag/Position Behavior

The last thing I want to point out is the dragging behavior.  This is also done through a Blend behavior, but it is being applied in a slightly different way: through a Style. 

<ListBox.ItemContainerStyle>

    <Style TargetType="ListBoxItem">

        <Setter Property="julmar:DragPositionBehavior.IsEnabled" Value="True" />

        <Setter Property="Canvas.Left" Value="{Binding X, Mode=TwoWay}" />

        <Setter Property="Canvas.Top" Value="{Binding Y, Mode=TwoWay}" />

        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />

...

Now, for those who have used Blend behaviors a lot, you may now that it is currently not possible to apply behaviors through Styles.  This is a restriction of the Attached Property definition being used – the collection cannot be associated on a style.  This is a very unfortunate problem because it makes my scenario very hard: I want to drag and reposition these items around through the mouse.  If I put the behavior onto the DataTemplate then I move the content but not the item container itself (the thing that provides selection and focus rendering)  So I would end up with a very weird visualization where you click on an item and the focus rectangle is drawn in a completely different place than the item itself!

So, in my set of behaviors, many of them allow you to setup the behavior both through Blend and through Style setters (or directly on an element without the full Blend syntax).  I do this by adding an attached property onto the behavior class and then injecting my behavior into the element where the attached property is set.  I’ll show this in a future blog post to give an example for those who’d like to do the same for their own behaviors.

Another question I’ve fielded is why did I even create this behavior at all when the Blend sample already exists to do this?  Well, the short answer is because I had a specific goal in mind here – this behavior knows about Canvas panels.  If the behavior is attached to an element in a Canvas, it changes the position by changing the Canvas.Left and Canvas.Top properties.  If not, it uses a RenderTransform.  The supplied blend sample only uses RenderTransform (at least when I last looked at it).

That about covers it, if you have any questions or comments, then contact me!

Friday, February 05, 2010 4:43:16 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | MVVM | WPF
# Monday, February 01, 2010

In this post, I will go over the simple message visualizers available in the MVVM Helpers toolkit.  Essentially the idea is that it is fairly common to want to display a simple message from the ViewModel to the user.  Since the VM is supposed to be testable, we encapsulate this ability into four services, three of which I’ll focus on here:

IMessageVisualizer Displays a title + message to the user and allows them to dismiss it through a set of user-defined buttons.  The button used to dismiss the dialog is returned as the result.
IErrorVisualizer Displays a title + message to the user to report an error.  The only button displayed is OK, and the visualizer returns true/false.
INotificationVisualizer Used to manage some short operation that will halt the UI briefly.
IUIVisualizer Displays a custom modal or modaless UI to the user with an associated ViewModel to drive it.


To demonstrate the first three visualizer types, we’ll build a very simple MVVM application to display messages.  I start with the project template and remove all the ViewModel and View code to have a blank solution.  Each of the three visualizers we are going to look at take a string Title and Message as their parameters – we’ll drive it from a unique command for each.  To start with, let’s define a simple data structure that wraps an ICommand and a textual title:

/// <summary>

/// Simple command + title text

/// </summary>

public class TitledCommand

{

    /// <summary>

    /// Title to display

    /// </summary>

    public string Title { get; private set; }

 

    /// <summary>

    /// Command to execute

    /// </summary>

    public ICommand Command { get; private set; }

 

    /// <summary>

    /// Constructor

    /// </summary>

    /// <param name="title"></param>

    /// <param name="cmd"></param>

    public TitledCommand(string title, ICommand cmd)

    {

        Title = title;

        Command = cmd;

    }

}


Next, in the MainViewModel.cs file, we need a Title string property – this will be the title for each of the visualziations.  It’s just a simple field-backed INPC property, we’ll bind it to something in the view:

/// <summary>

/// Main View Model

/// </summary>

public class MainViewModel : ViewModel

{

    private string _title;

 

    /// <summary>

    /// Title for visualizations

    /// </summary>

    public string Title

    {

        get { return _title; }

        set { _title = value; OnPropertyChanged("Title"); }

    }

 

}


Now we can create a collection of the TitledCommand objects and display them to the user for execution.  We will place this collection into the MainViewModel.cs.  Let’s populate it with a set of delegating commands for each type of visualization we want to create.  We will use the DelegatingCommand<T> version which allows us to type the parameter being passed.  We will assume the inbound parameter is always the message to display and there a string:

/// <summary>

/// Main View Model

/// </summary>

public class MainViewModel : ViewModel

{

    ...

    /// <summary>

    /// Visualization Command list

    /// </summary>

    public IList<TitledCommand> VisualizationCommands { get; private set; }

 

    /// <summary>

    /// Constructor

    /// </summary>

    public MainViewModel()

    {

        VisualizationCommands = new List<TitledCommand>

        {

            new TitledCommand("Show Message", new DelegatingCommand<string>(OnShowMessage,

                s => !string.IsNullOrEmpty(Title) && !string.IsNullOrEmpty(s))),

            new TitledCommand("Show Error", new DelegatingCommand<string>(OnShowError,

                s => !string.IsNullOrEmpty(Title) && !string.IsNullOrEmpty(s))),       

            new TitledCommand("Show Notification",

                new DelegatingCommand<string>(OnShowNotification,

                s => !string.IsNullOrEmpty(Title))),

        };

    }

}


The CanExecute handler for each of them will test the Title property – ensure there is a value there, and the inbound parameter (the Message) and make sure there is a value there as well.

IMessageVisualizer

The IMessageVisualizer is used to show a simple message to the user – it takes a title, message and an enumeration to decide which buttons to display.  The default implementation of the service displays a MessageBox.  

image

The buttons you can display include:

    public enum MessageButtons

    {

        OK = 0,

        OKCancel = 1,

        YesNoCancel = 3,

        YesNo = 4

    }


The result from the service is which button was used to dismiss the dialog:

    public enum MessageResult

    {

        None = 0,

        OK = 1,

        Cancel = 2,

        Yes = 6,

        No = 7

    }


Using the visualizer is very easy – request the service from the service locator using the Resolve method (this requires you derive from the JulMar.Windows.Mvvm.ViewModel base class, or hit the service locator using the static property):

    private void OnShowMessage(string message)

    {

        var messageVisualizer = Resolve<IMessageVisualizer>();

        if (messageVisualizer != null)

        {

            Result = Enum.GetName(typeof (MessageResult),

               messageVisualizer.Show(Title, message, MessageButtons.YesNoCancel));

        }

    }


Notice that I test to ensure the visualizer is available – remember that services can be replaced or removed – I might do this in my unit tests for example (I actually mock the interface rather than replace it, but you get the point – test to make sure it’s there).

We want to see the result, so I take the resulting enum and convert it to a string and assign it to a new Result property on the ViewModel.  This, like Title, is just a field-backed string that does a property change notification.

IErrorVisualizer

The error visualizer is for cases where you want to display an error dialog to the user with a title and message.  The default implementation displays a MessageBox with an OK button

image

It returns a boolean response indicating that the user clicked the OK button (versus dismissing using the Close “X” button).   It has a similar interface to the message visualizer:

    private void OnShowError(string errorMessage)

    {

        var errorVisualizer = Resolve<IErrorVisualizer>();

        if (errorVisualizer != null)

        {

            Result = errorVisualizer.Show(Title, errorMessage).ToString();

        }

    }


We will assign the boolean result to the string Result property as well.

INotificationVisualizer

This visualizer is for cases where you are doing something in the ViewModel logic, on the UI thread that takes a moment to process.  Sorting a list, or searching an in-memory list might be an example.  True long-running operations should always be on a separate thread and use properties or the message mediator to coordinate with the UI thread.  That said, there are times when you want to do the logic inline with the request and you know it’s going to take a second or two to process it.  Enter the INotificationVisualizer.  It takes the same title and message as it’s cousin visualizers but the default implementation does not use them – instead, the default implementation simply changes the cursor to an hourglass (the defacto standard for “please wait”).  This is a service that I often replace with a custom visualzation – a progress bar, thumbar progress on Windows 7, or even a dialog overlay.  Invoking it is simple:

    private void OnShowNotification(string message)

    {

        var notifyVisual = Resolve<INotificationVisualizer>();

        if (notifyVisual != null)

        {

            using (notifyVisual.BeginWait(Title, message))

            {

                // Sleep for 2sec, pretending to work

                Thread.Sleep(2000);

            }

        }

    }


The BeginWait() method kicks off the notification visual (hourglass cursor in this case).  It returns a disposable object that you invoke Dispose on to return to the normal cursor.  Again, let me stress this is not optimal for a true long-running operation – this locks the UI up until the thread returns so only use this for very short operations.

Creating the View

The View for this application will be simple – let’s use an ItemsControl to generate a button for each of the exposed commands, two TextBoxes to hold the Title and Message, and then a TextBlock for the result, here’s what I want it to look like:

image

I’ll let you go through the XAML – it’s straightforward and should be pretty easy to follow.  The only new thing might be that we’ll set focus to the first focusable element using the FirstFocusedElement markup extension:

<Window x:Class="ServicesTest.Views.MainWindow"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:julmar="http://www.julmar.com/wpfhelpers"

   xmlns:ViewModels="clr-namespace:ServicesTest.ViewModels"

   Title="Notification Visualizer Test" Height="300" Width="400" Background="LightYellow"

   WindowStartupLocation="CenterScreen"

   FocusManager.FocusedElement="{julmar:FirstFocusedElement}"

   DataContext="{julmar:ViewModelCreator {x:Type ViewModels:MainViewModel}}">

    <Grid Margin="5">

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto" />

            <RowDefinition Height="Auto" />

            <RowDefinition Height="Auto" />

            <RowDefinition />

        </Grid.RowDefinitions>

 

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="Auto" />

            <ColumnDefinition />

        </Grid.ColumnDefinitions>

 

        <Label Grid.Column="0" Grid.Row="0" Content="Title:" />

        <TextBox Grid.Column="1" Grid.Row="0" Margin="5,2" Text="{Binding Title}" />

 

        <Label Grid.Column="0" Grid.Row="1" Content="Message:" />

        <TextBox x:Name="tbMessage" Grid.Column="1" Grid.Row="1" Margin="5,2" />

 

        <ItemsControl Grid.Row="2" Grid.ColumnSpan="2" Margin="10"

                    ItemsSource="{Binding VisualizationCommands}">

            <ItemsControl.ItemTemplate>

                <DataTemplate>

                    <Button Margin="5" Content="{Binding Title}"

                       Command="{Binding Command}"

                       CommandParameter="{Binding ElementName=tbMessage, Path=Text}" />

                </DataTemplate>

            </ItemsControl.ItemTemplate>

        </ItemsControl>

 

        <TextBlock FontSize="24pt" Grid.ColumnSpan="2" Grid.Row="3"

              HorizontalAlignment="Center" VerticalAlignment="Center"

              Text="{Binding Result, FallbackValue=None}" />

 

    </Grid>

</Window>


That should do it – if you’d like to just download the project and play with it, it’s available here: VisualizerTest.zip.  In the next post we’ll take a look at the grand-daddy of the message visualizers in the MVVM Helper toolkit: the IUIVisualizer!

Monday, February 01, 2010 9:59:35 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | MVVM | WPF
# Friday, January 29, 2010

A question I got recently was how to manage Radio Buttons with bindings – in this instance, the sample code was trying to map a single value to a set of Radio Buttons based on an enumeration set.  The original implementation was using a Value Converter to compare the “bound” value with the enumeration value expected for that radio button choice – if it was equal then the converter returned true, otherwise false.  Something like this:

<RadioButton Content="Blue"

     IsChecked="{Binding SelectedValue,

             Converter={StaticResource CheckValueAgainst}, ConverterParameter=Blue"/>

<RadioButton Content="Red"

     IsChecked="{Binding SelectedValue,

             Converter={StaticResource CheckValueAgainst}, ConverterParameter=Red"/>

<RadioButton Content="Yellow"

     IsChecked="{Binding SelectedValue,

             Converter={StaticResource CheckValueAgainst}, ConverterParameter=Yellow"/>


Initially this seemed to work, but as you changed the current enumeration value, the radio buttons would “lose” the binding – and after a few times you would end up with none of them selected.

Ultimately, this problem is really an expected behavior from WPF – when a set of Radio Buttons are placed together, they act as a group – where only one is expected to be checked and all the others are unchecked.  This happens because the selected Radio Button itself tells the group to uncheck all the others.  This has the effect of replacing the binding value for IsChecked with a local value of false.  See the problem?  Eventually, all of the buttons in the group have their value replaced and so we end up with all of them unchecked.  The solution was very easy – put each one into a separate group by defining a unique GroupName for each Radio Button. 

<RadioButton GroupName="gBlue" Content="Blue"

     IsChecked="{Binding SelectedValue,

             Converter={StaticResource CheckValueAgainst}, ConverterParameter=Blue"/>

<RadioButton GroupName="gRed" Content="Red"

     IsChecked="{Binding SelectedValue,

             Converter={StaticResource CheckValueAgainst}, ConverterParameter=Red"/>

<RadioButton GroupName="gYellow" Content="Yellow"

     IsChecked="{Binding SelectedValue,

             Converter={StaticResource CheckValueAgainst}, ConverterParameter=Yellow"/>


This solves the problem and required no real code changes, but of course, I didn’t want to stop there – I just had to whip up a quick MVVM version to show how I’d do this if I were responsible for the application!

Sample Application Description

Our goal will be to display a list of children and their details to track their favorite games.  I started by sketching it out with SketchFlow to get a sense of what I wanted to visually create:

image

The top list is a ListBox, showing each child and the bottom pane shows the details.  Note the RadioButtons used to represent Gender and Favorite Game.  Our goal will be to use a ListBox there as well – showing the list of Radio Buttons and bound to a ViewModel collection of data.  As a secondary goal, we want to separate the RadioButton value from the text displayed

It turns out that anytime you need to display a list or sequence of something, a ListBox (or ItemsControl if you don’t need the selection capability) is almost always a good choice.  Let’s see if we can make it work here with the MVVM pattern.

Now that I have an idea of what I want to build, I created a blank Windows WPF application and added the JulMar MVVM Helper library and created the directory structure I prefer (Views, ViewModels and Dependencies).  I moved the Window1.xaml and corresponding code behind into the Views folder and renamed it MainWindow.xaml.  This also required I adjust App.xaml to point to the correct StartupUri (Views\MainWindow.xaml).  As a quick start you could also just use the JulMar MVVM project template and delete the XAML and view models.  Here’s what I ended up with in the solution:

GamePrefSolution

Now, we’re ready to begin our data modeling.  In this case, I don’t have a real data model – I’m not going to store or manage any of the children in a persistent way so I’m just going to define the View Model definitions for the children and collection.  We’ll start with the child definition.  I created a class to manage the properties of the child I want to display: Name, Dob, Gender, and FavoriteGame.  For the Gender and Favorite Game, I will use Enums to model those as a known list.  I could have used a Boolean for Gender as well, but this serves my underlying goal so we’ll go with an enumeration.  Here’s what I came up with:

/// <summary>

/// Gender flag

/// </summary>

public enum Gender

{

    Male, Female, Unknown

}

 

/// <summary>

/// Game types

/// </summary>

public enum GameType

{

    Webkinz,

    Playdoh,

    PbsKids,

    Wii

}

 

/// <summary>

/// ViewModel to represent a single child.

/// </summary>

public class ChildViewModel : SimpleViewModel

{

    private string _name;

    private Gender _gender;

    private DateTime _dob;

    private GameType _favoriteGame;

 

    /// <summary>

    /// Name

    /// </summary>

    public string Name

    {

        get { return _name; }

        set { _name = value; OnPropertyChanged("Name","Details"); }

    }

 

    /// <summary>

    /// Gender of child

    /// </summary>

    public Gender Gender

    {

        get { return _gender; }

        set { _gender = value; OnPropertyChanged("Gender","Details"); }

    }

 

    /// <summary>

    /// Date of birth

    /// </summary>

    public DateTime Dob

    {

        get { return _dob; }

        set { _dob = value; OnPropertyChanged("Dob","Details"); }

    }

 

    /// <summary>

    /// Game they like to play

    /// </summary>

    public GameType FavoriteGame

    {

        get { return _favoriteGame; }

        set { _favoriteGame = value; OnPropertyChanged("FavoriteGame","Details"); }

    }

 

    /// <summary>

    /// Returns textual representation of child.

    /// </summary>

    /// <returns></returns>

    public string Details

    {

       get

       {

           return string.Format("{0} is a {1}, was born on {2:D} and loves to play {3}",

                        Name, Gender, Dob, FavoriteGame);

       }

    }

}


Pretty standard stuff – we have field backed properties and raise the PropertyChange notification on each one.  For this case I don’t think we’ll need any additional services so I derive from the JulMar.Windows.Mvvm.SimpleViewModel class which just provides INotifyPropertyChanged support.  The one extra thing I’ve added here is a Details property which is a concatenation of all the other properties – we’ll use this to verify that the data binding is working properly as a secondary display of the same data.  We need to be sure to include that property invalidation when any of the other properties it depends on changes.  The OnPropertyChanged implementation allows you to pass multiple strings for this very purpose.

Moving on, I want to display the generated Enumerations above as a list, so we need a way to encapsulate a value and the text used to represent the value together.  If I were using .NET4 I could use the uber-cool new Tuple<K,V> class but I want to target .NET 3.5 here so we’ll define a new ValueAndText class to hold this:

/// <summary>

/// This class wraps a value and string together.

/// </summary>

/// <typeparam name="T">Type of value</typeparam>

public class ValueAndText<T>

{

    /// <summary>

    /// Value to bind to

    /// </summary>

    public T Value { get; private set; }

 

    /// <summary>

    /// Text string to present

    /// </summary>

    public string Text { get; private set; }

 

    /// <summary>

    /// Constructor

    /// </summary>

    /// <param name="value"></param>

    /// <param name="text"></param>

    public ValueAndText(T value, string text)

    {

        Value = value;

        Text = text;

    }

}


Now, let’s turn to the actual glue – the MainViewModel that pulls it all together. 

/// <summary>

/// Main View Model that connects it all together.

/// </summary>

public class MainViewModel : SimpleViewModel

{

}

 

Let’s use a SimpleViewModel here as well.  The first property we need is a collection for the children – we won’t be modifying the list (i.e. no adding or deleting) so the backing storage can just be a List<T>, as part of the constructor we’ll populate it with some sample data:

/// <summary>

/// Collection of children

/// </summary>

public IList<ChildViewModel> Children { get; private set; }

       

/// <summary>

/// Constructor

/// </summary>

public MainViewModel()

{

   // Fill with sample data.

   Children = new List<ChildViewModel>

   {

      new ChildViewModel

      {

         Name = "Jonathan",

         Dob = new DateTime(2006, 3, 14),

         FavoriteGame = GameType.PbsKids,

         Gender = Gender.Male

      },

      ...

  };

}

  

Next, we want a single child to be the “current” selected child.  This is just a property of type ChildViewModel exposed by the parent view model.

private ChildViewModel _currentChild;

 

/// <summary>

/// The current (and only for now) child

/// </summary>

public ChildViewModel CurrentChild

{

   get { return _currentChild; }

   set

   {

      if (_currentChild != value)

      {

         _currentChild = value;

         OnPropertyChanged("CurrentChild");

      }

   }

}


We’ll also set the first child as the current child in the MainViewModel constructor after we populate the collection:

// Set the first child as selected.

CurrentChild = Children[0];


We want to have a bindable list of the gender values (and text) and a bindable list of the game types.  In this case, let’s take advantage of the ability to bind to any IEnumerable data source and just generate the list using the C# 2.0 iterator support:

/// <summary>

/// Gets the gender values

/// </summary>

public IEnumerable<ValueAndText<Gender>> GenderValues

{

    get

    {

        yield return new ValueAndText<Gender>(Gender.Male, "Boy");

        yield return new ValueAndText<Gender>(Gender.Female, "Girl");

    }

}

 

/// <summary>

/// Gets the game types

/// </summary>

public IEnumerable<ValueAndText<GameType>> GameTypes

{

    get

    {

        yield return new ValueAndText<GameType>(GameType.Webkinz,

                                             "WebKinz (http://www.webkinz.com)");

        yield return new ValueAndText<GameType>(GameType.Playdoh, "Loves Playdoh");

        yield return new ValueAndText<GameType>(GameType.PbsKids,

                                             "PBS Kids (http://www.pbskids.com)");

        yield return new ValueAndText<GameType>(GameType.Wii, "Wii and other console");

    }

}


That should do it for our logic and data requirements, now let’s turn to the visualization for it.  We have the following properties defined on the MainViewModel to drive the view:

Children Collection of PersonViewModel objects with child details.
CurrentChild Current (selected) child
GenderValues Collection of ValueAndText objects to select child gender
GameTypes Collection of ValueAndText objects to select the favorite game



Using the SketchFlow prototype as an example, we’ll start with a DockPanel as the root element – locking a StatusBar at the bottom, a ListBox at the top and a Border (which will contain our details pane) as the fill content.  We’ll use the JulMar ViewModelCreator markup extension to tie this to the MainViewModel, and let’s push the initial focus into the children ListBox using the FocusManager.FocusedElement attached property on the window.

<Window x:Class="RadioButtonBinding.Views.MainWindow"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:julmar="http://www.julmar.com/wpfhelpers"

   xmlns:ViewModels="clr-namespace:RadioButtonBinding.ViewModels"

   xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"

   DataContext="{julmar:ViewModelCreator {x:Type ViewModels:MainViewModel}}"

   FocusManager.FocusedElement="{Binding ElementName=lbChildren}"

   Title="Game Preference Tracker" Height="400" Width="500" Background="OldLace">

 

    <DockPanel>

 

        <!-- List of children we are tracking -->

        <ListBox x:Name="lbChildren" DockPanel.Dock="Top">

        </ListBox>

 

        <!-- StatusBar just to make sure two-way binding is working properly -->

        <StatusBar DockPanel.Dock="Bottom" BorderBrush="Black" BorderThickness="0,1,0,0">

        </StatusBar>

 

        <!-- Details pane -->

        <Border Margin="5" BorderBrush="LightGray" BorderThickness="1">

        </Border>

    </DockPanel>

</Window>


Next, let’s fill in the top ListBox details.  We need to populate it with the list of children – this is the Children property off our ViewModel, so we’ll bind the ItemsSource property to that collection.  Next, we’ll set the SelectedItem to the CurrentChild property – making sure to use a two-way binding:

<ListBox x:Name="lbChildren" DockPanel.Dock="Top" ItemsSource="{Binding Children}"

                SelectedItem="{Binding CurrentChild, Mode=TwoWay}" />


This will generate a list of items, but won’t have any decent visualization – so we’ll use a DataTemplate to give us a basic visual, at the same time, let’s replace the default panel with a WrapPanel so it looks more like our SketchFlow:

<ListBox x:Name="lbChildren" DockPanel.Dock="Top" ItemsSource="{Binding Children}"

        SelectedItem="{Binding CurrentChild, Mode=TwoWay}"

        ScrollViewer.HorizontalScrollBarVisibility="Disabled">

    <ListBox.ItemsPanel>

        <ItemsPanelTemplate>

            <WrapPanel />

        </ItemsPanelTemplate>

    </ListBox.ItemsPanel>

    <ListBox.ItemTemplate>

        <DataTemplate>

            <Border BorderBrush="DarkBlue" BorderThickness="2"

                    Background="SkyBlue" CornerRadius="5">

                <StackPanel Margin="10">

                    <TextBlock FontWeight="Bold" FontSize="12pt" Text="{Binding Name}" />

                    <TextBlock Text="{Binding FavoriteGame}" />

                </StackPanel>

            </Border>

        </DataTemplate>

    </ListBox.ItemTemplate>

</ListBox>


Now, let’s turn our attention to displaying the current child details.  Remember the properties we created on the ChildViewModel:

Name Their name
Gender Their gender – Male/Female
Dob The date of birth
Details The string with all the details for this child.


So let’s first use the details – we can bind a TextBlock in the StatusBar to the CurrentChild.Details property to display the selected child details:

<!-- StatusBar just to make sure two-way binding is working properly -->

<StatusBar DockPanel.Dock="Bottom" BorderBrush="Black" BorderThickness="0,1,0,0">

    <TextBlock Text="{Binding CurrentChild.Details}" TextWrapping="Wrap" />

</StatusBar>


Now, let’s turn our attention to the details – we’ll use a Grid to lay it out within the Border, the Name and Date Of Birth are pretty easy to just drop in a set of Labels and TextBox/DatePicker – we’ll need the WPF Toolkit for this.  We’ll drop in two ListBox elements for the Radio Button list.

<Border Margin="5" BorderBrush="LightGray" BorderThickness="1">

    <Grid>

        <Grid.Resources>

            <!-- Common style for header labels -->

            <Style TargetType="Label">

                <Setter Property="HorizontalAlignment" Value="Right" />

                <Setter Property="VerticalAlignment" Value="Top" />

                <Setter Property="FontWeight" Value="Bold" />

                <Setter Property="Margin" Value="5,2" />

            </Style>

        </Grid.Resources>

 

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="Auto" />

            <ColumnDefinition />

        </Grid.ColumnDefinitions>

 

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto" />

            <RowDefinition Height="Auto" />

            <RowDefinition Height="Auto" />

            <RowDefinition Height="Auto" />

        </Grid.RowDefinitions>

 

        <Label Grid.Row="0" Content="Name:" />

        <TextBox Grid.Row="0" Grid.Column="1" Margin="5,2"

             Text="{Binding CurrentChild.Name}" />

 

        <Label Grid.Row="1" Content="Gender:" />

        <ListBox Grid.Row="1" Grid.Column="1" />

 

        <Label Grid.Row="2" Content="Date Of Birth:" />

        <Controls:DatePicker Grid.Row="2" Grid.Column="1" Margin="5,2"

              SelectedDate="{Binding CurrentChild.Dob}" />

 

        <Label Grid.Row="3" Content="Favorite Game:" />

        <ListBox Grid.Row="3" Grid.Column="1" />

    </Grid>

</Border>


Let’s focus on the Gender list first – the same concepts will apply to the game list.  We have an IEnumerable list of ValueAndText objects – each object has a Value property (corresponding to the underlying enum value tracked in the ChildViewModel) and a Text property which is what we want displayed in the RadioButton choice.  First, let’s set it up so we get a list of RadioButtons – we can do this by changing the ControlTemplate for each item in the list itself – that is, change the ListBoxItem control template. 

As a bit of background, anytime you add an element to an ItemsControl (ListBox, ComboBox, TreeView, Menu, etc.) a special wrapper is internally created around your data to provide the special UI properties necessary to drive the functionality – things like focus, selection, mouse-over, etc. are all provided by this wrapper.  In the case of the ListBox, the created wrapper is a ListBoxItem class and we can control it’s properties by overriding the ItemContainerStyle on the ListBox itself.  So, to start off, we’ll create a new Style for the ListBox, set some basic properties and then override the ListBoxItem style inside that:

<Style x:Key="radioListBox" TargetType="ListBox"

       BasedOn="{StaticResource {x:Type ListBox}}">

    <Setter Property="BorderThickness" Value="0" />

    <Setter Property="Margin" Value="5" />

    <Setter Property="Background" Value="{x:Null}" />

    <Setter Property="ItemContainerStyle">

        <Setter.Value>

            <Style TargetType="ListBoxItem"

                   BasedOn="{StaticResource {x:Type ListBoxItem}}">

            </Style>

        </Setter.Value>

    </Setter>

</Style>


Since this is going to list a group of radio buttons, we’ll drop the border off the ListBox and the Background color as well so that our parent’s background shows through.  We’ll throw a Margin on there to give it a little spacing. Next, to change the visualization of the ListBoxItem, we’ll override it’s ControlTemplate (the thing that generates the visual tree for the item).  This, like all Controls in WPF, is done by overriding the Template property. What we want is put a Radio Button in there:

<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">

    <Setter Property="Template">

        <Setter.Value>

            <ControlTemplate TargetType="ListBoxItem">

               <RadioButton IsChecked="{TemplateBinding IsSelected}">

                  <ContentPresenter />

               </RadioButton>

            </ControlTemplate>

        </Setter.Value>

    </Setter>

</Style>


In order to get the IsChecked state properly setup, we’ll bind it to the ListBoxItem.IsSelected property – so if the item is selected according to the ListBox, then the Radio Button will be checked.  We also drop a ContentPresenter into the RadioButton so it displays whatever the data bound value is – this will provide for any DataTemplate visualization if one is present.  This will achieve the visualization we desire, but it won’t work properly as we interact with it.  The problem is that the Radio button will override this state when it is clicked – exactly the problem we had originally!

To fix this, let’s make the radio button invisible to the mouse and keyboard.. we can do this by setting the Focusable and IsHitTestable properties to false – however this makes them non-interactive and now we can’t select the ListBoxItem with the mouse.. so, let’s wrap it in something that is selectable – anything should work, so we’ll just throw it into a Grid.  Set the Grid.Background to transparent so you can click on it and we end up with:

<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">

    <Setter Property="Template">

        <Setter.Value>

            <ControlTemplate TargetType="ListBoxItem">

                <Grid Background="Transparent">

                    <RadioButton Focusable="False"

                      IsHitTestVisible="False" IsChecked="{TemplateBinding IsSelected}">

                        <ContentPresenter />

                    </RadioButton>

                </Grid>

            </ControlTemplate>

        </Setter.Value>

    </Setter>

</Style>


This does exactly what we want – clicking on the radio button changes the selection in the ListBox and, in turn, checks or unchecks the radio button in question.  Now, let’s wire it up to our data – remember we have a Value and Text.  We want to bind to the Value but display the Text.  It turns out the ListBox already has this feature backed in – there is a SelectedItem property we normally use, but there is also a SelectedValue property that makes the distinction between the item in the collection and the value used to select it.  There is also a DisplayMemberPath and SelectedValuePath property used for data binding purposes when generating the content from an ItemsSource supplied value.  Pulling these things together we can do this:

<ListBox Grid.Row="1" Grid.Column="1"

        Style="{StaticResource radioListBox}"

        DisplayMemberPath="Text"

        SelectedValuePath="Value"

        ItemsSource="{Binding GenderValues}"

        SelectedValue="{Binding CurrentChild.Gender}" />


Testing this, it works perfectly!  Since the DisplayMemberPath/SelectedValuePath are the same for the two lists, we can move that to our radioListBox style, leaving us with the two ListBox definitions being:

<ListBox Grid.Row="1" Grid.Column="1" Style="{StaticResource radioListBox}"

         ItemsSource="{Binding GenderValues}"

         SelectedValue="{Binding CurrentChild.Gender}" />

... 

<ListBox Grid.Row="3" Grid.Column="1" Style="{StaticResource radioListBox}"

         ItemsSource="{Binding GameTypes}"

         SelectedValue="{Binding CurrentChild.FavoriteGame}" />


And the completed application looks like:

image

You can download the completed project here: RadioButtonBinding Test

Friday, January 29, 2010 12:41:42 PM (Central Standard Time, UTC-06:00)  #    Comments [2] -
.NET | MVVM | WPF
# Thursday, January 28, 2010

The main project I’ve been working on the past few months has been a rRNA sequencing application.  It’s a joint project involving Microsoft Research and the University of Texas in Austin.  The goal being to produce lightning fast visualizations (nucleotide, 2D and 3D) with very large (100,000 sequence) data sets on WPF.  It’s been a big learning experience for me in many ways because the traditional mechanisms for dealing with things in WPF just flat out fail when we load big datasets and start scrolling them around.  So, we’ve had to invent data virtualization schemes, our own UI virtualization for scrolling, several custom controls and a variety of other elements to pull it off so far.  rCAT 4.0 (coming in March) is even more ambitious with editing support for the sequences!

All that said, our current effort is now online with full source code – it’s interesting stuff to browse through even if you aren’t into molecular biology – check it out at http://rcat.codeplex.com/

Here’s a nice screen shot showing some of the elements – dockable tabs and sidebar items, birds-eye viewer, taxonomy viewer and custom colorization of nucelotide data.  And it, of course, is all MVVM.  Fun stuff!

CATUI.Overview.Shrink

Thursday, January 28, 2010 2:58:46 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | MVVM | WPF

I know I said I was going to cover some services next, but I got a request last night to show how to rename TreeView nodes (ala Explorer) using the MVVM pattern in WPF.  The solution is quite easy and elegant and I thought I’d share it here.

First, the idea is we want to be able to double-click on the text portion of the TreeViewItem and have it allow us to type in a new name, replacing the current text.  This involves changing the visual template out (from a TextBlock to a TextBox) and then detecting that the edit is complete.

I started with the MVVM project template, creating the default File Explorer view.  The TreeView on the left is displaying folders – so I opened the DirectoryViewModel.cs that drives the data.

First, let’s add a property to indicate whether we are in “editing” mode or not.  This is a simple field-backed property that raises the PropertyChange notification:

/// <summary>

/// True/False whether we are changing the name of the directory

/// </summary>

public bool IsEditingName

{

   get { return _isEditingName; }

   set { _isEditingName = value; OnPropertyChanged("IsEditingName"); }

}


I also added the private field (_isEditingName) into the class.  Next, locate the Name property that is being used to display the name.  Here we need to add a setter that renames the directory.  We want it to be robust, so we do some upfront checks and make sure to catch any I/O exceptions that occur:

/// <summary>

/// Name of the directory

/// </summary>

public string Name

{

   get { return _data.Name; }

 

   // Code to rename directory

   set

   {

      string newValue = value;

      if (!string.IsNullOrEmpty(newValue))

      {

         // Remove any trailing backslash.

         string fullName = _data.FullName.TrimEnd(Path.DirectorySeparatorChar);

 

         // Determine the new directory name

         string directoryPath = fullName.Substring(0, fullName.Length - _data.Name.Length);

         if (!string.IsNullOrEmpty(directoryPath) && directoryPath != fullName)

         {

            string newFullName = Path.Combine(directoryPath, newValue);

            try

            {

               _data.MoveTo(newFullName);

            }

            catch (IOException ex)

            {

               var errorVisualizer = Resolve<IErrorVisualizer>();

               if (errorVisualizer != null)

               {

                  errorVisualizer.Show("Cannot rename directory", ex.Message);

               }

            }

         }

      }

      // Tell WPF the name has changed.  Note if the same control

      // is being used to display vs. edit then the

      // binding will need to force WPF3x to re-read the property value. 

      // This is done by using a RefreshValueConverter;

      // under .NET4 this won't be necessary.

      OnPropertyChanged("Name");

 

     // Flip off the editing bit

     IsEditingName = false;

  }

}


Notice how changes the editing flag at the end – we assume that once the rename has occurred we are out of editing mode.  Finally, we need a way to transition from “normal” to “edit” mode and back.  In the VM these kinds of things are driven with commands – so, let’s define an ICommand that takes us in and out of edit mode:

/// <summary>

/// Command used to switch to editing mode

/// </summary>

public ICommand SwitchToEditingMode { get; private set; }


And then finally initialize it in the default constructor – we also now need to chain to that constructor from the parameterized version since we always want this initialization to happen (you could also do the initialization in both, but I prefer this approach):

/// <summary>

/// Constructor for the marker directory.  This is used to detect an expansion.

/// </summary>

private DirectoryViewModel()

{

   // Command that switches us into editing mode.

   SwitchToEditingMode = new DelegatingCommand(

                 () => IsEditingName = !IsEditingName,

                 () => _data.FullName != _data.Name);

}

 

/// <summary>

/// Public constructor

/// </summary>

/// <param name="di">DirectoryInfo to pull information from</param>

public DirectoryViewModel(DirectoryInfo di) : this()

{

...

}


That’s all the code changes we need for this – now let’s switch to the View and see how we will wire this up!  Open the MainWindow.xaml file and look at the DataTemplate used by the TreeView.  All of our changes will go into this template. First, we need to add a TextBox into the template that sits in the same space as the TextBlock that displays the name.  Then we need some way to switch between these two elements – I use Visibility here, you could also swap out the entire template.  We’ll use a DataTrigger and drive it off our new IsEditingName property:

<HierarchicalDataTemplate x:Key="DirectoryTemplate" ItemsSource="{Binding Subdirectories}">

   <StackPanel Orientation="Horizontal">

      <Image Width="16" Height="16"

          Source="{Binding FullName, Converter={StaticResource iconConverter}}" />

      <Grid Margin="5,0">

         <TextBlock x:Name="tb" Text="{Binding Name}" />

         <!-- Editing text box -->

         <TextBox x:Name="etb" Visibility="Collapsed" MinWidth="100"

              Text="{Binding Name, UpdateSourceTrigger=LostFocus,

                     Converter={julmar:RefreshValueConverter}}" />

      </Grid>

   </StackPanel>

   <HierarchicalDataTemplate.Triggers>

      <DataTrigger Binding="{Binding IsSelected}" Value="True">

         <Setter TargetName="tb" Property="FontWeight" Value="Bold" />

      </DataTrigger>

      <!-- When editing mode is turned on, get rid of the TextBlock and

           make the TextBlock visible. -->

      <DataTrigger Binding="{Binding IsEditingName}" Value="True">

         <Setter TargetName="tb" Property="Visibility" Value="Collapsed" />

         <Setter TargetName="etb" Property="Visibility" Value="Visible" />

      </DataTrigger>

   </HierarchicalDataTemplate.Triggers>

</HierarchicalDataTemplate>

 

The other thing we need to do is set the TextBox binding (which also uses the Name property) to apply any changes when the control loses focus – that way we don’t rename as the user types!  This is done by changing the UpdateSourceTrigger on the binding to “LostFocus”. This happens to be the default setting for WPF – but not for Silverlight, so I tend to be deliberate when I want to ensure a specific behavior.  I’ve also added a converter onto the binding above – the RefreshValueConverter.  This is a no-op converter, but it forces WPF to re-read the property value after the setter is called, without it, the TextBox will have stale data if the rename fails.  Note that this is unnecessary in WPF4 which now always re-reads the property values automatically.  Since this targets WPF3.5, this converter will ensure proper behavior.

The final thing we need to do is somehow get in and out of editing mode.  We want this to happen when we double-click on the text element – so let’s add a JulMar behavior and action to the TextBlock:

<TextBlock x:Name="tb" Text="{Binding Name}">

   <Interactivity:Interaction.Triggers>

      <!-- DoubleClick activates editing mode -->

      <julmar:DoubleClickTrigger>

         <julmar:InvokeCommand Command="{Binding SwitchToEditingMode}" />

      </julmar:DoubleClickTrigger>

   </Interactivity:Interaction.Triggers>

</TextBlock>


This also requires you define the proper namespace on the Window element:

xmlns:Interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"


I’d also like to drop out of editing mode when you press ENTER in the TextBox. To accomplish this, let’s add an InputBinding to the TextBox for the ENTER key that invokes our SwitchToEditingMode command – in WPF 3.5 we need to go through a resource-based binding helper to get access to the ViewModel (which is our DataContext).  So, let’s defined a BindableCommand in the Grid resources (so we get the DirectoryViewModel as the DataContext) and then bind the input command to that:

<Grid.Resources>

<!-- Put here so it inherits the data context properly.  We want the command to execute on

     directory view model -->

   <julmar:BindableCommand x:Key="EditingModeCommand"

        Command="{Binding SwitchToEditingMode}" />

</Grid.Resources>

<TextBox x:Name="etb" Visibility="Collapsed" MinWidth="100"

   Text="{Binding Name, UpdateSourceTrigger=LostFocus,

           Converter={julmar:RefreshValueConverter}}">

   <!-- Pressing ENTER in the TextBox turns off editing mode. 

        Tab or clicking away will do the same thing -->

   <TextBox.InputBindings>

      <KeyBinding Key="Enter" Command="{StaticResource EditingModeCommand}" />

   </TextBox.InputBindings>

</TextBox>


And that’s it!  If you run the app and double-click on a directory name (except the root) you can rename it!

RenameTreeNodePic

Here’s the finished solution: RenameTreeNode.zip

Thursday, January 28, 2010 11:13:52 AM (Central Standard Time, UTC-06:00)  #    Comments [2] -
.NET | MVVM | WPF
# Friday, January 22, 2010

In the previous post, I provided a link to the project template you can use to start a new MVVM project using the JulMar MVVM library. Here's the two links in case you didn't get them before:

MVVM Helpers Distribution
Project Template

Copy the project template into your Visual Studio 2008 templates directory located off your user documents - mine is at %UserProfile%\Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual C#\Windows.

Ok, so once you have these installed, what can you do with them? Well, for starters, you can now generate a starter project that provides a nice template for an MVVM application. The starter template creates a simple "Explorer" like program - it looks like this:

Notice there are two sections - a TreeView listing all the directories, and a ListView showing all the files in the selected directory. Let's look a little closer at the project structure. There are four directories in the solution:

Converters This has a simple ValueConverter that takes a filename and returns an icon as an ImageSource.
Dependencies This is the binary dependencies the project requires, specifically it contains the JulMar MVVM libraries and Blend action libraries.
ViewModels This directory contains all the business logic in the form of ViewModels.
Views Finally, this directory contains all the UI (XAML) for the application.

Views

Let's start with the last folder - the Views. Views are the UI presentation of data - in the case of a WPF/Silverlight application this is most commonly the XAML and XAML code behind files (they are considered a single element together). We want to have UI-specific code and designer elements present in these files. Generally we prefer to place business logic and testable elements into the ViewModel area.

In this starter project, we have a single view MainWindow.xaml. This is what presents the main UI shown above. The code behind file contains the required boilerplate code (essentially a constructor and call to InitializeComponent).

If you open the view (note that the designer will choke on it until you compile the project), you will find fairly straightforward XAML that creates the UI, let’s break it down as we go:

<Window x:Class="WpfMVVMApplication1.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:julmar="http://www.julmar.com/wpfhelpers"
    xmlns:ViewModels="clr-namespace:WpfMVVMApplication1.ViewModels"
    xmlns:Converters="clr-namespace:WpfMVVMApplication1.Converters"
    DataContext="{julmar:ViewModelCreator {x:Type ViewModels:MainViewModel}}"
    Title="File Explorer" Height="400" Width="500">

 

First, notice how the DataContext is established – through a custom MarkupExtension called ViewModelCreator.  This extension is responsible for creating an associated ViewModel for this view (where our testable business logic should go) and also wiring up a couple of special event handlers that will allow the ViewModel to activate the view and close the view respectively.

Next, let’s check out the resources:

<Window.Resources>

  <!-- Bindable commands sit in resources and allow keyboard input to target ViewModel commands -->

  <julmar:BindableCommand x:Key="CloseCommand" Command="{Binding CloseAppCommand}" />

  <Converters:FilenameToIconConverter x:Key="iconConverter" />

  <HierarchicalDataTemplate x:Key="DirectoryTemplate"

           ItemsSource="{Binding Subdirectories}">

     <StackPanel Orientation="Horizontal">

        <Image Width="16" Height="16" Source="{Binding FullName,

               Converter={StaticResource iconConverter}}" />

        <TextBlock x:Name="tb" Margin="5,0" Text="{Binding Name}" />

     </StackPanel>

     <HierarchicalDataTemplate.Triggers>

        <DataTrigger Binding="{Binding IsSelected}" Value="True">

           <Setter TargetName="tb" Property="FontWeight" Value="Bold" />

        </DataTrigger>

     </HierarchicalDataTemplate.Triggers>

  </HierarchicalDataTemplate>

</Window.Resources>


Here we find three defined resources – first we have a JulMar MVVM BindableCommand.  This is a special ICommand instance that can be data bound and forwards to the specified binding.  We use this a bit later in the keyboard accelerator to close the application.  Next, there is the converter that takes a filename and converts it to an icon – that’s the source code in the Converters folder mentioned earlier.  I use a converter here because this is very UI-centric and not very testable – so the converter will data bind to a string (filename) property of the ViewModel and retrieve the icon for the UI to display.  That way, my ViewModel sticks with base (non-WPF) types.  This isn’t a hard rule – but it’s a good one to try to follow.

Finally, there is a DataTemplate that is used to display the directory structure – this is what the TreeView uses to display it’s data.  Notice it data binds to a couple of properties – FullName, Name and IsSelected.  All of these, as you will see, exist in our ViewModel definition.  The View takes the data from the ViewModel and displays it onto the UI for the user to interact with.

Next in the XAML is the input bindings – this is where we define keyboard and mouse gesture accelerators, and it’s where I use the bindable command I defined earlier:

    <Window.InputBindings>

        <KeyBinding Key="X" Modifiers="ALT" Command="{StaticResource CloseCommand}" />

    </Window.InputBindings>

 

Here you can see that instead of trying to bind to the command, we use {StaticResource} to get it from the resources.  This is necessary under WPF 3.5 because the KeyBinding will not inherit the DataContext and so cannot bind directly to the command – but resources can, and specifically Freezable resources can – that’s what the BindableCommand provides – a Freezable resource that forwards the ICommand implementation onto a command defined in the DataContext ViewModel.  This is not necessary under WPF4 – this is actually one of the new features they’ve added: to inherit the DataContext in your input bindings! 

The remainder of the view is fairly traditional – we use bindings to connect the UI up to the ViewModel definitions, so let’s go look at what those are.

ViewModels

The ViewModel folder contains three source code files – DirectoryViewModel.cs, FileViewModel.cs, and MainViewModel.cs.  If you recall from above, MainViewModel is the primary ViewModel that is data bound to the view.  The other two are child view models used to represent the files and folders respectively.  Let’s look at FileViewModel as an example:

    public class FileViewModel : SimpleViewModel

    {

        /// <summary>

        /// Marker file that signals expansion of the tree.

        /// </summary>

        internal static FileViewModel MarkerFile = new FileViewModel();

 

        private readonly FileInfo _data;

 

        /// <summary>

        /// File name

        /// </summary>

        public string Name

        {

            get { return _data.Name; }

        }

 

        /// <summary>

        /// Full path + filename

        /// </summary>

        public string FullPath

        {

            get { return _data.FullName; }

        }

 

        /// <summary>

        /// Size of the file in bytes

        /// </summary>

        public long Size

        {

            get { return _data.Length; }

        }

 

        /// <summary>

        /// Private constructor used to create marker file.

        /// </summary>

        public FileViewModel()

        {

        }

 

        /// <summary>

        /// Public constructor that captures a list of files.

        /// </summary>

        /// <param name="fi">FileInfo to grab file information from</param>

        public FileViewModel(FileInfo fi)

        {

            _data = fi;

        }

    }

 

As you can see, it is very simple – it is simply a wrapper around a piece of data, a FileInfo that represents a file on disk.  It exposes properties that are data bindable.  There is one element (MarkerFile) that I want you to ignore for a moment – we’ll get to it in a second.  Notice that it extends SimpleViewModel.  This is one of three primary VM classes in the MVVM helper library.  SimpleViewModel is intended for cases where you need the bare minimum support – specifically support for INotifyPropertyChanged.  No other services are provided by this base class, and as such it is very light.  Let’s look at the directory class next:

    /// <summary>

    /// Sample ViewModel that wraps a Directory.

    /// </summary>

    public class DirectoryViewModel : ViewModel

    {

        /// <summary>

        /// String used to send message to main view model about directory selection.

        /// </summary>

        internal const string SelectedDirectoryChangedMessage = @"SelectedDirectoryChanged";

 

        /// <summary>

        /// Marker directory that signals expansion of the tree.

        /// </summary>

        internal static DirectoryViewModel MarkerDirectory = new DirectoryViewModel();

 

        private bool _isSelected, _isExpanded;

        private readonly DirectoryInfo _data;

        private readonly ObservableCollection<FileViewModel> _files;

        private readonly ObservableCollection<DirectoryViewModel> _subdirs;

 

        /// <summary>

        /// Name of the directory

        /// </summary>

        public string Name

        {

            get { return _data.Name; }

        }

 

        /// <summary>

        /// Full path + name of the directory

        /// </summary>

        public string FullName

        {

            get { return _data.FullName; }

        }

 

        /// <summary>

        /// True/False whether the directory is selected (i.e. current).

        /// Selecting the directory causes it to populate it's file collection.

        /// </summary>

        public bool IsSelected

        {

            get { return _isSelected; }

            set

            {

                if (_isSelected != value)

                {

                    _isSelected = value;

 

                    if (_isSelected)

                    {

                        if (_files.Count == 1 && _files[0] == FileViewModel.MarkerFile)

                        {

                            _files.Clear();

                            _data.GetFiles()

                                .Where(f => (f.Attributes & (FileAttributes.Hidden | FileAttributes.System)) == 0)

                                .ForEach(f => _files.Add(new FileViewModel(f)));

                            OnPropertyChanged("TotalFiles", "TotalFileSize");

                        }

                        SendMessage(SelectedDirectoryChangedMessage, this);

                    }

                    else

                    {

                        _files.Clear();

                        _files.Add(FileViewModel.MarkerFile);

                    }

 

                    OnPropertyChanged("IsSelected");

                }

            }

        }

 

        /// <summary>

        /// True/False if the directory is expanded. Expanding the directory causes it

        /// to fill it's subdirectory collection.

        /// </summary>

        public bool IsExpanded

        {

            get { return _isExpanded; }

            set

            {

                if (_isExpanded != value)

                {

                    _isExpanded = value;

                    if (_isExpanded)

                    {

                        if (_subdirs.Count == 1 && _subdirs[0] == DirectoryViewModel.MarkerDirectory)

                        {

                            _subdirs.Clear();

                            _data.GetDirectories()

                                .Where(d => (d.Attributes & (FileAttributes.Hidden | FileAttributes.System)) == 0)

                                .ForEach(d => _subdirs.Add(new DirectoryViewModel(d)));

                        }

                    }

                    // Throw them away to recollect later - implements a refresh.

                    else

                    {

                        _subdirs.Clear();

                        _subdirs.Add(DirectoryViewModel.MarkerDirectory);

                    }

                }

 

                OnPropertyChanged("IsExpanded");

            }

        }

 

        /// <summary>

        /// List of files in this directory.

        /// </summary>

        public IList<FileViewModel> Files { get { return _files; } }

 

        /// <summary>

        /// List of subdirectories in this directory.

        /// </summary>

        public IList<DirectoryViewModel> Subdirectories { get { return _subdirs; } }

 

        /// <summary>

        /// Count of files in this directory.

        /// </summary>

        public int TotalFiles { get { return _files.Count; } }

 

        /// <summary>

        /// Total size of all files in this directory.

        /// </summary>

        public long TotalFileSize { get { return _files.Sum(file => file.Size); } }

 

        /// <summary>

        /// Constructor for the marker directory.  This is used to detect an expansion.

        /// </summary>

        private DirectoryViewModel()

        {

            _data = null;

        }

 

        /// <summary>

        /// Public constructor

        /// </summary>

        /// <param name="di">DirectoryInfo to pull information from</param>

        public DirectoryViewModel(DirectoryInfo di)

        {

            if (di == null)

                throw new ArgumentNullException("di");

 

            _data = di;

            _files = new ObservableCollection<FileViewModel> { FileViewModel.MarkerFile };

            _subdirs = new ObservableCollection<DirectoryViewModel> { DirectoryViewModel.MarkerDirectory };

        }

    }

 

This file is a bit more complicated – like the FileViewModel, this wraps a simple data object (a DirectoryInfo in this case).  Notice that it too exposes properties to provide access to various bits of information.  Here you can see that it is creating new properties such as TotalFileSize which is the sum of all the files sizes in this directory.  That’s one of the jobs of the ViewModel – to provide easily bindable properties for the bits of information we want to display.  In this case, the TotalFiles and TotalFileSize gets displayed in the StatusBar of the window when the directory has files.

Notice that the directory exposes files and subdirectories in ObservableCollections – but they are delay populated.  This is done so that the TreeView comes up quickly and we don’t have to enumerate the entire disk to retrieve the directories and files!  When you expand and collapse the nodes in the tree, it is populating the data.  This is done through the IsExpanded property – if you look back in the View, you will see that the TreeView actually binds the TreeViewItem.IsExpanded to this property:

<TreeView Grid.Column="0" ItemsSource="{Binding RootDirectory}"

        ItemTemplate="{StaticResource DirectoryTemplate}">

   <TreeView.ItemContainerStyle>

      <Style TargetType="TreeViewItem">

         <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />

         <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />

      </Style>

   </TreeView.ItemContainerStyle>

</TreeView>

 

Notice it also binds up the IsSelected property – this is when we populate the files collection.  Since they are observable, they will force the UI to update when new items are added or removed and we see the Explorer effect we desire.

Lastly, before we leave this file, notice that when a directory is selected, it makes a method call to a function called SendMessage:

SendMessage(SelectedDirectoryChangedMessage, this);

It passes a string (the key) and an object (the data).  This is a built-in service of the ViewModel base class and it’s the reason why this ViewModel does not derive from SimpleViewModel, but instead from ViewModel which is the full version.  One of the services provided is a Message Mediator.  This service basically allows you to loosely couple various objects together – we’ll see how the target registers, but for now, just notice the sender – it passes a string key and an object.  Any target registered for the given key will receive the object.  There are several overrides for the message mediator which I’ll detail in a later post.

Ok, let’s switch to the final file – the MainViewModel:

    public class MainViewModel : ViewModel

    {

        private DirectoryViewModel _selectedDirectory;

 

        /// <summary>

        /// Root directory - can be bound to an ItemsControl on the UI.

        /// </summary>

        public DirectoryViewModel[] RootDirectory { get; private set; }

 

        /// <summary>

        /// Selected (active) directory

        /// </summary>

        public DirectoryViewModel SelectedDirectory

        {

            get { return _selectedDirectory; }

            set { _selectedDirectory = value; OnPropertyChanged("SelectedDirectory"); }

        }

 

        /// <summary>

        /// Command to display the About Box.

        /// </summary>

        public ICommand DisplayAboutCommand { get; private set; }

 

        /// <summary>

        /// Command to end the application

        /// </summary>

        public ICommand CloseAppCommand { get; private set; }

 

        /// <summary>

        /// Main constructor

        /// </summary>

        public MainViewModel()

        {

            // Register this instance with the message mediator so it can receive

            // messages from other views/viewmodels.

            RegisterWithMessageMediator();

 

            // Create our commands

            DisplayAboutCommand = new DelegatingCommand(OnShowAbout);

            CloseAppCommand = new DelegatingCommand(OnCloseApp);

 

            // Fill in the root directory from C:

            RootDirectory = new[] { new DirectoryViewModel(new DirectoryInfo(@"C:\")) { IsSelected = true } };

        }

 

        /// <summary>

        /// This method closes the application window.

        /// </summary>

        private void OnCloseApp()

        {

            // Ask the view to close.

            RaiseCloseRequest();

        }

 

        /// <summary>

        /// This method displays the About Box.

        /// </summary>

        private void OnShowAbout()

        {

            // Get the message visualizer service from the service resolver.

            // All services can be replaced, so make sure to check if we have something

            // registered.

            IMessageVisualizer messageVisualizer = Resolve<IMessageVisualizer>();

            if (messageVisualizer != null)

            {

                // Show a message box.

                messageVisualizer.Show("About File Explorer Sample", "File Explorer Sample 1.0", MessageButtons.OK);

            }

        }

 

        /// <summary>

        /// This method is invoked by the message mediator when a DirectoryViewModel is selected.

        /// </summary>

        /// <param name="newDirectory">DirectoryViewModel that is now active</param>

        [MessageMediatorTarget(DirectoryViewModel.SelectedDirectoryChangedMessage)]

        private void OnCurrentDirectoryChanged(DirectoryViewModel newDirectory)

        {

            SelectedDirectory = newDirectory;

        }

    }

 

Here you can see the same basic principle – it exposes properties the UI binds to.  In particular here we see Commands being exposed as properties.  Commands is what drives a UI – it allows a UI to trigger actions in the ViewModel.  We are using two basic commands here – CloseAppCommand and DisplayAboutCommand.  If you look at the constructor, you will see they are backed by a DelegatingCommand object.  This is a common pattern found in almost every MVVM framework out there, but it’s essentially a pair of delegates that are called when the command is checked and when it is invoked.  In our cases here, we always allow the command to execute so we only provide the execution handler (a second parameter would define the typical CanExecute handler).  There are a couple of overrides for this object as well – one that provides type safety for the parameter and one that always uses object and allows for any object as data.  Again here we are being simple and not using any parameters so our bound methods are both no-parameter methods.

The CloseAppCommand command invokes the OnCloseApp method – which in turn calls RaiseCloseRequest.  This JulMar ViewModel method will close the view associated with the ViewModel if you associated the two using the ViewModelCreator.

The OnShowAbout method is called by the DisplayAboutCommand.  It uses another registered service in the library called IMessageVisualizer.  The message visualizer is used to display a simple message box from the ViewModel.  Here we use it to display an about box.  There are several other services I’ll talk about in the next post.

Notice that the RootDirectory property which is data bound to the TreeView.ItemsSource is exposes as an array – this is because the TreeView always expects a collection of items even though we always have a single root item.  So we wrap a single DirectoryViewModel into a collection and return it as the property.

If you look at the end of the file you will find our message mediator target – OnCurrentDirectoryChanged.  We use this as a way to see when a new directory has been selected in the tree.  For a ListBox, we could  have just data bound the SelectedItem to the property, but TreeView isn’t a selector and doesn’t expose a SelectedItem property.  Instead you either have to catch an event (I’ll show how you can do that in a future blog entry about the MVVM helpers library) or use this little mediator trick.

The [MessageMediatorTarget] attribute is the secret sauce here – it tells the message mediator to wire this method up to the passed string key.  When that key is used in a SendMessage call and the parameter type is a DirectoryViewModel (or derived type), the mediator will invoke this method.  This all happens without any direct linkage between the DirectoryViewModel and the MainViewModel.  The delegate instance is held in a weak reference so there’s no concern for memory leaks.

The second part of the magic is in the constructor – the message mediator is an opt-in service, so notice the call to RegisterWithMessageMediator().  This is what causes this instance to be noticed by the mediator.  There is a balancing UnregisterWithMessageMediator if you ever want to unhook the instance.  You can also use methods to directly wire up handlers (without attributes).  This is useful when you are dynamically linking things together at runtime vs. compile time.

Well, that covers the basics of the framework Views + ViewModels.  In the next post, I will detail the service registration and basic service mechanism that’s built into the framework for you to use.  Until then, ciao!

Friday, January 22, 2010 4:35:37 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Code | MVVM | WPF
# Wednesday, January 20, 2010
To start off this new series, I have created a MVVM Helpers project template - this is a Visual Studio 2008 template which will create the starter project I will be using as an example. It shows off the primary usage of the MVVM library and has directories and references to required assemblies already established so it's a nice starting point for any MVVM WPF app using the helpers.

Download it from here and copy the zip file into your template directory.

As an example, if your user name was "Mark", like me and you are running Windows 7 it would be:
"C:\Users\Mark\Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual C#\Windows"

Here's what my directory looks like:

templatedir.jpg

With that in place you should be able to fire up Visual Studio 2008 and create a sample MVVM project:

project_screen.jpg

Let it generate a project and the build it -- running the program will give you a simple file explorer using the MVVM design pattern and WPF:

 sample-run1.jpg 

In tomorrow's post, we'll break the sample down and see how I built it. See you then!

 

Wednesday, January 20, 2010 5:35:13 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Code | WPF

With this post I am starting a new series - I hope to be more consistent in posting at least once or twice a week. To that end, I am going to focus on the WPF/MVVM helper library I use daily. I released an earlier version of it onto the web and have gotten a lot of comments which has been great, so I am releasing the latest version which has a lot of changes. So, without further ado, here's the code for you to download and play with, this compiles with Visual Studio 2008 SP1, or with Visual Studio 2010 Beta 2.

mvvmhelpers.zip

Read on for the basics of the project structure and files.

Project Structure

The code is broken into two assemblies: Julmar.Wpf.Helpers and Julmar.Wpf.Behaviors. The helpers assembly contains core WPF helper classes and MVVM support and the behaviors assembly depends on the System.Windows.Interactivity support and provides Blend-based behaviors for a variety of situations.

Building and Usage

There are pre-built assemblies included in the distribution, but you are free to build the source on your own - I don't include the certificate file (so I can tell versions that I have built) but you are free to delete the certificate from the solution or replace it with your own and build your own binaries from the source code. Or you can take any of the source code, modify it however you like and add it directly to your project.

Credits

As with most projects, this library has benefited significantly from the community. The WPF Disciples list on has been a particular source for ideas and even source code. There are some source files in the project that I did not author, or where I took a bit of code and modified it to suit my purposes. I have tried to make sure people get credit where appropriate in the source code itself, if I missed anyone I am truly sorry.

Documentation

As I mentioned earlier, my goal is to produce a set of blog posts that detail how to use the library, but there is also some documentation on each class included in the distribution in the form of a .CHM (Windows Help File). I encourage anyone who wants to use this library to check that out.
Solution.jpg

Wednesday, January 20, 2010 2:22:12 PM (Central Standard Time, UTC-06:00)  #    Comments [2] -
.NET | Code | WPF
# Tuesday, August 11, 2009

One of the new features added to WPF 3.5 SP1 was the ScrollViewer.IsDeferredScrollingEnabled property which allows you to scroll through large amounts of data without taking the actual scrolling hit until the user stops moving the scroll thumb.  This is essential when you have complex visualizations, or if the data itself is virtualized and the load time is expensive.  You can get information on this feature here:

http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.isdeferredscrollingenabled.aspx

Recently, I was working on a project where I have a Slider that is controlling a grouping option.  When the user changes the slider value, the visuals are regrouped based on the position of the slider itself.  The problem I ran into was it's an expensive operation to do the grouping and if the user tries to quickly drag the slider I ended up doing a whole bunch of non-essential groupings of my data for no reason.  They are expensive enough that the actual drag of the slider was impacted by it - not to mention the CPU and rendering!  So, my initial response in these situations is to turn on asynchronous data binding - that's as simple as throwing the Binding.IsAsync flag.  This essentially causes the binding transfer to occur on a background thread and will often improve responsiveness in situations like this.

In this case, however, it didn't really help because I was still doing all the intermediate calculations.  What I really need is some way to defer the binding transfer until the slider stops. There's no option for that however so I whipped up a simple class which allows me to bind two properties together and place a timer between them to indicate how long it should wait before transferring the Source to the Target.  I could have done it in the code - it's just a timer solution after all, but I wanted something reuseable.

Here's an example usage:

<StackPanel>
   <StackPanel.Resources>
      <DeferredBinder:DeferredBinding x:Key="dbTest" Timeout="1" />
   </StackPanel.Resources>
   <TextBlock x:Name="tb" Text="{Binding Source={StaticResource dbTest}, Path=Target}" FontSize="48pt" HorizontalAlignment="Center" />
   <Slider x:Name="slider" Margin="10" HorizontalAlignment="Center" Width="200" Minimum="0" Maximum="100" Value="{Binding Source={StaticResource dbTest}, Path=Source, Mode=OneWayToSource}" />
</StackPanel>

In this case, the slider's value is transferred 1 second after the final update (i.e. it waits 1 second for the user to stop sliding).

Here's a sample project to try out:

DeferredBindingSample.zip

 

Tuesday, August 11, 2009 5:54:00 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF

I'm a big fan of themes in WPF -- and I think it's great that Microsoft has released a whole set of themes for Silverlight and WPF at www.codeplex.com/wpf

However, in using some of those themes, I've run into an annoying bug in the RadioButton template - specifically, the checked state doesn't always show up initially.  Looking at the template, it turns out to be an easy fix.  The "CheckIcon" is set to an opacity of zero initially (so it's not shown) and then a trigger is used to apply an animation to change the value.  Unfortunately, it looks like the animation is switched - it applies when the checkbox is UNCHECKED vs. CHECKED.  So, two ways to fix it -- either change the initial opacity to "1" for the "CheckIcon" element in the control template, or go to the triggers in the control template for the RadioButton and swap the states so it looks like this:

<Trigger Property="IsChecked" Value="false" />
<Trigger Property="IsChecked" Value="True">
   <Trigger.EnterActions>
      <BeginStoryboard x:Name="CheckedOn_BeginStoryboard" Storyboard="{StaticResource CheckedOn}"/>
   </Trigger.EnterActions>
   <Trigger.ExitActions>
      <BeginStoryboard x:Name="CheckedOff_BeginStoryboard" Storyboard="{StaticResource CheckedOff}"/>
   </Trigger.ExitActions>
</Trigger>
Tuesday, August 11, 2009 11:30:13 AM (Central Daylight Time, UTC-05:00)  #    Comments [3] -
.NET | WPF
# Tuesday, August 04, 2009

I just put the latest version of the MVVM helpers online - mvvmhelpers.zip

There's a bunch of new stuff in it - check the release notes for the highlights.  There's a set of breaking changes in it as well, specifically I've moved several of the attached behaviors into the new Blend model.  Originally in my local version I did it to the JulMar.Wpf.Helpers.dll and got a dependency against System.Windows.Interactivity.dll.

I decided that for this release I didn't want to force that dependency so I created a secondary assembly JulMar.Wpf.Behaviors.dll which has all those behaviors in it.  The breaking change is I removed the original attached behaviors from the library (DoubleClickBehavior, NumericTextBehavior, MouseDragBehavior) in favor of using these new versions.  I did update the sample to show how they get used.

In a recent Essential WPF class, one of the students wanted an ObservableDictionary which we whipped up there - I cleaned up that implementation somewhat and added it into this library along with some unit tests for it.

Again, please check the readme included in the .zip file -- as always you are free to do whatever you like with this code.  If you do anything interesting or fun, let me know!

 

Tuesday, August 04, 2009 1:14:38 PM (Central Daylight Time, UTC-05:00)  #    Comments [3] -
.NET | WPF | MVVM
# Monday, August 03, 2009

A recent series of blog entries at http://themechanicalbride.blogspot.com/ introduced the Rx framework (System.Reactive.dll) which is an assembly used in the Silverlight toolkit for UI testing purposes.  It essentially provides a mechanism to do event driven programming through LINQ.  I'll refer you to the blog referenced above for all the gory details - frankly I'm still trying to wrap my mind around it!

Silverlight isn't my favorite technology however, I much prefer working in WPF and so I spent some time rebuilding Rx for the desktop CLR!  My original approach was to take my favorite exploration tool, reflector (available for free from www.redgate.com), and disassemble all the classes into C#, placing them into a project file.  I found however that Reflector choked on some of the more complicated structures - requiring me to go and hand-edit a bunch of the code.  I realized while I was doing this that there was a much easier way to convert a Silverlight assembly to a WPF assembly.

As you probably already know, Silverlight shares the same assembly format as the desktop CLR - there is no difference in the IL or structure of the assembly itself.  The difference is in the dependency on mscorlib and other references.  Specifically, when you add an assembly via VS2008, it looks at the version of the referenced mscorlib to determine whether it's a desktop CLR assembly or Silverlight assembly. 

Here's the header of a Silverlight assembly examined through ILDASM:

// Metadata version: v2.0.50727
.assembly extern mscorlib
{
   .publickeytoken = (7C EC 85 D7 BE A7 79 8E ) // |.....y.
   .ver 2:0:5:0
}

Here is a desktop assembly:

// Metadata version: v2.0.50727
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 2:0:0:0
}

Notice the version difference .. Silverlight uses 2.0.5.0 of mscorlib and the desktop CLR uses 2.0.0.0.  The public key is also different, but this is really just used for loading purposes.

Assuming the assembly doesn't use something Silverlight specific, we can modify the assembly references and allow the asembly to be used in the desktop CLR fairly easily. 

Here's how I did it for System.Reactive.dll:

ILDASM System.Reactive.dll /out:SR.il

change the assembly references in the resulting IL text file (for mscorlib, system and system.core)

ILASM SR.il /resource=sr.res /output=WPF/System.Reactive.dll

That gave me a desktop version of the assembly without modifying anything in the code itself - much easier than my original reflector route!

Next, I took a couple of the samples from the blog and ported them to WPF - specifically, I took the events sample listed here http://themechanicalbride.blogspot.com/2009/07/developing-with-rx-part-1-extension.html and ported it to WPF to test it.  I made very few changes, primarily just switching Application.Current.MainWindow for Application.Current.RootVisual.  Here is the resulting project and switched assembly for anyone who is interested in it.

ExtensionEvents.zip (44.62 KB)

I think Rx is a fascinating piece of code, although it will take me a bit of time to realize just what I can do with it I suspect.  I'm looking forward to building more with this using WPF now that's for sure!

Monday, August 03, 2009 10:56:03 AM (Central Daylight Time, UTC-05:00)  #    Comments [1] -
.NET | Code | WPF
# Friday, July 24, 2009

One of the coolest new features of Blend 3 is the inclusion of behaviors. This new feature formalizes the "attached behavior" model that has become so prevelant in WPF (and Silverlight) development.  I won't go into details on the architecture - instead I'll refer you to a nice reference:

http://blogs.msdn.com/expression/archive/2009/05/19/link-round-up-behaviors-related-posts.aspx

To play with this new support, I built a WatermarkTextBehavior which places a watermark into a TextBox when it has no entered data.  I've included this new behavior into the current build of my MVVM toolkit which I'll release soon, but for now, let's look at the behavior:

First, we derive from System.Windows.Interactivity.Behavior<T> - the placeholder parameter is the Visual type you want the behavior to act on.  This can be UIElement for anything WPF, or more restrictive if necessary based on the events you intend to hook up.  For our purposes here, we will set the restricted type to TextBox.

public class WatermarkTextBehavior : Behavior<TextBox>

Next, you override the OnAttached() and OnDetaching() methods to hook up your event behaviors you desire.  Call the base implementation first, and then the AssociatedObject property will be the element you've been attached to (the TextBox in this case).  In our case we want to hook the GotFocus and LostFocus events - this is where we trigger our behavior.

protected override void OnAttached()
{
  
base.OnAttached();
  
AssociatedObject.GotFocus += OnGotFocus;
  
AssociatedObject.LostFocus += OnLostFocus;
  
...
}

protected override void OnDetaching()
{
   base.OnDetaching();
   AssociatedObject.GotFocus -= OnGotFocus;
   AssociatedObject.LostFocus -= OnLostFocus;
}

Finally, we can provide any properties necessary to drive our behavior.  These should be done in the form of Dependency Properties so they are bindable and interact nicely with WPF.  The base Behavior<T> derives from Freezable and inherits the DataContext automatically to enable this support.  In our implementation we will have a Text property to indicate the watermark, and an attached property which we will place onto the TextBox so it can be styled when the watermark is being used.

public static readonly DependencyProperty TextProperty =
  
DependencyProperty.Register("Text", typeof (string), typeof (WatermarkTextBehavior),
                     
new FrameworkPropertyMetadata(string.Empty));

Next we can hook it up in Blend through the Asset panel - all known assets are shown here (either registered, in the Blend directory, or project references).  Drag our WatermarkTextBehavior onto any TextBox and set the Text property and it will generate the following XAML:

<TextBox>
   <TextBox.Style>
      <Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
         <Style.Triggers>
            <Trigger Property="julmar:WatermarkTextBehavior.IsWatermarked" Value="True">
               <Setter Property="Foreground" Value="Gray" /> 
               <Setter Property="FontStyle" Value="Italic" />
            </Trigger>
         </Style.Triggers>
      </Style>
   </TextBox.Style>
   <i:Interaction.Behaviors>
      <julmar:WatermarkTextBehavior Text="Enter a name here" />
   </i:Interaction.Behaviors>
</TextBox>

Here is the complete source code to the behavior:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace JulMar.Windows.Interactivity
{
    /// <summary>
    /// This behavior associates a watermark onto a TextBox indicating what the user should
    /// provide as input.
    /// </summary>
    public class WatermarkTextBehavior : Behavior<TextBox>
    {
        /// <summary>
        /// The watermark text
        /// </summary>
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof (string), typeof (WatermarkTextBehavior),
                                        new FrameworkPropertyMetadata(string.Empty));

        static readonly DependencyPropertyKey IsWatermarkedPropertyKey =
            DependencyProperty.RegisterAttachedReadOnly("IsWatermarked", typeof(bool), typeof(WatermarkTextBehavior), 
                                        new FrameworkPropertyMetadata(false));

        /// <summary>
        /// This readonly property is applied to the TextBox and indicates whether the watermark
        /// is currently being displayed.  It allows a style to change the visual appearanve of the
        /// TextBox.
        /// </summary>
        public static readonly DependencyProperty IsWatermarkedProperty = IsWatermarkedPropertyKey.DependencyProperty;

        /// <summary>
        /// Retrieves the current watermarked state of the TextBox.
        /// </summary>
        /// <param name="tb"></param>
        /// <returns></returns>
        public static bool GetIsWatermarked(TextBox tb)
        {
            return (bool) tb.GetValue(IsWatermarkedProperty);
        }

        /// <summary>
        /// Retrieves the current watermarked state of the TextBox.
        /// </summary>
        public bool IsWatermarked
        {
            get { return GetIsWatermarked(AssociatedObject);  }    
            private set { AssociatedObject.SetValue(IsWatermarkedPropertyKey, value);}
        }

        /// <summary>
        /// The watermark text
        /// </summary>
        public string Text
        {
            get { return (string) base.GetValue(TextProperty); }
            set { base.SetValue(TextProperty, value); }
        }

        /// <summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>
        /// <remarks>
        /// Override this to hook up functionality to the AssociatedObject.
        /// </remarks>
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.GotFocus += OnGotFocus;
            AssociatedObject.LostFocus += OnLostFocus;

            OnLostFocus(null, null);
        }

        /// <summary>
        /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
        /// </summary>
        /// <remarks>
        /// Override this to unhook functionality from the AssociatedObject.
        /// </remarks>
        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.GotFocus -= OnGotFocus;
            AssociatedObject.LostFocus -= OnLostFocus;
        }

        /// <summary>
        /// This method is called when the textbox gains focus.  It removes the watermark.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnGotFocus(object sender, RoutedEventArgs e)
        {
            if (string.Compare(AssociatedObject.Text, this.Text, StringComparison.OrdinalIgnoreCase) == 0)
            {
                AssociatedObject.Text = string.Empty;
                IsWatermarked = false;
            }
        }

        /// <summary>
        /// This method is called when focus is lost from the TextBox.  It puts the watermark
        /// into place if no text is in the textbox.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnLostFocus(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(AssociatedObject.Text))
            {
                AssociatedObject.Text = this.Text;
                IsWatermarked = true;
            }
        }
    }
}

 

Friday, July 24, 2009 2:14:52 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code | WPF
# Monday, July 06, 2009

A project I've been working on for the last two months is finally online in beta form - check out

http://rcat.codeplex.com/

It's essentially a biological alignment viewer for RNA sequences.  Here's a couple of screen shots:

Alignment Viewer

2D Structure Viewer

2D Circle relationship Viewer

You can download the source code from the above link to play with it - it's a MVVM implementation and has quite a bit of interesting optimizations in it for performance purposes, including a read-only data virtualization for large sequence manipulation.  The next release will include a full read/write implementation so watch the project if you are interested!

 

Monday, July 06, 2009 1:24:44 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code | Real World | WPF
# Wednesday, April 29, 2009

In the previous post, I wrote about using the MVVM pattern with Context Menus, but you can use it with top-level menus too -- for example, perhaps I'd like to manage a set of options through a set of checkboxes.  First, let's start with my list of options - for simplicity, we'll just make it an enumeration:

public enum Test
{
   A,
   B,
   C,
   D,
   E,
   F
}

Next, let's define a ViewModel to wrap this - each entry should support a single value and a boolean binding to determine whether it is checked:

public class CheckValues
{
   public Test Value { get; set; }
   public string Text { get { return Value.ToString(); } }
   public bool IsChecked { get; set; }
}

Very likely this object would also implement INotifyPropertyChanged and fire change notifications, in this case it's not necessary since we aren't changing the values from code behind.  The next step is to expose this as a bindable collection - since it's not changing we'll just use a List<T>.

public List<CheckValues> EnumValues { get; set; }

...

EnumValues = new List<CheckValues>();
foreach (object t in Enum.GetValues(typeof (Test)))
{
   EnumValues.Add(new CheckValues {Value = (Test) t});
}

Finally, in the XAML itself we want to databind to the collection of CheckValues, supplying the appropriate support for each MenuItem to bind the menu checks to the collection:

<Menu DockPanel.Dock="Top">
   <MenuItem Header="Enum Values" ItemsSource="{Binding EnumValues}">
      <MenuItem.ItemContainerStyle>
         <Style TargetType="MenuItem">
            <Setter Property="Header" Value="{Binding Text}" />
            <Setter Property="IsCheckable" Value="True" />
            <Setter Property="IsChecked" Value="{Binding IsChecked}" />
         </Style>
      </MenuItem.ItemContainerStyle>
   </MenuItem>
</Menu>

That gives us our nice "checkable" menu - when the user clicks a checkmark, it sets the appropriate boolean in the code behind which could trigger logic, set values, etc.

But wait!  Often with checkboxes you want mutual exclusive choices - like the RadioButton groups.  This was a feature of Windows Forms which unfortunately did not make it into WPF, but we can make it work that way.  We could use the above logic and have the selection of a specific CheckValue unselect any others, or we could take advantage of RadioButtons to do this -- unfortunately I've not found a way that doesn't invoice a little code behind so it's not quite as clean as I'd like it to be, but it is possible.

First, let's define an exclusive ViewModel object, here we will track the "current" selection:

public class ExclusiveCheckValues
{
   public static Test SelectedValue { get; set; }
   public Test Value { get; set; }

   public string Text { get { return Value.ToString(); } }
   public bool IsChecked
   {
      get { return Value == SelectedValue; }
      set
      {
         if (value)
            SelectedValue = Value;
      }
   }
}

Next, we populate it into a bindable collection just as before and then we create some slightly more complex XAML for our menu items.  The trick here is to put a RadioButton into the menu item and associate it with a group.  I have to give a shout out to Dr. WPF from the wpf-disciples list some kudos here - he posted this trick on the MSDN forums (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/76c14163-9462-44d6-b0eb-6f22a006b423).  It turns out the MenuItem.Icon is positioned just where the normal check mark would be so if we place a styled RadioButton as the MenuItem.Icon we can make it look just like the checkmark:

<Menu DockPanel.Dock="Top">

   <Menu.Resources>
      <RadioButton x:Key="rb" x:Shared="false" HorizontalAlignment="Left"
                   GroupName="MenuGroup" IsChecked="{Binding IsChecked}">
         <RadioButton.Template>
            <ControlTemplate TargetType="{x:Type RadioButton}">
               <Path x:Name="check" Margin="7,0,0,0" Visibility="Collapsed" VerticalAlignment="Center"
                      Fill="{TemplateBinding MenuItem.Foreground}" FlowDirection="LeftToRight"
                      Data="M 0,5.1 L 1.7,5.2 L 3.4,7.1 L 8,0.4 L 9.2,0 L 3.3,10.8 Z"/>
               <ControlTemplate.Triggers>
                   <Trigger Property="IsChecked" Value="True">
                      <Setter TargetName="check" Property="Visibility" Value="Visible" />
                   </Trigger>
                </ControlTemplate.Triggers>
             </ControlTemplate>
          </RadioButton.Template>
       </RadioButton>
    </Menu.Resources>

    <MenuItem Header="Single Select Enum Values" ItemsSource="{Binding ExclusiveEnumValues}">
       <MenuItem.ItemContainerStyle>
          <Style TargetType="MenuItem">
             <Setter Property="Header" Value="{Binding Text}" />
             <Setter Property="Icon" Value="{DynamicResource rb}" />
             <EventSetter Event="Click" Handler="OnMenuItemClick" />
          </Style>
       </MenuItem.ItemContainerStyle>
    </MenuItem>
</Menu>

Here, we've placed the RadioButton into our resources - but marked it as non-shareable.  The issue is that Styles always share property setters - and if you tried to do this:

<Style TargetType="MenuItem">
   <Setter Property="Icon"
>
     <Setter.Value>
       <RadioButton ... />
     </Setter.Value>
   </Setter>

You will get a very strange error message: "Cannot assigned type 'RadioButton' to type 'object'".  Which makes absolutely no sense until you realize the XAML parser is trying to assign the same RadioButton to every MenuItem.Icon.  The non-shareable resource fixes that issue.  The last step is to set the check -- this is done through the EventSetter in the above template.  It's wired to the little bit of code behind:

private void OnMenuItemClick(object sender, RoutedEventArgs e)
{
   ((RadioButton) ((MenuItem) sender).Icon).IsChecked = true;
}

This then sets the IsChecked property which will, in turn, select that item.  Now you can look at ExclusiveCheckValue.SelectedValue to get the current item.  This isn't the most elegant solution, nor is it the only solution but it's an interesting one to think on.  If I were truly building this into a production application, I'd probably look at controlling the selection in the ModelView (i.e. enumerate through my other choices and deliberately turn them off).  But this does illustrate how powerful WPF is!

Here's the example project with both styles.


 

Wednesday, April 29, 2009 8:30:51 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Tuesday, April 21, 2009

One question I've fielded a couple of times is how to manage menus, primarily context menus, with the MVVM pattern.  It turns out to be pretty easy once you know the "trick".  The key thing to keep in mind is that menus are just ItemsControls - they support data templating and binding like any other ItemsControl.  However, the part where people get lost is in hooking up the commands.  Here's the trick:

Step 1: Define some code behind construct to manage each menu item in a hiearchial fashion.  Here's one I've used:

public class MenuItem
{
   public string Text { get; set; }
   public List<MenuItem> Children { get; private set; }
   public ICommand Command { get; set; }
  
   public MenuItem(string item)
   {
       Text = item;
       Children = new List<MenuItem>();
   }
}

Step 2: Create your menu structure using the above container.

This involves just creating a List<MenuItem> which holds the root nodes and using a DelegatingCommand to wire up some code behind method.  Here's an example:

public List<MenuItem> MenuOptions
{
    get  {

       var menu = new List<MenuItem>();
       if (SupportedFileFormats.Count > 0)
      {
          var mi = new MenuItem("O_pen");
          foreach(var fl in SupportedFileFormats)
          {
               var sff = fl;
               mi.Children.Add(new MenuItem(fl.Attributes.Description) 
                      { Command = new DelegatingCommand(() => { LoadFromFormat(sff); })});
          }
          menu.Add(mi);
       }

       menu.Add(new MenuItem("Close _All") { Command = new DelegatingCommand(OnCloseAll, () => FileList.Count > 0)});
       return menu;
    }

}

Note the use of an anonymous method to suck the correct file format into the command handler.  A nice trick so the command is executed with some contextual information of what you clicked on.

Finally, you need to setup the context menu style:

<Style x:Key="ContextMenuItemStyle">
  
<Setter Property="MenuItem.Header" Value="{Binding Text
}"/>
   
<Setter Property="MenuItem.ItemsSource" Value="{Binding Children
}"/>
   
<Setter Property="MenuItem.Command" Value="{Binding Command
}" />
</Style>

And then use the style where you want the menu to appear:

<StackPanel Orientation="Horizontal">
   
<Image Source="{Binding Image}" Width="16" Height="16" />
   
<TextBlock Margin="5" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding Header}" />
   
<StackPanel.ContextMenu>
      
<ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}" ItemsSource="{Binding MenuOptions}" />
   
</StackPanel.ContextMenu>
</StackPanel>

</HierarchicalDataTemplate>

Now the context menu is populated and properly dispatches to your ViewModel commands!

Edit: added intermediate object in LINQ query to fix deferred query issue pointed out in comments.
 

Tuesday, April 21, 2009 5:35:59 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Friday, April 17, 2009

There's been a lot of talk about the Model-View-ViewModel pattern recently and it's usage around the WPF and Silverlight technology stack.  When teaching WPF, I always introduce students to MVVM as part of the Essential WPF class, it's an incredibly useful pattern that really separates the UI from the code behind behavior.  One of the things I give the students is a library to do MVVM - I also use it in my consulting work.  With all the focus on it lately, I figured maybe it's time to release it to the public.

A bit of history -- the library is really just a place where I dump all kinds of useful utility classes, helpers, wrappers, etc. that I tend to use a lot.  I started it about 3 years ago and it wasn't originally intended to be just an MVVM implementation so you'll find it's got all kinds of stuff in it, not all of which is MVVM specific.  It's evolution owes a lot to various blog posts, WPF Disciples, and other WPF leaders; I certainly didn't invent anything radically new but borrowed heavily from all kinds of places as I built various classes I needed for my own work.  These classes tended to evolve with new functionality (either due to necessity, or because a good idea occurred to me or someone else). For example, there was a recent thread on the Mediator pattern (initiated by Marlon Grech and added on by Josh Smith, Laurent Bugnion and others); I already had a message mediator in place but the idea of using an attribute to hook it up was a great one that I adopted into my library just because I like the idea.  The Delegating command pattern is one you see in a lot of places - including the Prism implementation.  The event routing attached behavior was made possible by a couple of blog posts by Mike Hilberg and John Gossman. So, be aware that as you use this code, it owes a lot to a variety of people.  That said, any bugs or issues are completely mine and I take full credit for them.

So, what all is here?  Well, quite a bit.  As I said, this is a collection of helpers I've built and reused over the years doing WPF consulting and instruction.  When MVVM came to my notice I worked on trying to completely separate the XAML side so I'll focus on those classes here. 

The basic idea is to derive your ViewModel classes from one of three base classes depending on what you need:

JulMar.Windows.Mvvm.ViewModel - supports basic INotifyPropertyChanged and Close/Activate eventing to the view.
JulMar.Windows.Mvvm.ValidatingViewModel - supports everything above, adds Validation through IDataErrorInfo support
JulMar.Windows.Mvvm.EditingViewModel - supports basic + validation + IEditableObject

Next, in each view (XAML) you set the DataContext property to your view model, the library has a MarkupExtension to do the work for you -

<Window x:Class="TestMvvm.MainWindow"
  
xmlns:julmar="http://www.julmar.com/wpfhelpers"  xmlns:me="clr-namespace:TestMvvm"
   DataContext="{julmar:ViewModelCreator ViewModelType={x:Type me:WinViewModel}}">

This creates the view and also wires up support for closing the view and activating the view through the ViewModel class (using the RaiseCloseRequest and RaiseActivateRequest methods).

Everything is driven off ICommand - you can bind commands to the lifetime of the view (so you can detect activation, deactivation, loading, closing) through the LifetimeEvents attached behavior:

<Window x:Class="TestMvvm.MainWindow"
   julmar:LifetimeEvent.Activated="{Binding ActivatedCommand}"
  
julmar:LifetimeEvent.Close="{Binding CloseCommand}"
  
julmar:LifetimeEvent.Loaded="{Binding LoadedCommand}"
  
julmar:LifetimeEvent.Deactivated="{Binding DeactivatedCommand}" >

These execute the bound command in the ViewModel when those events occur in the view.  If you need other events styles you can use the EventCommander attached behavior which allows any arbitrary event to be wired to a command.  This can be placed on any UIElement:

<julmar:EventCommander.Mappings>
  
<julmar:CommandEvent Command="{Binding MouseEnterCommand}" Event="MouseEnter" />
  
<julmar:CommandEvent Command="{Binding MouseLeaveCommand}" Event="MouseLeave" />
julmar:EventCommander.Mappings>

You can also wire up keyboard and mouse gestures to commands using the InputBinder attached property:

<julmar:InputBinder.Bindings>
   <julmar:KeyBinding Command="{Binding ExitCommand}" Key="F3" Modifiers="ALT" />
  
<julmar:MouseBinding Command="{Binding ExitCommand}" Gesture="Control+RightClick" />
julmar:InputBinder.Bindings>

This replaces the traditional InputBindings collection with a data bindable version - it also supports CommandParameter objects on each KeyBinding or MouseBinding.  You can use it on any element which supports input bindings.

There are some helper classes implemented through interfaces and a (very) simple ServiceProvider to locate them:

IErrorVisualizer - to display errors (title + message).  Default implementation displays MessageBox with OK button.
IMessageVisualer - to display messages with a prompt.  Default implementation uses MessgeBox.
INotificationVisualizer - to display a wait prompt.  Default implemation uses an hourglass cursor.
IUIVisualizer - to display other views through a key.  Supports both modal and modaless display.

You use the ServiceProvider to find the services - the base ViewModel class has support built in for it:

Resolve<IErrorVisualizer>().Show("An Error Occurred", e.Description);

You can register the default implementation for all of the above in the App.xaml.cs file -

ViewModel.RegisterKnownServiceTypes();

You can also provide your own implementation through the ServiceProvider itself.  The ViewModel class has a public static field:

ServiceProvider.Add(typeof(IErrorVisualizer), new MyErrorVisualizer());

This replaces or adds the given service (using the type as the key) to the registry database.  You then use Resolve to find the service at runtime in any view.  Creating secondary views is done through the IUIVisualizer interface.  The default implementation provides a registry and must be added explicitly to use it:

IUIVisualizer controller = new UIVisualizer(new Dictionary
                                        {
                                            {Dialogs.AddNewPage, typeof(AddNewPageWindow)},
                                            {Dialogs.ManagePages, typeof(BrowseWindow)},
                                            {Dialogs.NewLogon, typeof(LoginDialog)}
                                        });

ServiceProvider.Add(typeof(IUIVisualizer), controller);

This adds three UI dialogs to the visualizer - the key is a simple string, the second parameter is a Type object that represents the Window to create.  You then get the window to display through the IUIVisualizer interface:

LoginViewData ld = new LoginViewData();

IUIVisualizer uiController = ServiceProvider.Resolve();
if (uiController.ShowDialog(Dialogs.NewLogon, ld).Value == true)
{
}

This shows the login dialog, using the LoginViewData as the DataContext (ViewModel).  It displays it as a modal dialog and returns the final result.  You can also display modaless dialogs which take an optional completion proc:

public bool Show(string key, object state, bool setOwner, EventHandler completedProc)

The completed procedure is invoked when/if the window ever closes.  Again, the state passed is the data context and if it derives from ViewModel the appropriate Closing/Activated events will be wired up to the events in the ViewModel.

I've been using this library for quite a while and it works great (for me).  I provide it here with full source code so you can diagnose any issues you have, or just look through it.  Feel free to use it however you like.  I don't claim this to be the end-all implementation - as I said much of the ideas expressed in here can be found elsewhere.  There is also a help file provided and a simple example of how to use some of the classes provided that I whipped up for fun.

Here's the download with everything packaged.

Enjoy - let me know if you have any issues or think of a good addition!  Just remember I put no guarentee on this code - consider it a sample for you to do whatever you like with.

 

Friday, April 17, 2009 11:06:09 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Wednesday, April 01, 2009

One annoying thing about ObservableCollection<T> is that it doesn't support modifications from background threads.  That is to say, the CollectionChanged notification doesn't marshal to the proper thread when it is raised and it causes the exception "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread". 

I ran into this problem a while back and searched out to see if someone else had solved it. I found a solution from Tamir Khason (a fellow WPF disciple), he wrote a thread-safe version (http://blogs.microsoft.co.il/blogs/tamir/archive/2007/04/22/Thread-safe-observable-collection.aspx), but I didn't want to add the locking into the collection itself (I want to manage it at a higher level myself).  Really, all I want is to do the notification on the proper (Dispatcher) thread. 

It turns out to be pretty easy, here's my solution:

public class MTObservableCollection<T> : ObservableCollection<T>
{
   public override event NotifyCollectionChangedEventHandler CollectionChanged;
   protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   {
      var eh = CollectionChanged;
      if (eh != null)
      {
         Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
                 let dpo = nh.Target as DispatcherObject
                 where dpo != null
                 select dpo.Dispatcher).FirstOrDefault();

        if (dispatcher != null && dispatcher.CheckAccess() == false)
        {
           dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
        }
        else
        {
           foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
              nh.Invoke(this, e);
        }
     }
  }
}

Wednesday, April 01, 2009 12:17:37 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Thursday, March 05, 2009

A couple of weeks ago, Jason Whittington (a fellow instructor at Developmentor) and I were doing a talk on asynchronous programming and we started with a very simple example of the APM -- using two loops to create and then consume the IAsyncResult work:

static void TwoLoopMain(string[] args)
{
   Queue<IAsyncResult> ars = new Queue<IAsyncResult>();
   Func<int,int,int> mathProc = Multiply;

   for (int i = 1; i <= 20; i++)
   {
      for (int j = 1; j <= 20; j++)
         ars.Enqueue(mathProc.BeginInvoke(i, j, null, null));
   }
   for (int i = 1; i <= 20; i++)
   {
      for (int j = 1; j <= 20; j++)
      {
         int result = mathProc.EndInvoke(ars.Dequeue());
         Console.SetCursorPosition(i * 3, j);
         Console.Write(result);
     }
  }
}

We had already presented a talk on LINQ earlier in the week and so I thought we might be able to do the above in a single expression with LINQ - kind of a challenge .. here's what we came up with:

static void LinqTest()
{
   Func<int,int,int> mathProc = Multiply;

   (from i in Enumerable.Range(1, 20)
    from j in Enumerable.Range(1, 20)
    select new { i, j, ar = mathProc.BeginInvoke(i, j, null, null) })
      .ToList()
      .ForEach(e => {
        int result = mathProc.EndInvoke(e.ar);
        Console.SetCursorPosition(e.i * 3, e.j);
        Console.Write(result);
     });
}

It's not easily readable (and so I wouldn't promote this for production code), but it's way cool and an example of how LINQ (and functional programming in general) is really changing the way programmers think about code.. just freaking cool..

Thursday, March 05, 2009 11:27:19 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET
# Thursday, January 29, 2009
Update
Microsoft has released the API code pack including Windows 7 support -- get it here: http://code.msdn.microsoft.com/WindowsAPICodePack

Well, it's been a while since I posted anything, I'm sorry!

I've been busy working with Windows 7 and Microsoft Surface touch-computing. To that end, I needed to get access to some of the new Windows 7 APIs in managed code ... which isn't supported yet (but is coming).

So I built an interop library to access:

  • Scenic Ribbon (native Win32 ribbon) in Windows Forms
  •  Native WM_TOUCH and WM_GESTURE messages
  •  Sensor API
  •  Shell APIs (jump lists, thumbnail buttons, libraries)
One note: I make no guarantee that everything is correct (it's hard to do that on a shifting beta with minimal docs, but in addition I'm not sure I've gotten 100% coverage with everything anyway). Here's the interop library with source code:

Windows 7 Beta 1 Interop Library for .NET 2.0

I'll be posting more details and samples a bit later, here's a couple to get you started.

Here's a simple example of using the Scenic Ribbon and native touch support to create a (very) simple Windows Forms finger
 paint program:

touch_img.jpg

  Multi Touch example with Windows Forms

Here's a simple example of using the gestures and library support in a WPF application. It grabs all the directories in your Pictures Library and then shows you each picture and lets you use the swipe gesture to move between then, pinch to scale and of course, rotate.

gesture_img.jpg

Gesture example with WPF

Both of these samples work with the HP Touchmate (and multi-touch drivers) and Windows 7 Beta 1. Have fun! -mark
Thursday, January 29, 2009 12:02:21 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Code | WPF
# Thursday, November 13, 2008

I've been playing with the Silverlight toolkit (released at PDC) this week and ran across a pretty nasty edge case related to HeaderedContentControl and the implicit style manager.  If you create something like this, where the Header is set to a Visual of some kind:

<UserControl x:Class="SilverlightPrototype.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">

<StackPanel x:Name="LayoutRoot" Background="White">
   <Button Click="Button_Click" Content="Change Style" />
   <Controls:HeaderedContentControl>
      <Controls:HeaderedContentControl.Header>
         <TextBlock Text="Header" Foreground="DarkBlue" FontWeight="Bold" />
      </Controls:HeaderedContentControl.Header>
      <TextBlock Text="Body" />
   </Controls:HeaderedContentControl>
</StackPanel>

</UserControl>

And then you change the style of the headered control when the button is clicked:

private void Button_Click(object sender, RoutedEventArgs e)
{            
    Uri uri = new Uri(@"SilverlightPrototype;component/theming/simplestyle.xaml", UriKind.Relative);
    ImplicitStyleManager.SetResourceDictionaryUri(LayoutRoot, uri);
    ImplicitStyleManager.SetApplyMode(LayoutRoot, ImplicitStylesApplyMode.OneTime);
    ImplicitStyleManager.Apply(LayoutRoot);
}

Where the style is just a simple ContentPresenter or ContentControl for the header and the body:

<Style TargetType="Controls:HeaderedContentControl">
   <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Controls:HeaderedContentControl">
           <StackPanel Orientation="Horizontal">
              <ContentPresenter Content="{TemplateBinding Header}" ContentTemplate="{TemplateBinding HeaderTemplate}" Margin="10" />
              <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Margin="10" />
           </StackPanel>
        </ControlTemplate>
     </Setter.Value>
   </Setter>
</Style>

Silverlight will crash deep in the DependencyProperty.SetValue code with an ArgumentException indicating that the TextBlock for the header is invalid.  The issue appears to be that the TextBlock defined as the header content is already part of the visual tree and therefore cannot be bound to the new control template.  Content works fine so there is some other path being taken for that property.

The workaround is pretty easy, just use a non-visual in the header and then supply a DataTemplate to give it the appropriate visual tree.  Silverlight will re-create the visual tree each time from the data template so we don't have the reuse issue:

<StackPanel x:Name="LayoutRoot" Background="White">

<StackPanel.Resources>
   <!-- Header works as long as template is supplied - i.e. non-visual element applied directly to header -->
   <DataTemplate x:Key="HeaderTemplate">
      <TextBlock Foreground="DarkBlue" FontWeight="Bold" Text="{Binding}" />
   </DataTemplate>
</StackPanel.Resources>

<Button Click="Button_Click" Content="Change Style" />

<Controls:HeaderedContentControl HeaderTemplate="{StaticResource HeaderTemplate}">
   <Controls:HeaderedContentControl.Header>
      <sys:String>Header Text</sys:String>
   </Controls:HeaderedContentControl.Header>

   <TextBlock Text="Body" />
</Controls:HeaderedContentControl>

</StackPanel>

If you need more than a string, then just define an object and assign that instead - for example:

class HeaderStuff
{
   public string Text { get; set; }
   public bool IsChecked { get; set; }
}

<DataTemplate x:Key="HeaderStuff">
   <StackPanel>
      <Rectangle Fill="Blue" Stroke="Yellow" Width="50" ... />
      <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Text}" />
   </StackPanel>
</DataTemplate>

...

<Controls:HeaderedContentControl HeaderTemplate="{StaticResource HeaderStuff}">
   <Controls:HeaderedContentControl.Header>
      <me:HeaderStuff IsChecked="True" Text="This is a checkbox" />
   </Controls:HeaderedContentControl.Header>
</Controls:HeaderedContentControl.Header>


Thursday, November 13, 2008 9:42:01 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET
# Wednesday, November 12, 2008
One of the coolest new debugging features included with VS2010 CTP1 is the management of WPF event traces directly in the IDE.  With this feature you can turn specific event traces on and off and have them show up in the debug window.  The default setting is to just show data binding errors - the existing behavior.  But now you can view resource lookups, routed event creation, etc. Here's the dialog:


Wednesday, November 12, 2008 1:06:04 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | WPF
# Monday, September 22, 2008
Thanks to all who attended - it was great to meet all of you and hang out until the wee hours and play Rock Band! 

Here are the demos from the class - I removed most of the binaries to bring it down to a reasonable size.

I also put the pictures online at Flickr

Thanks again everyone!


Monday, September 22, 2008 8:33:32 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code
# Friday, September 12, 2008

One thing that's kind of cool in WPF is that you can use brushes to fill almost anything and that there are some really cool brushes in the toolkit.  It always blows people away when you show them a piece of text filled with a live video complements of a Visual Brush.

 

But, unfortunately text doesn't have a stroke property - only a fill so you can't add an edge to it.  You can layer another piece of text under it, but often it doesn't quite match up size-wise when you do this.  The solution is to convert the text to a Path which has both a fill and stroke and it turns out it's pretty easy to do.

 

If you just have one piece of text you are better off using Blend's "Convert to Path" option -- it will do the one-time conversion for you and you can just insert the shape into your UI.  If you have more than one element though it can be tedious, and it doesn't work at all for dynamic pieces of text - that's where this TextPath class comes in handy.   With it you can create text like this:

 

 

Notice how the text is outlined in a different color -- any brush could be used so you could do wacky things like have the "WPF" part be ringed in fire (using the Dreamscene fire video for example). 

 

The class is dead simple to use, it's a Shape class so you can simply insert it right into your XAML and set the font properties and text:


 

<StackPanel Orientation="Horizontal" TextElement.FontWeight="Bold" TextElement.FontSize="72pt">
       
<me:TextPath FontFamily="Consolas,Courier New" Margin="5" Text="WPF"
                      
StrokeThickness="3" Fill="Gold" Stroke="Red" /> 
        
<me:TextPath FontFamily="Balloon" Margin="5" Text="Rocks" StrokeThickness="3" Stroke="Black">
          
<me:TextPath.Fill>
             
<ImageBrush ImageSource="rocks.jpg" />
           
</me:TextPath.Fill>
       
</me:TextPath>
</StackPanel>

 

Notice it uses the same font dependency properties as all other text-based framework elements - that allows us to inherit the property values which is useful. 

 

Here's the sample project which full source code:  OutlineTextTest.zip (1.54 MB)

Friday, September 12, 2008 10:52:21 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF

We've seen how to programatically control focus and that's all great stuff, but one thing I like to do with WPF is see how much of the repetitive or UI-specific code I can move into the XAML and keep out of the code behind.  We can use the FocusManager.FocusedElement property to shift focus in XAML but it only works when the element exists in the main XAML file.  If you use UserControls it turns out that the approach doesn't work because that element is loaded separately and not available when the initial focus is being determined.

In my specific case, I have a wizard-style application which utilizes a TabControl to move between the pages.  The first page looks like this:

The XAML layout for window1.xaml looks something like this:

<TabControl x:Name="Pages" SelectedIndex="0">
   <FocusTest:Page1 />
   <FocusTest:Page2 />
   <FocusTest:FinalPage />
</TabControl>

What I want is to have focus immediately positioned within the first text box but it turns out that you can't get WPF to do this directly from XAML - because the TextBox isn't a direct descendent of Window - it's part of the Page1 user control.  You can try putting the focus shift into the user control but it turns out that it won't work there either - it's got to be assigned to the focus scope which is the window.

So it might seem we are stuck with adding code behind logic (blech!) but all is not lost!  When I hit situations like this, I try to think about how to solve the problem generically so I can reuse my solution.  In this case, I decided to build a MarkupExtension to locate the first focusable element descendent.

If you are not familiar with markup extensions, they are a corner piece in the XAML extensibility story.  They allow for dynamic property assignment - where the value is determined at runtime vs. XAML compile time.  That's exactly what I need here - I want to find that TextBox at runtime and shift focus to it - just like I would have done in the code behind.

Creating a markup extension is trivial - you just extend the MarkupExtension base class and implement the ProvideValue method.  In this case, when provide value is called, I have to do several steps:

  1. If the element we are bound to is not loaded yet, we need to wait for it.  We won't be able to find the child in the visual tree if the parent isn't yet loaded.
  2. Once it is loaded, search the children and find the first control we can give focus to.  That means, the control is visible, focusable and enabled.
  3. Assign logical focus to the new control in the closest focus scope parent, or just return the value if the property being assigned to is not FocusManager.FocusedElement.

I decided to try to make a generic markup extension that could be used outside my scenario so I added a little bit of code to see if we are assigning to FocusManager.FocusedElement and act differently in that specific case - otherwise the extension just returns the value.

With this new extension, I can now add a single line of code to each user control:

<UserControl x:Class="FocusTest.Page2"
   xmlns:FocusTest="clr-namespace:FocusTest"
   FocusManager.FocusedElement="{FocusTest:FirstFocusedElement}">

Now, when I run the application, focus is always assigned to the first control it can be assigned to.  It turns out that I can go one step better and always assign focus when the page becomes visible in my wizard - remember we have to wait for the control to finish loading to find the element.. this is done by hooking the FrameworkElement.Loaded event.  This event is raised each time the TabControl shifts to a new tab - so if we never unhook our handler, our focus management code is called each time the tab page becomes visible.  This might not be the required behavior so I added a simple property to the markup extension called OneTime to control that behavior.

There's a bit too much code to blog here, but if you want to try this out yourself, here's the test project.. feel free to use this however you like.  FocusTest.zip (17.88 KB)

Update: Andrew Smith pointed out that the code would assign focus to a focus scope if it ran across one - which could happen if you have a toolbar or menu present in the UI.  I didn't in the sample (or in my production app) but I could certainly see that being a common reality.  I changed the above code to deliberately skip focus scopes and their children and keep going down the tree until it finds the first child.  Thanks Andrew!

Friday, September 12, 2008 7:49:20 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Thursday, September 04, 2008

In the last post, I wrote about how focus is generally managed in WPF - we have focus scopes to track a single element within that scope for logical focus, and then one of those elements is given physical, or keyboard focus.

Now, let's talk a little about how you can influence that programatically.  First, you can always determine which element has logical focus in your application through the FocusManager.GetFocusedElement method -- pass it the window in question and it will return which element has logical focus in that window.  Remember that logical focus != keyboard focus at all times -- toolbars and menus track their own focus so if you are currently interacting with a menu then the menu has physical focus.  But in general, the following code will tell you which element WPF thinks has focus in the window:

IInputElement focusedElement = FocusManager.GetFocusedElement(thisWindow);

To determine whether this element has keyboard focus, we can check the IsKeyboardFocused property - if it's set to true, then that element currently has the keyboard focus (as well as being the logical focus for that focus scope).

Keyboard focus is most often set through runtime activity - the user clicks on an element, or uses the TAB key to move around the UI.  You can also set it programatically a couple of ways.  First, there is a Keyboard class in WPF which exposes several methods and properties.  There is a Keyboard.FocusedElement read-only property which returns the current keyboard focused element, and there is a Keyboard.Focus method which attempts to change keyboard focus.  It returns the element that now has focus - so you can check to see if your request was fulfilled or ignored.  So, for example, you can change focus during your application initialization:

void OnLoaded(object sender, RoutedEventArgs e)
{
   Keyboard.Focus(firstTextBox);
}

Notice that we uses the Loaded event - this is because no focus requests will be accepted prior to the element being initialized and loaded.  That's the first place in the application where you can make focus changes.

When would setting focus fail?  Well, it can fail for a lot of reasons, but the most common are:

  1. The element has Focusable = false
  2. The element has Enabled = false
  3. The element has IsVisible = false
  4. The element has not been loaded yet
  5. The currently focused element will not release focus.

That final one is important, changing focus involves potentially taking it away from an existing element - they receive a PreviewLostKeyboardFocus and LostKeyboardFocus event.  If they handle the preview event, focus will not change.

You can also manipulate focus through programatic keyboard navigation - simulating the user pressing TAB to cycle through the focusable elements.  This is controlled through the KeyboardNavigation class which is used when the user presses a key that changes focus (TAB, SHIFT+TAB, Up, Down, etc.).

Controls can set a TabIndex property assignment which determines the tabbing order.  The default is to tab through them in order of declaration.  You can also use the KeyboardNavigation.TabIndex attached property which works for any element - not just controls.

To control navigation, the KeyboardNavigation class has an attached property TabNavigation allowing you to change how navigation occurs within a container.  You can set it to:

  1. Continue - each focusable element receives focus and the container is exited when the edge is reached.
  2. Cycle - focus does not leave the container but wraps around the edges
  3. Once - the container itself is treated as a single focusable element where only the first child receives focus
  4. Local - uses TabIndex locally within the container - independant of any outside elements.
  5. Contained - focus statys in the container but does not wrap (stays at edges when top/bottom are reached)
  6. None - no keyboard navigation allowed in the container

The default is Continue, but you can set the attached property on any element to change it for that element and any children. To see this in action, paste the following into your XAML editor of choice and change the ComboBox while tabbing through the TextBlock elements.

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="Simple Focus"
>

<Window.Resources>
   <Style TargetType="TextBox">
      <Setter Property="Margin" Value="10" />
      <Setter Property="Width" Value="100" />
   </Style>
</Window.Resources>

<StackPanel>
   <ComboBox x:Name="tabStyles" SelectedIndex="0" Focusable="False">
      <sys:String>None</sys:String>
      <sys:String>Continue</sys:String>
      <sys:String>Cycle</sys:String>
      <sys:String>Once</sys:String>
      <sys:String>Local</sys:String>
      <sys:String>Contained</sys:String>
   </ComboBox>

   <TextBox TabIndex="1" />
   <TextBox TabIndex="2" />
   <StackPanel
       
KeyboardNavigation.TabNavigation="{Binding ElementName=tabStyles,Path=SelectedItem}">
      <TextBox TabIndex="1" />
      <TextBox TabIndex="2" />
   </StackPanel>
</StackPanel>
</Window>

You can have the system ignore specific elements (but still allow them to have focus) by setting the KeyboardNavigation.IsTabStop="false" attached property.  This will cause keyboard navigation to "jump" over the control as if it were not present.

Three methods are exposed by UIElement and FrameworkElement to programatically shift focus: Focus, MoveFocus and PredictFocus.

To force focus to a specific element, you can call Focus on it.  For example, above we set the keyboard focus by calling Keyboard.Focus(), but the same effect can be achieved like this:

void OnLoaded(object sender, RoutedEventArgs e)
{
   firstTextBox.Focus();
}

This method attempts to set focus using Keyboard.Focus().  If that fails, but the element is Focusable and enabled, it finds the focus scope for the element and sets logical focus there (so that keyboard focus will eventually end up on the control).

FrameworkElement.MoveFocus is used to change the keyboard focus in the application using the same algorithm as the TAB traversal.  You pass in the direction (specified through a TraversalRequest object) and the method returns true/false to indicate success.   Under the covers it actually uses the KeyboardNavigation class, but it's an easy way to push focus around the window:

firstTextBox.MoveFocus(
           
new TraversalRequest(FocusNavigationDirection.Next));

PredictFocus works the same way, but instead of actually shifting focus, it returns what would be the focused item if you were to execute MoveFocus.

So, up to this point, we've seen a lot of code to change focus.  However, the most common request is to set initial focus to a specific control - remember that WPF doesn't do that by default.  You can do it in code, just like the above example where we use the Loaded event.  Or, it turns out you can do it in XAML too.  The key to remember is that the FocusedElement of the main focus scope (the Window) is the one that will get initial focus.  That is (by default) null, but you can set it in XAML using the attached property syntax.  Using the above XAML example, we can supply a name for one of the TextBox controls and then a little data binding magic to set that onto the Window:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="Simple Focus"
        FocusManager.FocusedElement="{Binding ElementName=tb2}">
  ...
    <TextBox TabIndex="1" />
    <TextBox x:Name="tb2" TabIndex="2" />
  ...
</Window>

Now when you run the application, focus is placed into the second text box in the window.  This technique works great as long as the element you want to assign focus to is declared here in the same XAML file.  However, a popular way to develop WPF applications is to separate out chunks of UI into separate UserControls.  When you do that, the above trick fails -- even if you put the FocusManager.FocusedElement binding into the UserControl!

How we solve that is what we'll look at in the next post!  Stay tuned...

 

 


Thursday, September 04, 2008 3:44:44 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Tuesday, September 02, 2008

Focus Types

As you may know, in WPF there are two types of focus: logical focus and keyboard focus. 

Keyboard focus is the easiest to grasp: the element with keyboard focus is where any keystrokes will end up.  Only one element can have keyboard focus at any particular time, and it’s possible that no element currently has keyboard focus (this happens most commonly when the application itself is not the activated application).

Logical focus is a little murkier.  Logical focus represents where keyboard focus could go within a group of elements.  There may be multiple elements with logical focus within the application and one of them likely has keyboard focus.  Having keyboard focus automtically indicates logical focus but not vice-versa.

This distinction is modeled after Win32 itself -- each thread has one HWND it has identified to have focus but only one of them really has input focus at any given point in time.

In WPF, logical focus is tracked and managed by a Focus Scope.  A focus scope is created by certain elements to keep track of which element should have focus.  There can be multiple focus scopes within the application – each identifying a single element that has logical focus.   Focus scopes are created and managed by the FocusManager class.  It exposes two attached properties and the requisite static method wrappers to access them:

IsFocusScope - determines whether the current object is a focus scope.
FocusedElement - returns which element child of the given focus scope object has logical focus.

It also exposes a handy method to find the focus scope for a given element - GetFocusScope

So what creates a focus scope and why do we need more than one?  Well, the elements in WPF that create focus scopes by default are Window,  Menu, ContextMenu and ToolBar.  The reason we need more than one is to ensure your application works the way you expect it to.  When you are typing in a TextBox and click a menu item, you really want focus to return to the original TextBox once the menu is dismissed.  That’s focus scopes in action – the Window maintains logical focus in the TextBox and when you click on the menu, keyboard focus shifts to the menu.  Since it maintains its own focus scope, it has its own logically focused element that WPF sets focus to (the menu and menu items in this case).  Once you shift back to the window, keyboard focus moves back to that focus scope’s logical focus: the text box.  Without focus scopes to track the original focus holder, WPF wouldn't know where focus should go.

Focus scopes are also critical to command routing – often execution of commands depends upon focus.  Some commands become active because a specific control which has a handler for the command has focus.  Without focus scopes, we could not have menu items and toolbar buttons initiate those commands – they would steal focus away from the target, making the command unavailable.  However, when WPF encounters a focus scope it checks the element that has logical focus in that scope to see if it can handle the command.  If not, the command continues routing up to the parent of the focus scope.

To show all of this behavior, I have rigged up a sample application with two windows.  The first is a traditional text editor window with a menu and toolbar and a RichEdit control for the content.  It looks like:

ste001.jpg

Forgive my 5-minute graphics for the buttons – I just threw them together in Visual Studio, a real project would use Blend to generate the graphics. 

Regardless of it's look, the application functions the way you expect – you can type in the text field, click buttons and select menu choices to Open, Cut, Copy and Paste content.  The Cut/Copy/Paste commands are only available when the TextBox is in the appropriate state:

Cut:       TextBox has focus and has some text selected.
Copy:    TextBox has focus and has some text selected.
Paste:    TextBox has focus and text exists on the clipboard.

This is all an artifact of the routed command system in WPF – the TextBox has command handlers registered for ApplicationCommands.Cut, ApplicationCommands.Copy and ApplicationCommands.Paste and when it has focus (and the above criteria is met) those commands could be executed.

When you click on a button or a menu choice, it executes the command it is associated with and WPF decides which handler should be called.  This normally involves walking the visual tree:

ste002.jpg

In this case, if the menu item for “Cut” were selected, it would start looking at the menu, then move up the tree consulting each parent and looking for a CommandBinding to handle the command.  If that were the whole story then the Cut command would never happen because nothing in the visual tree above the menu has a binding to execute the Cut command.  But, of course,  it’s not the whole story – in this case, WPF sees that the Window is a focus scope and so it gets the logically focused element from the Window and looks for a CommandBinding there.  That happens to be our RichTextBox – which is where the command ultimately gets handled. 

To see all of this in action, the second part of the application is a focus scope monitor window. 

ste004.jpg

It shows all the known focus scopes and what the active focused element is, as well as whether that element has keyboard focus.  The window is live so as you click around in the text editor you can see focus shifting and changing.  The element with keyboard focus is the Paste menu item – notice that the rich text box is the logically focused item for “Window1” but does not have keyboard focus.  Once you select the menu choice (or cancel) then keyboard focus shifts back to Window1 which assigns it to the RichTextBox.

ste003.jpg

If you'd like to play with this sample, you can get the full source code here.

In the next blog post, I’ll write about how you can programmatically assign and control focus in code and XAML.

Tuesday, September 02, 2008 2:55:39 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Monday, September 01, 2008

Recently I was involved in a project where we needed to build a multi-step input application where each step showed progress and you could proceed forward and backward through the pages.  I looked at the Navigation support in WPF (which is nice) but ultimately decided to model it around a styled TabControl – each page being a tab and the progress noted through the custom TabItem visuals across the top.  It all works great and looks fabulous.

One of the bugs that was logged against the application and got assigned to me was related to focus – the initial keyboard focus was not being placed into the first control, instead it appeared that nothing had focus which is totally accurate.  Those that are new to WPF might be surprised that it does not assign initial focus to any particular child control – you must deliberately click or tab into a control to give it focus.   You can, of course, also assign focus programmatically but it turns out to not be as easy as you’d think.  In fact, I encountered several nasty gotchas trying to get it to work exactly the way I wanted it to. 

My frustrations with focus and how WPF manages it have resulted in this set of blog posts

Part 1:  Focus Basics
Part 2:  Setting focus in code and XAML

Part 3:  Getting a little smarter – setting focus to the first focusable control
Part 4:  Setting focus to template items

Monday, September 01, 2008 2:07:39 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Monday, August 25, 2008
Business validations in WPF
Monday, August 25, 2008 9:45:20 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Friday, August 01, 2008

Thanks to all who came - it was fast-paced but a lot of fun to hang with all of you.  Here are the:

demos.zip and labs.zip

Friday, August 01, 2008 6:20:02 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET
# Friday, July 25, 2008
It's been a long time since I blogged anything specific on WPF -- I've been doing a lot of it lately, along with some Silverlight.  Recently I was experimenting with dragging tabs around on a TabControl at runtime.  My end goal is really to implement it with Silverlight 2, but I've found it's much easier to prototype things in WPF and then port them over because the debugging experience is easier with WPF.

I didn't want to create derived implementations of any classes - I wanted something that was non-intrusive to my code so I decided to use an attached property.  Attached properties are basically property values "attached" to a class at runtime - where the property itself isn't defined on the target but instead on some other type.  The cool thing about attached properties is they can register a change notification handler which gives them a reference to the object they are being placed on -- this is how the Spell Checker works with the TextBox in WPF.  All the code for the spell checking lives in the SpellChecker class and when you add the SpellCheck.IsEnabled property onto the TextBox, it adds handlers to the TextBlock's TextChanged property and adds all the nifty spell checking goodness without changing the code in TextBox.

Back to my drag/drop prototype.  So with this code, I can add the property to any TabControl and get a nice, simple drag/drop experience.  It's far from complete - it would be cooler if the tabs moved around as you dragged (they don't), but I was just prototyping here.

Here's the code:




using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace WpfApplication1
{
    public class DragDropTabManager
    {
        private static readonly DependencyProperty ManagerProperty =
            DependencyProperty.Register(typeof (DragDropTabManager).ToString(), typeof (DragDropTabManager),
                                        typeof (DragDropTabManager));

        public static readonly DependencyProperty EnabledProperty = 
            DependencyProperty.RegisterAttached("Enabled", typeof(bool), 
                                                typeof(DragDropTabManager),
                                                new PropertyMetadata(false, DDTM_EnabledChanged));

        private static void DDTM_EnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var tc = d as TabControl;
            if (tc != null)
            {
                var oldValue = (bool) e.OldValue;
                var newValue = (bool) e.NewValue;

                if (oldValue == true && newValue == false)
                {
                    var ddtm = tc.GetValue(ManagerProperty) as DragDropTabManager;
                    if (ddtm != null)
                    {
                        tc.PreviewMouseDown -= ddtm.TabItem_PreviewMouseDown;
                        tc.SetValue(ManagerProperty, null);
                    }
                }
                else if (oldValue == false && newValue == true)
                {
                    var ddtm = new DragDropTabManager();
                    tc.SetValue(ManagerProperty, ddtm);
                    tc.PreviewMouseDown += ddtm.TabItem_PreviewMouseDown;
                }
            }
        }

        public static bool GetEnabled(DependencyObject obj)
        {
            return (bool)obj.GetValue(EnabledProperty);
        }

        public static void SetEnabled(DependencyObject obj, bool value)
        {
            obj.SetValue(EnabledProperty, value);
        }

        private bool isMoving;
        private TabItem movingTabItem;
        private TabItem lastTab;
        private Point ptStart;

        void TabItem_PreviewMouseDown(object sender, MouseEventArgs e)
        {
            var ti = e.Source as TabItem;
            if (ti != null && e.LeftButton == MouseButtonState.Pressed)
            {
                var tc = ti.Parent as TabControl;
                if (tc != null)
                {
                    tc.MouseMove += tc_MouseMove;
                    tc.MouseLeftButtonUp += tc_MouseLeftButtonUp;

                    ptStart = e.GetPosition(tc);
                    movingTabItem = ti;
                }
            }
        }

        void tc_MouseMove(object sender, MouseEventArgs e)
        {
            var tc = sender as TabControl;
            if (tc == null)
                return;

            Point pt = e.GetPosition(tc);

            if (isMoving == false)
            {
                if (Math.Abs(pt.X - ptStart.X) > 10)
                {
                    movingTabItem.IsHitTestVisible = false;
                    movingTabItem.RenderTransformOrigin = new Point(.5, .5);
                    movingTabItem.RenderTransform = new TranslateTransform(0, 0);
                    tc.Cursor = Cursors.Hand;
                    Panel.SetZIndex(movingTabItem, 1);
                    isMoving = true;
                    tc.CaptureMouse();
                }
                return;
            }

            TabItem newPos = FindTabItem(tc, pt);
            if (newPos == null)
                tc.Cursor = Cursors.No;
            else
            {
                lastTab = newPos;
                var xform = movingTabItem.RenderTransform as TranslateTransform;
                if (xform != null)
                    xform.X = pt.X - ptStart.X;
                tc.Cursor = Cursors.Hand;
            }
        }

        void tc_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var tc = sender as TabControl;
            Debug.Assert(tc != null);

            tc.ReleaseMouseCapture();
            tc.MouseMove -= tc_MouseMove;
            tc.MouseLeftButtonUp -= tc_MouseLeftButtonUp;

            if (isMoving == true)
            {
                isMoving = false;
                tc.Cursor = Cursors.Arrow;
                movingTabItem.RenderTransform = null;
                movingTabItem.IsHitTestVisible = true;

                Panel.SetZIndex(movingTabItem, 0);

                if (lastTab != null)
                {
                    if (lastTab != null && movingTabItem != lastTab)
                    {
                        int targetIndex = tc.Items.IndexOf(lastTab);
                        tc.Items.Remove(movingTabItem);
                        tc.Items.Insert(targetIndex, movingTabItem);

                        movingTabItem.Focus();
                    }
                }
            }
            movingTabItem = lastTab = null;
        }

        private static TabItem FindTabItem(UIElement parent, Point pt)
        {
            var fe = parent.InputHitTest(pt) as FrameworkElement;
            while (fe != null && fe.GetType() != typeof(TabItem))
                fe = VisualTreeHelper.GetParent(fe) as FrameworkElement;
            return fe as TabItem;
        }
    }
}
Friday, July 25, 2008 3:09:45 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code | WPF
# Wednesday, July 23, 2008

It's been a while since I updated the ATAPI assembly, I've fixed a couple of minor bugs that were reported and updated the samples to compile with VS2008.  I've also added two new events onto the TapiPhone class so you can see state changes and button presses - somehow I missed that when I added the phone support.

Finally, there's now online documentation available at

http://www.julmar.com/atapi_help/index.aspx

You can download the updated assembly, help file and samples from

http://www.julmar.com/tapi/atapinet.zip

Have fun!

Wednesday, July 23, 2008 12:54:45 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Tapi
# Tuesday, May 13, 2008

I often show students in my classes how to add ILDasm to their tools menu - it's handy because you can then click on ILDasm and it will open the current module allowing you to look at the manifest, IL, etc.

1. Select Tools | External Tools. You’ll get the tools dialog:

Tools1.png

2. Enter ILDASM for the title and set the Command to the path for ILDASM. The path varies a bit from version to version of Visual Studio. For VS2008 you will find it at C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\ildasm.exe

3. Click the button to the right of Arguments and select "Target Path" and select the "Use Output Window" checkbox.



5. You should now be able to access Tools | ILDASM.

One student in another class recently asked how to get a keyboard shortcut to this. Michael Kennedy - our resident VS.NET shortcut king showed exactly how to do this. It turns out to be really simple -- go to Tools | Options and select Keyboard. Then 1,2,3:


Tuesday, May 13, 2008 2:13:09 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET
# Tuesday, May 06, 2008


Last month, my colleague, Pinku Surana, wrote an article about .NET AppDomains and how they can be used to provide component isolation and make your applications more reliable.  If you missed it, you can read the Developments archives on Developmentor’s website.   This month, I’d like to continue exploring reliability and extensibility by introducing you to a new framework included with .NET 3.5: The Managed Add-in Framework (MAF), sometimes referred to as System.AddIn.

Developers (and managers) have long desired a way to easily create extensible applications that allow new features to be added without jeopardizing the stability of the existing code base.  The .NET framework has provided the underlying support to accomplish this from the very beginning through the reflection API and AppDomain support Pinku examined last month.  MAF builds on that fundamental support to provide a higher-level service that allow you to dynamically discover, load, secure and interact with external assemblies used to provide features for your application.  Several common architectural requirements are made trivial with MAF:

1)   Isolate aspects of your code for security reasons or partial-trust scenarios.

2)   Allow business partners to extend your application safely without access to the source code; Adobe Illustrator is a great example of this style of application.

3)   Separate volatile sections of your application out – where depending on the customer the application needs to execute different sets of code.

4)   Add or change code without unloading the application – for example pay-to-play scenarios, or where you need to update an assembly but the application must continue to run.

5)   Develop and evolve different sections of the application in parallel without any fear of destabilizing one based on the other.

If any of these scenarios sound like something you could utilize in your application then you should know about MAF!

At the center of the MAF-based application is the pipeline.

The Pipeline

Communication between add-ins and the host application is strictly regulated by the pipeline.  The pipeline is dynamically created by MAF through a set of loosely-coupled components which are used to version, marshal and transform the data as it passes back and forth between the host and each loaded add-in.

image001.png

Each section of the pipeline is contained in a separate assembly, loaded as necessary to manage the specific add-in.  MAF discovers each component and then loads them on request using reflection.   

For reliability, MAF allows optional isolation boundaries to be created between the add-in and host – everything to the left of the contract is loaded into the main (host) AppDomain and everything to the right loaded into a newly created AppDomain which has its own security permission set.  The isolation can also be done through cross-process calls if true process-level isolation is necessary.  Under the covers, the system uses traditional remoting calls to do the work of marshaling calls back and forth.

Breaking down the pipeline, there are three main parts starting in the center with the contract.

Contract

As you might expect, MAF is based on interface contracts.  Interfaces allow classes in an application to be loosely coupled, reducing the risk when changes are made between dependent sections of the code.   The interface contract is shared between the host and add-in and once it has been established, it should never be changed. 

Consider the simple example of a translator program.  The host will expect to load one or more translator add-ins that will do some work on an inbound string and return the results.  To accomplish this, I might create an ITranslator interface that looks like:

[AddInContract]

public interface ITranslator : IContract

{

   string Translate(string input);   
}


Notice that the interface derives from IContract.   This is a requirement for add-in contracts and is what will be used to provide marshalling support when the pipeline is established.  We also need to decorate the interface with the [AddInContract] attribute – this is the marker used by MAF to identify the contract when it is dynamically constructing the pipeline.  Both of these types come from the System.AddIn.Pipeline namespace in System.AddIn.Contract.dll.

Views

Moving to the edges, we find the views.  This is the code that the add-in and host directly interact with.  It represents a host or add-in specific “view” of the contract and, like the contract, is contained in a separate assembly.

Both of the view classes will echo the structure of the contract, but not actually be dependent upon the contract.  For example, our host side view might look like this:

public abstract class TranslatorHostView

{

   public abstract string Translate(string input);
}


The view is commonly exposed as an abstract class to make it look more natural when used by the host, but an interface will work just as well.  The host uses the view directly when communicating with any add-in based on the contract.

On the add-in side, we have an almost identical class – except we decorate this type with the [AddInBase] attribute so MAF knows which side of the pipeline this view is for (the add-in).   This is located in the System.AddIn.Pipeline namespace in the System.AddIn assembly.

When we create each add-in, the implementation will use this type as the base class.

[AddInBase]

public abstract class TranslatorAddInView

{

   public abstract string Translate(stringinp);
}

Adapters

The last piece of the pipeline is the adapters.  The adapters play a very special role in the pipeline – they are the glue that binds the contract to the view: implementing lifetime management and any necessary data conversion between the two ends. 

It may seem redundant to have this class, but by separating the view from the contract we introduce version tolerance into our architecture – the host can version independently of the add-in and vice-versa.  Depending on the situation, the adapters can be as simple as a pass-through class, or can provide higher-level services to allow non-serializable types to be marshaled across the isolation boundaries.

On the host side, the adapter will implement the view (remember it is either an interface or abstract class).  It will be passed a reference to the contract in the constructor and it is responsible for connecting the two together.

[HostAdapter]

public class TranslatorHostViewToContract :  

                     TranslatorHostView

{

   ITranslator _contract;

   ContractHandle _lifetime;

 

   public TranslatorHostViewToContract(

              ITranslator contract)  

   {

      _contract = contract;

      _lifetime = new ContractHandle(contract);

   }

 

   public override string Translate(string inp) 

   {

      return _contract.Translate(inp);
   }
}


In this simple example, the code caches off the contract interface.  This is a remoting proxy to the actual loaded add-in.  The adapter then implements the Translate method and passes it forward to the contract for implementation.  If we had non-serializable types, then the adapter would be responsible for converting them into something that was serializable. 

It also provides some lifetime management for the contract.  Because the contract is a remoting proxy and is likely running in a separate AppDomain (or even process) we have to be concerned with how long it lives.  MAF provides all the support for this through the ContractHandle class.  Most of the time, all you will need to do is store a ContractHandle in your host adapter and then pass it the inbound contract to wrap in your constructor.

Finally, in order for MAF to identify this class, it must be decorated with the [HostAdapter] attribute from the System.AddIn.Pipeline namespace out of the System.AddIn.dll.

The add-in side looks very similar, but does the opposite: it makes the add-in view look like the contract.

[AddInAdapter]

public class TranslatorAddInViewToContract :

                  ContractBase, ITranslator

{

   TranslatorAddInView _view;

 

   public TranslatorAddInViewToContract(

             TranslatorView view)  

   {

      _view = view;

   }

 

   public string Translate(string inp)  { 

      return _view.Translate(inp); 

   }

}

 
MAF passes the view to the constructor and the class caches the reference off in a field.  It implements the contract (ITranslator) and ContractBase which provides the implementation of the IContract interface for us (remember this was a required interface on our contract).  As the host makes calls to the contract interface, this class will translate those calls to the add-in view, which as you will see is the implementation provided by the add-in itself.  Note how the [AddInAdapter] attribute is used to mark this class so MAF can discover it.

If it seems like all the above is a lot of repetitious, boilerplate code well.. you’re right!  To make it easier on the developer to create the pipeline components, the MAF team has created a pipeline builder available at http://www.codeplex.com/clraddins.  It takes the contract assembly and then generates the views and adapters from it:

image003.jpg

Creating an add-in

Once the pipeline pieces are built you can create add-ins.  Each add-in provides an implementation of the abstract add-in view.  For example, we might provide a BabelFish add-in for universalized translation:

[AddIn(“BabelFishTranslator”,

       Description=“Universal translator”,

       Version=“1.0.0.0”, Publisher=“Zaphod Beeblebrox”]

public class BabelFishAddIn : TranslatorAddInView

{

   public string Translate(string input)

   {

     ...

   }
}


The add-in implements the AddInView, providing a concrete implementation of the Translate method.  It is decorated with the [AddIn] attribute that allows it to provide a name, version, description and other data the host can use to decide whether it is a useful translator.

Putting the pieces together – the directory structure

To properly identify each of the components necessary, MAF enforces a particular directory structure you need to follow for deployment.  Each piece is stored in a sub-directory off the root of the pipeline directory (this is typically the APPBASE where the host executable is stored). 

image006.png

The directory names are required, but not case sensitive – each directory holding a single piece of the pipeline that MAF will load dynamically when it is loading the add-in.  The host-side view is always located in the same directory as the host executable itself so it does not need a dedicated directory.  When creating your Visual Studio project, it is important to set the output directories appropriately so that you create the above directory structure.  In addition, all references between the components should be marked as CopyLocal = “false” in Visual Studio to ensure a local copy of the assembly isn’t placed into the sub-directory: 

image008.png

Discovering and loading add-ins from the host

The last piece of the puzzle is the actual loading of add-ins from the host.  This is done in three basic steps:

1.     Identify and catalog the add-ins

2.     Retrieve the list of specific add-ins based on view or name

3.     Activate and use the add-in

The first step is to identify the available add-ins for the host.  This is done through the System.AddIn.AddInStore class:

string[] errorList = AddInStore.Rebuild(

         PipelineStoreLocation.ApplicationBase);

 

Calling Rebuild forces MAF to walk the directory structure and create the pipeline database.  It stores this information in the pipeline root directory and returns a list of errors, if any occur.  The most common errors are missing pipeline components – where MAF is unable to locate some required portion of the pipeline such as a View or Adapter.

Next, the host will retrieve a list of add-ins based on the host view through the FindAddIns method – these will be the add-ins conforming to a specific contract (whatever the view/adapter is bound to):

Collection<AddInToken> addinTokens = AddInStore.FindAddIns(

                typeof(TranslatorHostView),

                PipelineStoreLocation.ApplicationBase);

 

The first parameter is the host view type – so MAF knows what add-ins we are looking for, the second is the pipeline root directory, which is the same directory passed to the Rebuild method and indicates where the pipeline database is stored.

 

The returning collection represents a series of tokens that are used to identify and control the add-ins.  This is how the host can examine, activate and unload the add-in.  To activate a specific add-in, you can take the token and call Activate:

 

Collection<AddInToken> addinTokens;

    ...

foreach (AddInToken token in addinTokens)
{

   TranslatorHostView view =

       token.Activate<TranslatorHostView>(

             AddInSecurityLevel.Internet);

  

   string hello = view.Translate(“Bonjour”);

     ...
}

 

The Activate call loads all the required components, instantiates the add-in type and returns the host view used to interact with the add-in.  Calls made to this object will be marshaled back and forth to the add-in using the pipeline.

 

Notice that the parameter passed to Activate indicates the security level required.  There are several overrides that allow you to dictate exactly how the add-in is loaded.  You can load the add-in into a specific AppDomain – the current one for best performance:

 

token.Activate<TranslatorHostView>(AppDomain.CurrentDomain)

 

You can specify a specific permission set to restrict the things the add-in can do on your behalf:

PermissionSet pset = ...;

token.Activate<TranslatorHostView>(pset);


Or you can specify a known permission set based on the CAS zones:

image010.png

Once the add-in is activated, the host can call it just like any other object – but never forget that you are likely crossing an isolation barrier!  Make sure to design your contracts so that you minimize the number of calls between the host and add-ins to ensure your performance doesn’t suffer.

When you are finished with the add-in, you can tell MAF to unload it through the AddInController associated with the view:

AddInController ctrl =    

      AddInController.GetAddInController(view);

ctrl.Shutdown();


This will unload the add-in side pipeline and then destroy the containing AppDomain so you release the resources associated with it.

There are many other capabilities MAF provides such as versioning, passing collections and WPF visuals, passing non-serializable types, etc.  You can get a pretty decent overview of the features from MSDN and the MAF team has a blog at http://blogs.msdn.com/clraddins/ that has some great, practical information on using this new framework.

Tuesday, May 06, 2008 4:46:26 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code | Real World
# Thursday, April 03, 2008
Creating popup windows in browser-hosted applications (XBAP)
Thursday, April 03, 2008 9:47:05 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Wednesday, February 06, 2008
Today at the GNET Michael Kennedy, Jason Whittington and I discovered a pretty interesting change in .NET 2.0 SP1 (included in .NET 3.5).

We knew they increased the thread pool limit from 25 threads/cpu to 250 threads/cpu, but we also found they changed the heuristics for creating threads to avoid creating a bunch of threads in a short period of time. In previous versions of .NET, threads were allocated at a rate of 1 every 500ms assuming there were queued items. This is documented behavior in MSDN.

In .NET 3.5, it appears to have been changed to a sliding scale where they slow down thread creation as more demand is placed on the pool. This is a change even from the beta and must have been slipped in at the last minute.

Michael documented the whole change on his blog here.. recommended reading.
Wednesday, February 06, 2008 11:35:52 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET
# Wednesday, December 19, 2007

After a long beta period Microsoft pushed Visual Studio .NET 2008 (code named “Orcas”) out to MSDN in November - keeping their promise to deliver it by the end of the year. We’ve been using Orcas in many of our .NET classes for a while now and I for one, am pretty excited that it’s finally here. There’s a ton of new features and enhancements in this release that makes it almost a no-brainer to upgrade - I thought I’d take a moment and list my top ten favorites in no particular order:

#10: WPF designer (“Cider”)

I spend a lot of time on rich-client island and compared to the embarrassing support for WPF provided for VS2005 (through an add-on) VS2008 just plain rocks. Not only does the designer just work, the XAML intellisense is full featured and driven through a real XAML parser and not an XSD file. That means custom types and namespace completion actually functions how you would expect them to! The visual designer and XAML views stay synchronized and “mini” thumbnails and scaling bars are used to help you see what you are building. You can also see how the new Cider environment has borrowed from Blend - a Search box is present to filter properties down and the selection in the XAML pane is synchronized with the visual designer so if you highlight a tag, it selects the appropriate object in the visual pane.

#9: WPF and Windows Forms integration (“Crossbow”)

Hand in hand with the designer view, VS2008 improves the designer experience for Windows Forms to WPF integration. Specifically, ElementHost is now present in the toolbox and you can drag and drop WPF user controls right onto your Form! You get a live preview of the control and can edit the content right in the designer.

#8: ClickOnce improvements
Microsoft introduced a simplified way to deploy Windows Forms clients from the web with Visual Studio 2005 called ClickOnce. With 2008, they’ve improved the experience by allowing deployment through FireFox (previously only IE was supported), file associations so your application can be launched by activating a data file, better support for certificate expiration and changing the deployment location without resigning the application and support for Office add-in and WPF XAML Browser application deployment.

#7: Multi-framework targeting

This release of Visual Studio has a much-needed feature that I wish had been there before - the ability to target multiple versions of .NET. Specifically, you can select your target framework (2.0 SP1, 3.0 or 3.5) and the project types, toolbox, references, intellisense and features will be appropriately set to that version. This selection can occur during project creation - in the project templates dialog or on the project properties dialog. Be aware that selecting .NET Framework 2.0 actually means 2.0 SP1 and not the original .NET 2.0 framework released with Visual Studio 2005.

#6: Better intellisense support

Web developers benefit from this release too - Visual Studio now has intellisense and code completion support for JavaScript! It’s smart enough to look at the underlying type currently assigned and correctly infer the methods which are available. So, for example if you assign a numeric type, the dropdown will be populated with the proper methods available for the type. Visual Studio will also look at the comments applied to your methods - just like in C# and VB.NET, it will pull descriptions out of XML based comments on your JavaScript methods and display descriptions as tooltips when you are navigating the intellisense dropdown. Another cool feature added to Intellisense is the filtering applied - now if you press a letter and start typing, it will begin to restrict your choices displayed, not just scroll to that section. This filters the output and makes it easier to find what you are looking for.

#5: Organize your using statements

Visual Studio now has the ability to organize your using statements. As a project evolves, you often end up with a ton of using statements at the top of each file which are not really being used - either because the project template added it, or because you originally did use something from that namespace which was then removed later. Now you can right click on your using statements and sort and/or remove unused namespaces.

#4: Refactoring enhancements
The refactoring support was a welcome addition to VS 2005 - and Microsoft has enhanced the support in 2008 to support C# 3.0 features and allow you to refactor anonymous types, extension methods and lambda expressions.

#3: C# 3.0 support
Speaking of C# 3.0, that has got to be one of the coolest features - functional programming seems to be all the rage these days and introducing these features into C# 3.0 will allow you to be the coolest programmer on your floor. Things like automatic properties, lambda expressions (which reduce your typing for anonymous delegates), partial methods, anonymous types and extension methods will radically change how you can build applications. They can seem weird at first for some people, but don’t be afraid of them! They will cut down your typing and provide for some really cool ways to enhance and evolve your projects.

#2: Visual Studio Split View

It is becoming increasingly more common to have multiple monitors on developers desks. Building on the “split” window feature of VS 2005, Visual Studio 2008 now allows you to tile the window horizontally or vertically so you can split your design and code view across monitors! This works in any of the designers (ASP.NET, WinForms, WPF, etc.)

#1: Debugging the .NET source code
There are actually several debugging enhancements (try debugging JavaScript on the client-side for example - it works great!) but I think the coolest feature by far has got to be the debugging enhancements which will allow you to actually debug into the source code of the .NET framework. Scott Guthrie announced a few weeks ago on his blog that they intend to release the source code under the Microsoft Reference License. As part of that release, VS2008 will have integrated debugging support so that you can step into the framework libraries (ever want to know why your DataBind isn’t working??). Visual Studio will automatically download the source file from Microsoft’s server and you will get full watch and breakpoint support. This isn’t quite ready yet, but it’s coming soon and promises to be one of the biggest timesavers added to Visual Studio!


There’s a ton of other features that make VS 2008 a worthwhile upgrade - you can experience it yourself by downloading a free copy today (Express editions have been released) or upgrading from MSDN. VS 2008 co-exists just fine with 2005 and 2003 but be aware that the project format has changed and it’s not backward compatible so sharing projects with your coworkers may be slightly painful for you until everyone moves to the new release as you will have to maintain two project and solution files.
Wednesday, December 19, 2007 10:56:11 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET
# Monday, November 19, 2007
Thanks to all those who attended the GNET in Tampa last week. We had a blast with all of you and wish you the best of luck going back and using all the cool tricks and technologies we showed you! As promised, here are the demos we build during the week - Demos. Enjoy!
Monday, November 19, 2007 5:01:13 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Code
# Thursday, September 06, 2007

Another interesting feature I hadn't noticed about VS.NET 2008 is the "Organize Using" command.  It allows you to sort and filter your using blocks on a file-by-file basis.  For large projects that have changed over time I could see how it could be very useful.

 

Thursday, September 06, 2007 9:47:15 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET
# Monday, August 13, 2007

If you right click on "References" in a VS2008 project you will find only two options now - "Add Reference" and "Add Service Reference".  The first is for local assemblies, and the second generates WCF-compatible proxies through SVCUTIL.EXE.  This happens to be one of the most obviously changed things in Orcas - the dialog presented is a more professional version than what was supplied with the original WCF CTP for VS.2005:

The "Discover" button above can locate IIS-hosted web services (not Self Hosted however) and it now shows operations directly which is pretty cool.  The best part is the "Advanced" button though.  Clicking that gives you:

Here you can control all the details of SVCUTIL.EXE -- how to reuse types, whether to generate public/private types, whether to genrate lower-level message contracts (giving complete control over the SOAP structure), and whether to generate asynchronous methods (ala the original web services references in .NET 2.0).

The bottom section - "Compatibility" allows you to generate a web service proxy using that original WS technology.  Clicking this will yield the traditional dialog you are probably used to:

So, if you were confused by the lack of a "Add Web Reference" in Orcas, fear no more - it's still there just a little harder to get to!

You might be asking - "Why would I want to generate one of those?  Why not just use WCF?"  Well, we have to keep in mind that not all our clients want to move to WCF just yet (as much as we want them to, there is a cost in deployment), and second, WCF isn't supported on pre-XP platforms.  There are still a lot of Windows 2000 systems out there!  For those clients, we have no choice but to use legacy web service proxies.

Monday, August 13, 2007 2:58:09 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET
# Monday, July 30, 2007
Microsoft apparently didn't resign all the tools in the SDK supplied with Beta 2 of Visual Studio 2008.  This is actually documented in the readme that UISpy has this issue, which of course, I didn't read..
 
SVCUtil.exe also has this problem and it causes any proxy-generation from VS.NET 2008 to fail (as well as killing the client tester process which is spawned for WCF testing).  You'll know you've hit this error when the program crashes with a "System.IO.FileException" and indicates that it has failed strong-name validation.
 
It's easy enough to fix ..
 
1) Open a command prompt with full admin rights
2) CD to the C:\Program Files\Microsoft SDKs\Windows\V6.0a\bin directory
3) execute "SN -Vr svcutil.exe"
 
This turns off strong-name validation for svcutil.exe.
 
Monday, July 30, 2007 5:20:15 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET
# Monday, July 16, 2007

I've been playing a bit with VS.NET '08 June CTP lately and noticing several nice improvements - the Cider WPF add-in especially seems to have better integration with the code window.  For example, double clicking on an element now creates the code-behind handler (finally!).

The layout support is much better as well - you finally get the drag handles and positioning lines.

 

The property sheet seems a bit sketchy right now - I see how Blend has certainly influenced it (as the code apparently is coming from that product), but I find Blend to be easier to work with there.  No support for Data Providers either which is a bummer.

Bindings are still not as nice as Blend; manual addition seems to be the only way to do them at this point, however Intellisense is *much* better now.  There's also a nice zoom bar present which allows fine-detail work to be done when drawing graphical elements (such as Control Templates or even just 2D/3D shapes).

Overall, I'm seeing some good progress - here's hoping for more as the product matures!

Monday, July 16, 2007 1:26:30 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Wednesday, January 17, 2007

About a year ago, I blogged on using the .NET 2.0 facility SynchronizationContext to create thread-aware components which could be hosted and would "do the right thing" for callbacks. Here's the Link to that post.

Recently, I got an email from a reader who wanted to use that paradigm, but wanted to be able to suspend the operation for some period of time and then resume it later on. He asked if there was an easy way to modify the sample I presented, and it turns out that there is.

It essentially involves three steps:

1. In the AsyncStateData structure, add a ManualResetEvent object. This will be used to trigger the pause/resume behavior. It must be initially set as signaled.

2.
In the actual asynchronous operation loop, add the event into the loop condition by calling event.WaitOne(). Make sure you have released any locks and the code can safely be halted at that point in the logic otherwise you may create deadlock scenarios and other difficult debugging issues.

3.
Add a Pause and Continue method into the class which signals and resets the event.

Modifying my previous code example, here's what I come up with:

Step 1: Add the event to AsyncStateDate

   1:  class AsyncStateData
   2:  {
   3:      private ManualResetEvent pauseEvent = new ManualResetEvent(true);
   4:      ...
   5:  }

Step 2: Add event into the loop at a safe point

   1:  public partial class Calculator
   2:  {
   3:      private void InternalCalculatePi(int digits, AsyncStateData
   4:  asyncData)
   5:      {
   6:         int completedDigits = 0;
   7:         for (; !asyncData.canceled && pauseEvent.WaitOne(-1, true) &&
   8:  completedDigits < digits; completedDigits++)
   9:         {   ...  }
  10:      }
  11:   
  12:  ...
  13:  }

Step 3: Add a Pause and Continue API

   1:  public partial class Calculator
   2:  {
   3:      public void PauseAsync(object asyncTask)
   4:      {
   5:          AsyncStateData asyncData = asyncTask as AsyncStateData;
   6:          if (asyncData != null && asyncData.running == true)
   7:              asyncData.pauseEvent.Reset();
   8:      }
   9:   
   10:     public void ContinueAsync(object asyncTask)
   11:     {
  12:          AsyncStateData asyncData = asyncTask as AsyncStateData;
  13:          if (asyncData != null && asyncData.running == true)
  14:              asyncData.pauseEvent.Set();
  15:     }
  16:  ...
  17:  }


There are certainly other ways to do this as well, for example, create a dedicated Thread object instead of using an Async delegate and then call Suspend on the thread (and Resume to continue). That can be dangerous if you take locks while running your async operation so the ManualResetEvent is probably a better solution from that perspective (since you are blocking in a known location vs. just suspending the thread arbitrarily and potentially holding onto shared resources.
Wednesday, January 17, 2007 10:11:04 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Code | Real World

One of the nifty new features of the WPF platform is the pluggable data providers.  It ships with two out of the box:

ObjectDataProvider: allows you to execute binding expressions against an object and it's methods
XmlDataProvider: loads an XML data source and makes it available as a binding source

Both of these derive from the abstract class System.Data.DataSourceProvider which implements the binding glue (INotifyPropertyChanged) needed for data binding.  A side note here is that you could write your own custom data provider if you needed to, although if the data is exposed through a .NET object, then the ObjectDataProvider is probably sufficient.

Using the providers is fairly easy -- let's say we have some XML data that looks like this:

<?xml version="1.0" encoding="utf-8"?>
<taxrecords>
 
<entry name="Opal Harrison" state="AL" income="$51,466.81" age="27" />
 
<entry name="Eugene Black" state="FL" income="$13,314.89" age="71" />
 
<entry name="Opal Chang" state="NC" income="$225,115.15" age="41" />
 
<entry name="Gary Waters" state="WI" income="$151,788.49" age="39" />
 
<entry name="Xavier Davis" state="AK" income="$136,344.97" age="66" />
 
<entry name="Stacy Harrison" state="TX" income="$122,432.82" age="32" />
</taxrecords>

The goal is to put this data into a ListBox - displaying the fields in the following format:

Name
State, Age, Income

We could clearly do all of this from procedural code -- create an XmlReader object, load the data and render each XmlNode into the listbox.  However, this is the 21st century and so we want to avoid coding as much as we can and utilize the underlying framework support instead!

We can get the data loaded into a collection source through the XmlDataProvider.  This is easily done in XAML:

<XmlDataProvider Source="largeXmlFile.xml" x:Key="xmlData" XPath="/taxrecords" />

This will look for the file "largeXmlFile.xml", create an XmlDocument and load the file into memory.  Notice we supply an XPath expression as part of this to indicate what we'd like the data provider to hand us as the collection itself.  In this case, we want to see everything under the node "taxrecords" which is the root of the document.  An interesting facet of this provider is that it performs it's work asynchronously -- you can see this behavior when you load very large XML files.  The UI will come up first, completely empty and then suddenly be populated with data.  The behavior can be adjusted through the IsAsynchronous property of the data provider.  Setting this to false will delay the display of the UI until the data is fully available.

Another interesting thing about this class is that we can define the XML data inline within the XAML document.  You do this with the x:XData tag:

<XmlDataProvider x:Key="xmlData" XPath="/taxrecords">
   <x:Data>
       <taxrecords>
         
<entry name="Opal Harrison" state="AL" income="$51,466.81" age="27" />
         
<entry name="Eugene Black" state="FL" income="$13,314.89" age="71" />
              ...

       </taxrecords>
  
</x:Data>
</XmlDataProvider>

The next step is to bind this data to a ListBox control - this is a normal Data Binding expression:

<ListBox Name="lb1" Margin="10" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource xmlData, XPath=entry}}">

Notice how we use a new property of the BindingExpression called XPath.  This property allows you to identify which element(s) you want to load from the XML data source.  It is specific to this data provider and allows for any XPath expression to be supplied.  This will succesfully load each of the "/taxrecord/entry" nodes into the ListBox, but the data itself will show up as a blank line.  This, of course, is because the data is really an XmlNode object which the ListBox has no idea how to display.  To fix this, we supply a DataTemplate to render our data: 

<ListBox.ItemTemplate>
   <
DataTemplate>
      <
StackPanel>
         <TextBlock FontWeight="Bold" Text="{Binding XPath=@name}" />
         <
StackPanel Orientation="Horizontal">
            <
TextBlock Text="{Binding XPath=@state}" />
            <
TextBlock Text=", " />
            <
TextBlock Text="{Binding XPath=@age}" />
            <
TextBlock Text=", " />
            <
TextBlock Text="{Binding XPath=@income}" />
         </
StackPanel>
      </
StackPanel>
   </
DataTemplate>
</
ListBox.ItemTemplate>

Again, we use the XPath property to define what piece of information we are binding to -- attributes of our entry in this case.  This template will give us the format we are looking for:

We can add sorting, filtering and grouping using the normal CollectionViewSource support.  Here is a XAML file which will present the above UI complete with sorting by the age element.  Notice how the XPath expression now moves to the CollectionView.  This is because the CollectionViewSource creates a ListCollectionView to manage the XML nodes because the data provider supports the IList interface.  The binding expression on the listbox is now simply a binding to the collection view.

<Window Title="AsyncDataBind" Height="300" Width="300"
 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Window.Resources>

  
<
XmlDataProvider Source="largeXmlFile.xml" IsAsynchronous="True"
                            
x:Key="xmlData" XPath="/taxrecords" />

  
<
CollectionViewSource x:Key="collView" Source="{Binding Source={StaticResource xmlData},XPath=entry}">
     
<
CollectionViewSource.SortDescriptions>
        
<
cm:SortDescription PropertyName="@age" Direction="Ascending" />
     
</
CollectionViewSource.SortDescriptions>
  
</
CollectionViewSource>

</
Window.Resources>

<
Grid>
  
<
Grid.RowDefinitions>
     
<
RowDefinition Height="*" />
     
<
RowDefinition Height="Auto" />
  
</
Grid.RowDefinitions>

   <ListBox Name="lb1" Margin="10" IsSynchronizedWithCurrentItem="True"
               
ItemsSource="{Binding Source={StaticResource collView}}">

     
<
ListBox.ItemTemplate>
        
<
DataTemplate>
           
<
StackPanel>
              
<
TextBlock FontWeight="Bold" Text="{Binding XPath=@name}" />
              
<
StackPanel Orientation="Horizontal">
                 
<
TextBlock Text="{Binding XPath=@state}" />
                 
<
TextBlock Text=", " />
                  
<
TextBlock Text="{Binding XPath=@age}" />
                 
<
TextBlock Text=", " />
                 
<
TextBlock Text="{Binding XPath=@income}" />
               
</
StackPanel>
            
</
StackPanel>
         
</
DataTemplate>
      
</
ListBox.ItemTemplate>

   
</
ListBox>

   <Button Grid.Row="1">
     
<
StackPanel Orientation="Horizontal">
        
<
TextBlock Text="{Binding ElementName=lb1, Path=Items.Count}" />
        
<
TextBlock Text=" Items" />
      
</
StackPanel>
   
</
Button>

</
Grid>
</
Window>

Data binding in WPF is extremely powerful -- I am constantly amazed at how much procedural code you can dump in favor of markup with creative bindings.  In the next post I'll talk a bit more about asynchronouus bindings outside of the two data providers.

Until then..

Wednesday, January 17, 2007 4:57:58 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Code | WPF
# Friday, December 08, 2006

There's been a discussion going on within DevelopMentor for a couple weeks regarding concurrent GC and when it really applies.

The idea behind the concurrent collector is to do as much of the GC while the UI thread continues to process UI stuff and then only interrupt the application threads when memory is being shuffled around and fixups are occurring. This provides for more responsive UI applications at the expense of slower collections and a higher memory utilization.

The instructors who are involved with .NET were discussing this because of a discrepancy in various reliable sources - First, Maoni Stephens, the ultimate authority on all things .NET GC, stated in her blog entries that concurrent GC was the default behavior for the workstation version of GC (see http://blogs.msdn.com/maoni for more information on this).

This is well known, and now well documented in various places. However, Jeff Richter seems to say in his book "CLR via C#" that concurrent collections occur only on multiprocessor machines. Several other authors back this up (notably Stephen Pratschner in "Customizing the .NET Framework Common Language Runtime" and Joe Duffy in his "Professional .NET Framework 2.0" book; both are excellent btw).

So, we had some differing opinions from people in the "know". Our Effective .NET and Essential .NET courses were written around Maoni's blogs and so the diagram we presented showed concurrent collections even on single-processor machines since she didn't explicitly say it required multiple processors to turn it on. One of the guys noticed this and said "Wait! That's wrong!"

We tried to actually see the concurrent collection in action but it turns out that it's actually quite difficult to get this to happen because concurrent collections only occur on Gen2, which for a well-written application shouldn't occur that often. To add to the complexity, the CLR attempts to optimize this behavior - just because it can do the GC concurrently, it might not.  Finally, the thread which is used for this collection is actually created and destroy as necessary so it doesn't exist most of the time.

So, to settle the argument, Jason Whittington and I spent some time spelunking into the CLR this past week to see if we could spot the concurrent collection in action. With a little WinDBG and some symbols, I think we've put the question to rest once and for all (at least for us) :-).  If you scan the GC symbols in mscorwks.dll, you'll find a treasure trove of information; one of the things that caught my eye was this:

0:000> x mscorwks!WKS::gcheap::*
79f8c5dd mscorwks!WKS::GCHeap::Relocate = <no type information>
7a0d09d9 mscorwks!WKS::GCHeap::ValidateObjectMember = <no type information>
7a088e2a mscorwks!WKS::GCHeap::IsConcurrentGCInProgress = <no type information>
Disassembling that method showed me that it checks a flag in memory --
0:000> u mscorwks!WKS::GCHeap::IsConcurrentGCInProgress 
mscorwks!WKS::GCHeap::IsConcurrentGCInProgress:
7a088e2a a1701b387a      mov     eax,dword ptr [mscorwks!WKS::gc_heap::settings+0x10 (7a381b70)]
7a088e2f c3              ret
I tried putting a breakpoint at the end of the GC process and dumping that flag out when it was a Gen2 collection (the breakpoint itself stolen shamelessly from Maoni's MSDN article in November 2006):
0:000> bp mscorwks!WKS::GCHeap::RestartEE "j 
(dwo(mscorwks!WKS::GCHeap::GcCondemnedGeneration)==2)
'dd mscorwks!WKS::gc_heap::settings+0x10 L1';'g'"
But I didn't get much success seeing it set to "1" - I suspect that it requires a more complex application than I was using to cause the CLR to decide a concurrent collection is worth the effort. So I decided this was a dead end and started looking to see where the GC process determines that concurrent collections are allowed at all. I figured GCHeap::Initialize sounded like a good spot --
0:000> u mscorwks!WKS::GCHeap::Initialize
mscorwks!WKS::GCHeap::Initialize:
79ed6924 a14412387a      mov     eax,dword ptr [mscorwks!g_pConfig (7a381244)]
79ed6929 8b4058          mov     eax,dword ptr [eax+58h]
.....
79ed697b 51              push    ecx
79ed697c e823040000      call    mscorwks!WKS::gc_heap::initialize_gc (79ed6da4)
79ed6981 85c0            test    eax,eax
Going into that function yielded what I was looking for --
0:000> u mscorwks!WKS::gc_heap::initialize_gc
mscorwks!WKS::gc_heap::initialize_gc:
79ed6da4 56              push    esi
79ed6da5 e80cf1ffff      call    mscorwks!WKS::write_watch_api_supported (79ed5eb6)
79ed6daa 33f6            xor     esi,esi
...
79ed6dc6 c70564ce387a01000000 mov dword ptr [mscorwks!WKS::gc_heap::gc_can_use_concurrent (7a38ce64)],1
Looking at that particular memory location, I tried various configurations to make sure I had the right spot. First, I did a simple console app with no config file and dumped out the location on a multi-processor box:
0:000> dd mscorwks!WKS::gc_heap::gc_can_use_concurrent L1
7a38ce64  <b>00000001b>
Next, I set the application up in server mode (also on a multi-processor box):
<xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <gcServer enabled="true" />
  </runtime>
</configuration>
0:000> dd mscorwks!WKS::gc_heap::gc_can_use_concurrent L1
7a38ce64  <b>00000000b>
Showing that it was now off.. next I tried a VM session which emulates a single processor:
0:000> dd mscorwks!WKS::gc_heap::gc_can_use_concurrent L1
7a38ce64  <b>00000001b>

It appears that the CLR is capable of doing concurrent collections on a single processor! My final test was to try turning it off altogether via a configuration switch:

<xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <gcConcurrent enabled="false" />
  </runtime>
</configuration>
0:000> dd mscorwks!WKS::gc_heap::gc_can_use_concurrent L1
7a38ce64  <b>00000000b>

As a final note on this, Jason asked Maoni directly and her response was that concurrent GC does not depend on the number of processors - just as we are seeing above. So, apparently several primary sources are actually incorrect on this behavior. It just goes to show how complex the overall GC process really is -- simple in concept, but boy there are a lot of moving parts!
Friday, December 08, 2006 1:25:29 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Debugging
I've updated ATAPI.NET in the samples page http://www.julmar.com/samples/atapinet.zip with several fixes and support for conferences, full transfers and phone support. I think almost everything is now wrapped - if you find any missing functions that you want/need ping me and I'll see what I can do.
Friday, December 08, 2006 12:11:22 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Tapi
# Friday, September 01, 2006
I was preparing a sample memory leak application for an Advanced C# class at Microsoft this past week and debugging through it with SOS.DLL ("Son of Strike"). My prepared application was an ASP.NET application that would leak memory by holding references to the page objects after they had completed their work. I did this by having the page hook up an event handler to a global event and then never remove the handler.

This, of course, is bad form because the System.Web.UI.Page object is intended to be a transient object - it goes away at the end of the request - in production code, I would really bind the event to a handler in global.asax instead. But as I said, this was a sample.

So, I was debugging through it prior to the class just to make sure it exhibited the behavior I was looking for. I run the web page a few times, noted my working set going up and never coming back down. Next, I used ADPLUS.VBS to take a hang dump of the process. I then loaded this dump up into WinDBG and started poking around. First, I looked at the heap and sure enough I saw a bunch of page objects:
0:000> .load sos
0:000> !DumpHeap -stat
total 36955 objects
Statistics:
      MT    Count    TotalSize Class Name
7b4ecd7c        1           12 System.Windows.Forms.ButtonInternal.ButtonPopupAdapter
7b481f00        1           12 System.Windows.Forms.LinkLabel+LinkComparer
7b475ca8        1           12 System.Windows.Forms.FormCollection
7b474f8c        1           12 System.Windows.Forms.Layout.DefaultLayout
7b4749e0        1           12 System.Windows.Forms.ClientUtils+WeakRefCollection
7b473ca8        1           12 System.Windows.Forms.Layout.ArrangedElementCollection
7a755834        1           12 System.Diagnostics.PerformanceCounterCategoryType
7a753394        1           12 System.Diagnostics.TraceOptions
7a71a710        1           12 System.Net.TimeoutValidator
.......
00166030      891       169744      Free
054d24d4     3128       187680 System.Web.UI.LiteralControl
0548cbd4      519       197220 ASP.default_aspx
791242ec     1545       297960 System.Collections.Hashtable+bucket[]
79124670     1185      1090500 System.Char[]
79124228    11961      1279380 System.Object[]
790fa3e0    19149      1561392 System.String
Total 110069 objects
So, next I used DumpHeap to just look at this specific type by giving it a metadata token:
0:000> !DumpHeap -mt 0548cbd4        
 Address       MT     Size
.....     
01854ff0 0548cbd4      380     
01860130 0548cbd4      380     
0186b2b4 0548cbd4      380     
018773f8 0548cbd4      380     
01882538 0548cbd4      380     
0188d6bc 0548cbd4      380     
01898840 0548cbd4      380     
018a39c4 0548cbd4      380     
018aeb48 0548cbd4      380     
total 519 objects
Statistics:
      MT    Count    TotalSize Class Name
0548cbd4      519       197220 ASP.default_aspx
Total 519 objects
I then used the very cool GCRoot command to determine why a page instance was still rooted and therefore not collectable.

Note: it appears that GCRoot doesn't work well inside VS.NET 2005 - apparently the SOS debugging extension is using some debugger API which isn't fully supported in VS.NET, so you need to familiarize yourself with WinDBG to do this.


0:000> !gcroot 018aeb48 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 3a8
Scan Thread 2 OSTHread e8
Scan Thread 3 OSTHread 1a8
Scan Thread 6 OSTHread 7d4
Scan Thread 7 OSTHread 2b4
Scan Thread 8 OSTHread fdc
Scan Thread 9 OSTHread eac
DOMAIN(001E5E08):HANDLE(Pinned):12312f0:Root:0226c498(System.Object[])->
018af940(System.EventHandler)->
0186c0ac(System.Object[])->
018af920(System.EventHandler)->
018aeb48(ASP.default_aspx)
With this output, I can tell that my default_aspx object is being kept alive through an EventHandler as I expected. The interesting thing about this output is I cannot tell which event handler is keeping it alive - i.e. there is nothing in this root list that points to a specific object holding it other than a object[]. That essentially means this is a static event and there isn't an actual object around on the heap for it. This just makes the debugging exercise more interesting - after all if it were an instance event then I would see the class name at the top of the root list and we could stop right here.

So, my next step is to dump the event handler to try to identify what method it is wrapping - I could then search the code for this method and find out where it is being bound. I dump out the EventHandler object:
0:000> !do 018af920
Name: System.EventHandler
MethodTable: 7910d61c
EEClass: 790c3a7c
Size: 32(0x20) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
790f9c18  40000f9        4        System.Object  0 instance 018aeb48 _target
79109208  40000fa        8 ...ection.MethodBase  0 instance 00000000 _methodBase
790fe160  40000fb        c        System.IntPtr  0 instance 88962888 _methodPtr
790fe160  40000fc       10        System.IntPtr  0 instance        0 _methodPtrAux
790f9c18  4000106       14        System.Object  0 instance 00000000 _invocationList
790fe160  4000107       18        System.IntPtr  0 instance        0 _invocationCount
From this I get the internals of the EventHandler object. It gives me some specific information:
  • _target is the object the delegate is holding onto - my default_aspx in this case. The value better match up with my original object!
  • _methodBase is used for dynamic code and is null here.
  • _methodPtr is the method associated with the instance, or possibly a dynamically generated thunk for static methods. This is what I'm interested in.
  • _methodPtrAux is used for static methods; this holds the method descriptor and the _methodPtr is a dynamically generated block of code to remove the this reference. Noting that this is null, I can infer that this is an instance method bound to the delegate.
  • _invocationList and _invocationCount are used for Multicast Delegates -- these are both zero indicating that this is a single delegate and there is no chain to follow.

My next step is to try to get a valid method name from the _methodPtr so I convert that to hex and pass it into IP2MD.
0:000> !ip2md 0n88962888 
Failed to request MethodData, not in JIT code range
This is a pretty common error and simply means that the method may not have been JITted yet, or may be a dynamic block of code which never went through the JIT compiler. In .NET 1.1 we could start dumping method descriptors and trying to match up the address (DumpClass -md) for this class and it's base class.

However, under .NET 2.0 this rarely works anymore - the address doesn't appear to ever match up to a valid descriptor. However, it clearly is part of the managed heap due to it's address. So, failing to locate this address, I tried disassembling the code:
0:000> !u 0n88962888 
Unmanaged code
054d7748 e862289b74      call    mscorwks!LogHelp_TerminateOnAssert+0x3f5f (79e89faf)
054d774d 5e              pop     esi
054d774e cc              int     3
054d774f cc              int     3
054d7750 38c8            cmp     al,cl
054d7752 48              dec     eax
054d7753 05a0774d05      add     eax,54D77A0h
054d7758 0100            add     dword ptr [eax],eax
054d775a 0011            add     byte ptr [ecx],dl
054d775c 0000            add     byte ptr [eax],al
Humph. This doesn't even look like valid code to me.. this looks like random data, so I dumped it out:
0:000> dd 0n88962888 
054d7748  9b2862e8 cccc5e74 0548c838 054d77a0
054d7758  11000001 90000000 054d77a0 11000002
054d7768  90000004 00000000 054d77a0 00000000
The third and fourth DWORD look interesting because they appear to fall in the managed heap as well -- so I began to dump them out trying to figure out what they were. I found that the first value is a method descriptor:
0:000> !dumpmd 0548c838 
Method Name: _Default.OnDatabaseHasChanged(System.Object, System.EventArgs)
Class: 054ab574
MethodTable: 0548c86c
mdToken: 06000004
Module: 0548c35c
IsJitted: no
m_CodeOrIL: ffffffff
It is the real method bound to the delegate instance. The other DWORD appears to be an metadata reference to the event owner itself:
0:000> !dumpmt 054d77a0
EEClass: 0551940c
Module: 048ac9ec
Name: DatabaseMonitor
mdToken: 02000002  (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\leakypage\2a399ab5\b1e04c63\App_Code.onwg1zqj.dll)
BaseSize: 0xc
ComponentSize: 0x0
Number of IFaces in IFaceMap: 0
Slots in VTable: 8
From here I can see the module that this code is defined in (the dynamically generated App_Code directory) and the name (DatabaseMonitor). This gives me enough information to stop here and begin looking at the code itself - specifically where default.aspx binds it's OnDatabaseHasChanged method to the DatabaseMonitor static class defined somewhere in the App_Code directory. If I didn't have the source code available, I could locate the module and then save it out to a file through the savemodule command:
0:000> lm m App_Code_onwg1zqj
start    end        module name
04de0000 04de8000   App_Code_onwg1zqj C (no symbols)           
0:000> !savemodule 04de0000 c:\appcode.dll
3 sections in file
section 0 - VA=2000, VASize=504, FileAddr=200, FileSize=600
section 1 - VA=4000, VASize=2c8, FileAddr=800, FileSize=400
section 2 - VA=6000, VASize=c, FileAddr=c00, FileSize=200
I could then ILDasm or Reflector the generated assembly and look for my bug from that.

I love SOS and WinDBG.. if only they could match up managed source code to the image I'd abandon VS.NET as a debugger altogether..
Friday, September 01, 2006 1:18:41 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code | Debugging
# Monday, August 28, 2006
One question I get a lot when teaching the VSTS course is "How can I move tasks or bugs from our existing system into TFS?"

The answer is quite simple: write a program that utilizes the Team Systems Object Model.

The Object Model is documented partially in the VSIP SDK -- if you intend to work with it, I highly recommend you go and grab that SDK from Microsoft, but here is a simple example of creating a bug in the first Team Project available on the server named TFSServer (you can imagine the rest which uses ADO.NET to pull your existing tracking tickets from whatever system you have):

   1:  using System;
   2:  using System.Collections;
   3:  using System.Collections.Generic;
   4:  using System.Text;
   5:  using Microsoft.TeamFoundation.Client;
   6:  using Microsoft.TeamFoundation.WorkItemTracking.Client;
   7:   
   8:  namespace EnterWorkItems
   9:  {
  10:      class Program
  11:      {
  12:          static void Main(string[] args)
  13:          {
  14:              TeamFoundationServer tfs = new TeamFoundationServer("TFSServer");
  15:              WorkItemStore wis = (WorkItemStore) tfs.GetService(typeof(WorkItemStore));
  16:   
  17:              Project teamProject = wis.Projects[0];
  18:              foreach (WorkItemType wit in teamProject.WorkItemTypes)
  19:                  Console.WriteLine(wit.Name);
  20:   
  21:              WorkItemCollection wic = wis.Query("Project='Test' AND Type='Bug'");
  22:              foreach (WorkItem wiEntry in wic)
  23:              {
  24:              }
  25:   
  26:              WorkItemType witBug = teamProject.WorkItemTypes["Bug"];
  27:              if (witBug != null)
  28:              {
  29:                  Console.WriteLine("Adding new bug to Team Project {0}", teamProject.Name);
  30:   
  31:                  WorkItem wi = new WorkItem(witBug);
  32:                  wi.Description = "This is a sample bug which was added through the object model";
  33:                  wi.Reason = "New";
  34:                  wi.Title = "You have Bugs! [Ding]";
  35:   
  36:                  wi.Save();
  37:                  Console.WriteLine("Added Work Item # {0} created by {1}", wi.Id, wi.CreatedBy);
  38:              }
  39:          }
  40:      }
  41:  }


Breaking this down a bit, the first main piece of code is the connection to the Team Server itself. This is accomplished on line 14 by creating a new TeamFoundationServer object. An optional constructor allows for credentials to be provided, otherwise it logs on as the current principle.

Next, we retrieve the WorkItemStore. Almost everything in the object model is accessed through the IServiceProvider interface which provides a GetService method where you pass in the System.Type object you want to work with. This is a nice versioning technique that is utilized in many other Microsoft technologies as well.

With the WorkItemStore, you can then query work item type definitions, one of which is necessary to create a WorkItem. You fill in the details for the Work Item you want to create and call the Save method (line 36) to commit the changes to the TFS store. The WorkItem id will then be valid and could be added to the existing bug tracking system as a forward link to the new information if you wanted.
Monday, August 28, 2006 6:45:13 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Enterprise
# Monday, July 17, 2006
I was having lunch with an associate a while back and he mentioned a need to move a work item from one team project to another. While there isn't any direct support for this from the Team Explorer interface, I figured it couldn't be too hard to manipulate the underlying database and achieve the results - it's just SQL Server right? I hadn't actually looked at the schema mind you, I'm an optimist.

It wasn't quite as simple as I thought - it felt like the database had been designed by the security group and intentionally obscured for privacy. The TFS database is fairly generic (so that it can add arbitrary items into the schema for custom project types) and has been somewhat secured to protect the code itself - the stored procedures are encrypted and SQL Profiler doesn't give much information on what's happening.

So, I spent a week or so looking at the schema for the Work Item system and a lot of trial and error. End result is that I got a simple application to move work items around. This application does a couple of other things as well - lists projects, active web services, etc. I was mostly playing with the schema and trying to figure things out. It's just a console application but it does the job.

Here's the code, use at your own risk (a.k.a. if it screws up your system, I can't help you). The source for the simple test project is included so you can see what was done and incorporate it into your own code base if you like.

The program is fairly easy to use - a binary is included with the release. Issuing the command with no parameters generates a simple "Help" page --

C:\Work\TfsCmd>tfscmd
TfsCmd [command] [/t tfsserver] [/u user] [/p password] [params]
ListProjects - Lists the active projects on the TF server.
TfsCmd ListProjects
ListServices - Displays the web services exposed by the TF server.
TfsCmd ListWebServices
WQL - Execute a WorkItem Query.
TfsCmd Wql [query]
MoveWorkItem - Moves a work item from one Team Project to another
TfsCmd MoveWorkItem [id] [ProjectName]

Executing a command will use your logged on user/password (domain credentials) unless you supply a /u and /p parameter. For example, running the ListProjects command generates something like:

C:\Work\TfsCmd>tfscmd ListProjects
Project Name: Test
Status: WellFormed
Guid: 8c5b175b-b0ef-46bb-9a9e-dde05bb145ac
Process Template: MSF for Agile Software Development - v4.0
Defined Properties: MSPROJ

Listing the web services just hits the underlying database to get the information:

C:\Work\TfsCmd>tfscmd ListServices
BuildStoreService = http://(local):8080/Build/v1.0/BuildStore.asmx
BuildControllerService = http://(local):8080/Build/v1.0/BuildController.
IBISEnablement = http://(local):8080/Build/v1.0/Integration.asmx
LinkingProviderService = http://(local):8080/Build/v1.0/Integration.asmx
IProjectMaintenance = http://(local):8080/Build/v1.0/Integration.asmx
PublishTestResultsBuildService = http://(local):8080/Build/v1.0/PublishT tsBuildService.asmx

Moving work items is fairly easy - just provide the work item id (the numeric identifier) and the new project name - this must match an existing project in your TFS system. The tool will attempt to match up the iteration to a value in the new project - if it cannot, it will default to the first iteration available.


C:\Work\TfsCmd>tfscmd MoveWorkItem 1 "Mark's New Project"
Work Item #1: "Create Project Definition" is currently located in project "Test Project (Iteration 0)"
Moving work item to "Mark's New Project (Iteration 0)"

If you have the TFS client open, then you should shut it down and reopen it before modifying the moved work item - the client appears to cache bits of information and I had some issues with moved items if I didn't clear the cache by closing the work item window and reopening it.

Have fun!
Monday, July 17, 2006 1:05:53 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Enterprise
# Monday, June 19, 2006
Recording telephone conversations with TAPI
Monday, June 19, 2006 10:41:45 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code | Tapi
# Monday, May 01, 2006

A colleague of mine, Kev Jones, has posted some information on using a detached SQL Server database for driving VSTS unit tests which works great if you need a full blown SQL implementation.  However, if all you want is a simple data feed, you can also use an Excel file, and as it turns out, it's pretty easy to do.

Let's start by stealing Kev's sample, hopefully he won't mind -- say I have a starship class with a FirePhotonTorpedo method:

public class Enterprise
{
   private int torpedosLeft = 10;

   public int FirePhotonTorpedo(int count)
   {
      if (torpedosLeft < count)
         throw new ArgumentException("count");

      torpedosLeft -= count;
      // Instruct bridge officer to "Fire!"
      return torpedosLeft;
   }
}

The equivalent unit test might look something like:

[TestMethod]
public
void TestFirePhotonTorpedo()
{
   Enterprise target = new Enterprise();
   int torpedoCount = 5;
   int expected = 5;

   int actual = target.FirePhotonTorpedo(torpedoCount);
   Assert.AreEqual(expected, actual, "FirePhotonTorpedo did not return the expected value.");
}

This code just tests a specific case -- I would also need to write other unit tests for edge cases and exceptional cases.  I can do this several different ways I could do this:

1) Write a unit test for each specific case passing each value and testing the expected result.
2) Put all the tests into this one unit test function -- asserting each validation as we go.
3) Pull the input and expected out of a database and run them through the function.

This last step, as Kev details can be done from a SQL database - either one reachable by all the people who might run the unit tests, or as his blog shows from a .MDF file you check in with the project and then locally attach prior to running the unit tests.  Hit the link above for the details on that. 

So, to make an Excel data-driven test, the first step is to create an Excel document with columns for each of our pieces of data.  My sample Excel document has the following columns:

ID A unique number identifying the row so we can use the Random data driven test
torpedoCount The input for our unit test
expected The expected result coming out of the function
shouldFail Whether the function will throw an exception.

I can then enter a single test on each row of the given worksheet.  Here's a screen shot --

You can create multiple "tables" by adding additional sheets to the worksheet.  Each sheet can be named as appropriate; I'm naming this one "TorpedoData".

Now, I need to add the appropriate attribute to my test case to indicate that it should pull the data from a data source and run the method once per row found.  The key is that any ADO.NET data source can be used.  Here I will specify my Excel file which is named "UnitTests.xls" and indicate that the table itself is a particular sheet within the Excel document "TorpedoData":

[TestMethod]
[DeploymentItem("Tests.xls")] // Copies the file to the deployment directory
[DataSource(
"System.Data.OleDb", // The provider
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='Tests.xls';Persist Security Info=False;Extended Properties='Excel 8.0'",
"TorpedoData$",      // The table name, in this case, the sheet name with a '$' appended.
DataAccessMethod.Sequential)] 

public
void TestFirePhotonTorpedo()
{

}

I also need to update the test case itself to use the data -- we do that through the TestContext.DataRow property that gives us access to the current row of data from our data source:

public void TestFirePhotonTorpedo()
{

   Enterprise target = new Enterprise();
  
int torpedoCount = Convert.ToInt32(TestContext.DataRow["torpedoCount"]);
   int expected = Convert.ToInt32(TestContext.DataRow["expected"]);
   bool shouldFail = (bool)TestContext.DataRow["shouldFail"];

   TestContext.WriteLine("Running test with TorpedoCount={0}, ExpectedCount={1}, ShouldFail={2}",
            torpedoCount, expected, shouldFail);

   try
   {
      int actual = target.FireTorpedos(torpedoCount);
      Assert.AreEqual(expected, actual, "FireTorpedos did not return the expected value.");
   }
   catch (Exception ex)
   {
      if (!shouldFail)
         Assert.Fail(string.Format("FireTorpedo threw exception {0}", ex.Message));
   }
}

So, here we will grab the data from the current row, converting it as necessary to the appropriate types, output a test line just to prove that we executed the method more than once and then run the test.  The test will compare the result with the expected database result and output a failure if they aren't the same.  If an exception is thrown, then the shouldFail must be true or that will be considered a failure.

This approach allows me to run through different scenarios very easily and I can just store the Excel worksheet right with my unit tests - make sure it's deployed to the target deployment directory (either through a DeploymentItem attribute, or through the test run configuration).  The size of my table here is about 14K, compared to the equivalent .MDF file which is over 2M for the same data.  If I didn't want to hardcode the filenames and such, I can also use an app.config file for the unit test and put the information there - just as Kev details.

Cool stuff indeed.

Monday, May 01, 2006 11:55:40 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code | Enterprise
# Thursday, April 20, 2006

Minor, but breaking update for ATAPI.NET (version number has changed).  It was pointed out to me that the assembly wasn't very VB.NET friendly in that it didn't show any events at the TapiManager level and you couldn't use the UI to hook it all up.  That's fixed and all the line-level events are also exposed at the TapiManager level for those who want to use VB.NET with the 2.0 wrapper.

 

Thursday, April 20, 2006 9:01:49 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Tapi
# Tuesday, April 04, 2006

Recently someone informed me that the TAPI wrappers (ITAPI3 and ATAPI) do not appear to function properly on the Win64 platform.  It throws an exception that says:

"Could not load file or assembly 'ITapi3, Version=1.0.0.3, Culture=neutral, PublicKeyToken=36377d9f6f1f4883' or one of its dependencies. An attempt was made to load a program with an incorrect format."

Now, as most know, .NET code compiles to an Intermediate Language (IL) which is a bytecode that is translated to the appropriate processor-specific instructions at runtime by the just-in-time (JIT) compiler.  The type of code that is generated is determined by the version of the CLR that is loaded.

When a .NET application starts, mscoree.dll is responsible for determining the proper version of the CLR to start for the process.  This is done by looking at the application manifest to see which version of .NET the application was compiled for (1.0, 1.1, or 2.0) and mscoree will suck in the appropriate assemblies and DLLs for that specific version, or in some cases, upgrade it silently to a newer version.

On Win64, the picture is a little more complex because we have to consider the platform as well.  There are actually two 2.x versions of .NET on Win64 - a 32-bit version (which is the same as the one running on Win32) and a 64-bit version which has been optimized for the 64-bit platform and generates 64-bit JITted code.  When an assembly starts on a Win64 platform, the mscoree.dll will look at not just the version, but also the platform flag which is coded into the manifest.  We can see this flag using ILDASM:

The .corflags above tells the loader that this particular assembly requires the 32-bit CLR, in other words, that we have a dependency on a 32-bit resource such as a COM object or platform DLL.  By default, the flag will be set to 0x0000001 (ILONLY) indicating no dependency (VS.NET refers to this as "AnyCpu" in the platform flag settings) and, on a Win64 machine, the assembly will be loaded under the 64-bit CLR.  With it set as above, on a Win64 machine it would be loaded into the 32-bit CLR.  For those who are interested in this aspect, there is a tool in the SDK (CORFLAGS.EXE) that will let you manipulate this flag and force an ILONLY assembly to be loaded as 32-bit.

VS.NET allows you to change the platform type on an assembly-by-assembly basis through the project settings, Build Tab:

When loading, this platform CLR determination appears to be, as with the CLR versioning, based solely on the assembly that starts the process.  The loader doesn't scan the dependencies and determine that one of the required assemblies is marked as '"x86" and will simply fail the process when that assembly eventually gets loaded.

So, if I have an assembly that requires 32-bit execution (such as ATAPI.NET or ITAPI3 that depend on the 32-bit TAPI subsystem and COM objects), but my starting assembly is marked as "AnyCpu", then the loader will start it under Win64 as a 64-bit process and when it tries to initialize ATAPI.NET or ITAPI3, it will fail the AppDomain with an exception.  Marking ATAPI.NET and ITAPI3 as "x86" (which they are by the way) won't help in this case -- you must mark your application as 32-bit.

This really is a bummer and, while I'm not surprise the CLR loader doesn't do it, I am surprised that VS.NET doesn't force the .EXE to be "x86" when it sees a dependency that requires it.

The wrappers do function under Win64, but only if the starting application has the platform target marked as "x86".

Tuesday, April 04, 2006 10:39:12 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET
# Monday, March 20, 2006

One issue that's always a struggle with building reusable components is managing asynchronous operations.  The problem is that depending on the type of application that is going to use the component, the thread used for callbacks and events may or may not be important.  For example, with Console based applications, callbacks on different threads might be ok - at least as long as the application itself ensures thread safety.  But, with a Windows Forms application, threading is critical - you are not allowed to touch UI controls from any thread other than the main one and so we end up with the Control.BeginInvoke logic in each of our callbacks which sucks.

Enter the Synchronization Context - a new feature of .NET 2.0.  Here's how it works:

You derive your component from System.ComponentModel.Component.Component and provide your typical asynchronous function -- in this example, we will build a PiCalculator:

public class PiCalculator : Component
{
   public PiCalculator();
   public object CalculatePi(int digits, object stateData);
   public void CancelAsync(object asyncTask);
}

Here, what we've done is create a new component with a default constructor and a method called CalculatePi which takes the number of digits, an optional piece of state data and returns an object.  With this component, I'd like to have multiple outstanding asynchronous operations and so I need some way to track each one to identify it when it completes, and also to cancel it if it runs too long.

Microsoft's general pattern for this is to use the stateData parameter and have the application pass in some unique value to identify the request. 

This is an ok way to do it, but it puts several restrictions on our implementation:

1) The state data must be supplied
2) The state data must be unique for each operation

In addition, there's the possibility of a race condition if I re-use the state data after canceling an operation.  So, to avoid all of these issues, I have the component return the task identifier as part of the request - this is the object return value coming back from CalculatePi.  I can then use that object to identify the results, and I can pass it into the component's CancelAsync method to cancel a pending request.

So, how do I get my results?  Through a delegate callback of course!  I need to create a delegate signature that uses it.  The general EventHandler callback signature is: void Method(object sender, EventArgs e) so, we'll use a derivative of this as our delegate:

public delegate void PiCalculationCompletedEventHandler(object sender, PiCalculationEventArgs e);

Then we'll create the class which will be used to report the results.  The class is pretty simple - just a data holder really:

public class PiCalculationEventArgs : EventArgs
{
   private int _digits;
   private string _value;
   private bool _canceled;
   private object _stateData;
   private object _taskId;

   public object TaskId
   {
      get { return _taskId; }
   }

   public object State
   {
      get { return _stateData; }
   }

   public bool Canceled
   {
      get { return _canceled; }
   }

   public int Digits
   {
      
get { return _digits; }
   
}

   public string Result
   {
      get { return _value; }
   }

   internal PiCalculationEventArgs(object taskId, int digits, string value, object stateData, bool canceled)
   {
      _digits = digits;
      _value = value;
      _canceled = canceled;
      _stateData = stateData;
      _taskId = taskId;
   }
}

Now we can implement out component.  First, we'll add a Completed event:

public event PiCalculationCompletedEventHandler CalculationComplete;

This will be used by the application to hook into the results of our component's calculation.  The next part is the key to all of this - AsyncOperation.  The AsyncOperation class is new to 2.0 and provides the facility to perform callbacks on the appropriate thread.  Essentially, it acts as a callback mediator - detecting the type of thread it was created on and then providing the appropriate marshaling code for it's internal delegate.  You utilize the callback through a new delegate type -- SendOrPostCallback.  We tie our callback to this delegate type and it will marshal us to the correct threading model.  We can then execute our own internal CalculationComplete event.  Here's the basic skeleton:  First, we will create an internal contained class which will be used to track the request.  This will actually be the object type we return from the CalculatePi method:

class AsyncStateData
{
   public AsyncOperation asyncOperation;
   public volatile bool canceled = false;
   public volatile bool running = true;

   public AsyncStateData(object stateData) 
   { 
      asyncOperation =
AsyncOperationManager.CreateOperation(stateData); 
   }
}

Notice the call to AsyncOperationManager.CreateOperation?  This is where we create our AsyncOperation class and this factory creator is the context detector.  We will have an AsyncOperation for each event we intend to fire back into the client - in our case one for each Pi calculation.  But, I could also create a single instance for the client as well - this is actually what is done in the ITapi3 component to allow it to be integrated onto a Windows Form even though events are being received on a background thread.  The Tapi events are always fired on the appropriate thread - the background one for non-WinForms apps and the UI thread for WinForms apps.

Next, we will create our internal callback - this is the callback that will actually be fired internally and then call the real application event, so we'll hook that up with an anonymous delegate in the constructor of our component:

private SendOrPostCallback completionMethodDelegate;

public PiCalculator()
{
   completionMethodDelegate =
delegate(object evt)
   {
      
// Called on the synchronization thread.
      
if (CalculationComplete != null)
         CalculationComplete(
this, (PiCalculationEventArgs)evt);
   };
}

Now, let's implement our CalculatePi method - it's pretty simple, we'll use an asynch delegate to our internal calculator, invoke it and return the AsyncStateData structure we create to identify each task submitted to the component.  Then the calculation will be performed on a thread pool thread and we'll callback to the client when it is finished.

public object CalculatePi(int digits, object stateData)
{
   PiDelegate piDel = InternalCalculatePi;
   
AsyncStateData asyncData = new AsyncStateData(stateData);
   piDel.BeginInvoke(digits, asyncData,
delegate(IAsyncResult ar) { piDel.EndInvoke(ar); }, null);
   
return asyncData;
}

CancelAsync is pretty simple too -- it will simply set the Canceled flag of the request:

public void CancelAsync(object asyncTask)
{
   
AsyncStateData asyncData = asyncTask as AsyncStateData;
   
if (asyncData != null && asyncData.running == true)
      asyncData.canceled =
true;
}

Now, we need to implement our PiCalculator.  We're going to cheese out here and just "pretend" to calculate Pi since that wasn't really the point of this component :-)  We'll define a delegate to use for the asynch execution and then implement our function:

private delegate void PiDelegate(int digits, AsyncStateData asyncData);
private void InternalCalculatePi(int digits, AsyncStateData asyncData)
{
   string PI_DIGITS = "3.141592637309238932482438234724782347234";
   
if (digits > PI_DIGITS.Length - 2)
      digits = PI_DIGITS.Length - 2;

   // This would be a real calculator here..
   
int completedDigits = 0;
   
for (; !asyncData.canceled && completedDigits < digits; completedDigits++)
   {
      
Thread.Sleep(1000);
   }

   asyncData.running = false;
   
string data = PI_DIGITS.Substring(0, completedDigits + 2);
   asyncData.asyncOperation.PostOperationCompleted(
      
completionMethodDelegate,
      
new PiCalculationEventArgs(asyncData, digits, data, asyncData.asyncOperation.UserSuppliedState, asyncData.canceled));
}

The key to the callback is the invocation of the PostOperationCompleted method from the AsyncOperation instance we created.  It is what calls our handler which will in turn call the client.  Once PostOperationCompleted is called, no further work may be done with the AsyncOperation.  So, it's not appropriate for progress reporting - instead you can use PostOperateration for that which allows for multiple calls. 

Now, when using this component, we can simply call it as expected:

static void Main(string[] args)
{
   ArrayList taskIds = new ArrayList();
   
   PiCalculator piCalc = new PiCalculator();
   piCalc.CalculationComplete +=
delegate(object sender, PiCalculationEventArgs e)
   {
      Console.WriteLine("[{0}] {1} = {2}, Canceled = {3}"
         
Thread.CurrentThread.ManagedThreadId, e.Digits, e.Result, e.Canceled);
   }         

   
foreach (string s in args)
   {
      taskIds.Add(piCalc.CalculatePi(
Convert.ToInt32(s), s));
   }

   Console.WriteLine("Waiting for results .. press ENTER to cancel.");
   
Console.ReadLine();

   foreach (object task in taskIds)
   {
      piCalc.CancelAsync(task);
   }

   Console.WriteLine("Press ENTER to terminate");
   
Console.ReadLine();
}

Here's the output:

Waiting for results .. press ENTER to cancel.
[3] 10 = 3.1415926373, Canceled = False
[4] 11 = 3.14159263730, Canceled = False
[5] 14 = 3.14159263730923, Canceled = False
[5] 15 = 3.141592637309238, Canceled = False
[5] 17 = 3.14159263730923893, Canceled = False

Press ENTER to terminate
[5] 20 = 3.1415926373092389324, Canceled = True

Not real exciting right?  Notice the thread id in the [brackets] is different for some of the callbacks.  This indicates we are getting called back on different threads - certainly not the main thread which is waiting for console input.  The cool part of this component is that I can use it exactly the same way in a Windows Forms application!  So, I don't have to know that the callback is on a different thread!  I don't have to worry about doing a BeginInvoke or Invoke to get back to the UI thread.  So, here's an example WinForm application:

public partial class CalcPiTestForm : Form
{
   ArrayList _pendingTasks = new ArrayList();

   public CalcPiTestForm()
   {
      InitializeComponent();
   }

   private void CalcPiTestForm_Load(object sender, EventArgs e)
   {
      piCalculator1.CalculationComplete += new UserMath.PiCalculationCompletedEventHandler(piCalculator1_CalculationComplete);
   }

   void piCalculator1_CalculationComplete(object sender, UserMath.PiCalculationEventArgs e)
   {
      lock(_pendingTasks)
      {
         _pendingTasks.Remove(e.TaskId);
      }

      // No need to do BeginInvoke here!!
      listBox1.Items.Add(string.Format("[{0}] {1} = {2}, Canceled = {3}",
         System.Threading.Thread.CurrentThread.ManagedThreadId, e.Digits, e.Result, e.Canceled));
   }

   private void btnCalculate_Click(object sender, EventArgs e)
   {
      if (maskedTextBox1.Text.Length > 0)
      {
         lock(_pendingTasks)
            _pendingTasks.Add(piCalculator1.CalculatePi(Convert.ToInt32(maskedTextBox1.Text)));
      }
   }

   private void btnCancel_Click(object sender, EventArgs e)
   {
      lock(_pendingTasks)
      {
         foreach (object task in _pendingTasks)
            piCalculator1.CancelAsync(task);
      }
   }
}

Notice the output here -- we haven't done anything special with the component's callbacks, but now the callback is always on thread [1].  This is the magic of AsyncOperation and synchronization contexts.  Now go out there and write some thread-aware components!  If you'd like this entire sample, here is the project: http://www.julmar.com/samples/asyncop.zip

Monday, March 20, 2006 5:42:45 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code
# Friday, March 17, 2006

I love anonymous delegates - I think they are extremely useful and allow me to solve some problems in very elegant ways.  However, once you really get into them, you start to see the dark side of anonymous delegates and that is unregistration.

Here's the basic problem: when binding an instance delegate to an event to handle some activity, the delegate will cache off the instance reference - thereby keeping the reference alive.  So for example, if I had a form which wanted to process some activity from an object:

class Publisher
{
   public event EventHandler OnEvent;
   ...
}

class MainForm : Form
{
   Publisher _pub = new Publisher();

   void ActivateChildForm() 
   {
      ChildForm f = new ChildForm(_pub);
      f.Show();
   }
}

class ChildForm : Form
{
   public ChildForm(Publisher pub) 
   {
      pub.OnEvent += ProcessEvent;
   }
   void ProcessEvent(object sender, EventArgs e)
   {
      listBox1.Items.Add("Event was fired!");      
   }
}

When the ChildForm instance is closed, the form won't be collected because the Publisher (_pub) is holding a reference to it.  This is easily fixed by adding some code into the FormClosing event:

class ChildForm : Form
{
   Publisher _pub;

   public ChildForm(Publisher pub)
   {
      _pub = pub;
      _pub.OnEvent += ProcessEvent;
   }

   void FormClosing(object sender, FormClosingEventArgs e)
   {
      _pub.OnEvent -= ProcessEvent; 
   }
}

Now, the form will be cleaned up when it's closed.  This is pretty standard stuff, and most people that have been using .NET for a while know all this.  Here's the rub: with .NET 2.0, we can simplify the code using anonymous delegates which are really helpful for these single-line processing event handling functions.  So, I could recode my handler as:

class ChildForm : Form
{
   public ChildForm(Publisher pub) 
   {
      pub.OnEvent += delegate { listBox1.Items.Add("Event was fired!"); }
      this.OnClosing += delegate { pub.OnEvent -= ????? }

   }
}

The issue is that I don't have a reference to the delegate as it's typed.  Under the covers, the C# compiler has generated a temporary function (or possibly even pulled it out to a separate inner class) and there's no way for me to get to the underlying function.  So, what can I do?  Well, the easiest thing to do is to save off the function:

class ChildForm : Form
{
   public ChildForm(Publisher pub) 
   {
      EventHandler eh = delegate { listBox1.Items.Add("Event was fired!"); }
       
      pub.OnEvent += eh;      
     
this.OnClosing += delegate { pub.OnEvent -= eh; }
   }
}

Now my code will function properly -- and is significantly reduced in size.  Of course, I've lost the benefit of being able to hook up events through VS.NET because it always generates seperate functions and I would need to cache off the Publisher instance as well as my delegate in that case. 

So, rule #1, always unregister the event when you are finished.  Rule #2, remember that anonymous delegates may be keep your instance alive so unregister them as well, unless the event is to be hooked up throughout the lifetime of the application.

Friday, March 17, 2006 11:56:40 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code
# Monday, March 13, 2006

I got hit with this problem from two separate clients last week - a .NET 1.1 application ported to .NET 2.0 is now terminating abruptly for no apparent reason.  Well, of course there's a reason - and it's that both applications had "hidden" exceptions being thrown in some background thread that weren't being caught.  Under .NET 1.1, the CLR would print any exceptions that occurred on threadpool threads to the console and then return the thread to the pool.  In addition, the CLR would silently eat any exception thrown on the finalizer thread (again printing the stack trace to the console).  Under .NET 2.0, the behavior has changed and it will cause the AppDomain to be unloaded (yikes!).  So, for example:

class BadClass
{
  ~BadClass()
  {
    throw new Exception("I'm Bad"); 
  }
}

class BadClass
{
  static void Main()
  {
     for (; ;)
       
new BadClass();
  }
}

The above code would run forever under CLR 1.1, but will terminate immediately when run under CLR 2.0 with an unhandled exception. 

Unhandled Exception: System.Exception: I'm bad
   at BadClass.Finalize() in W:\Projects\TestApp\TestApp\Program.cs:line 11

There are a couple of ways to deal with this - the best is to do all your testing and close the holes.  You really shouldn't have unhandled exceptions loose in your program.  But for a really large program, or one where you don't know where the exception is happening, Microsoft has given you a couple of options.  The first one is the <legacyUnhandledExceptionPolicy>  tag which you can put into your app.config file:

<configuration
  <
runtime

    <
legacyUnhandledExceptionPolicy enabled="1"
/> 
  <runtime
>
<configuration>

This will essentially revert the CLR to the 1.1 behavior.  Consider it a short-term fix because it will ultimately mask issues with your application that are really bugs.
 
Along with the above, you can also be notified about unhandled exceptions prior to the AppDomain being unloaded.  This is done through several different methods based on the type of application.  The first basic method is through the AppDomain.UnhandledException event which is raised for Console applications:

static
void Main()
{
   
AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs
e)  
   { 
      
Console.WriteLine("{0} - IsTerminating = {1}"
, e.ExceptionObject.ToString(), e.IsTerminating); 
   
};

   for (; ;)
      
new BadClass
();
}

In this case, the application will still be terminated, but we will now get notified right before termination.  This allows our application to log the error (using the nifty System.Diagnostics.TraceSource support or through the EventLog) so we at least know what happened.

For Windows Forms applications, things are a little different -- instead of the AppDomain.UnhandledException event being raised, the Windows Forms infrastructure will raise the Application.ThreadException event for exceptions that occur on the primary thread.   The default behavior for this handler is to display the friendly System.Windows.Forms.ThreadException dialog:

If the exception occurs in the primary (message pumping) thread, the user will see the above dialog box and be given the choice to terminate the application or not.  The code behind it looks something like:

void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
   
try
   
{
      
// Call user override
      
if (this.threadExceptionHandler != null
)
      {
         
this.threadExceptionHandler(Thread.CurrentThread, new ThreadExceptionEventArgs
(e.Exception));
      }
      
else
      
{
         
using (ThreadExceptionDialog excptDlg = new ThreadExceptionDialog
(e.Exception))
         {
            
DialogResult
result = excptDlg.ShowDialog();
            
if (result == DialogResult
.Abort)
               
Application
.Exit();
         }
      }
   }
   
catch
   
{
   }
}

That's great for the main thread, but if the exception occurs in a secondary thread, then the application will still be terminated after raising the AppDomain.UnhandledException event.  So, for non-UI threads, you must still register the unhandled exception handler on the AppDomain, log the failure and then watch your application die.  Having two handlers can be a pain and if you want to have the application terminate on any unhandled exception, you can direct Windows Forms to not catch primary thread exceptions automatically by using the Application.SetUnhandledExceptionBehavior method:

[STAThread]
static void
Main()
{
   Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
   Application.Run(new Form1());
}

The above line will cause exceptions thrown in the main thread to be unhandled - thereby triggering the AppDomain.UnhandledException event.

For ASP.NET applications, things are also a bit different.  First, be aware that any exception thrown during a Page request (the normal Page rendering process) will be handled automatically by ASP.NET and rendered back to the client based on the error settings in web.config.  If I throw an exception while rendering the page, then I'll get an HTML response like:

Server Error in '/TestWebSite' Application.
Bye, Bye!

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

The important thing here is that the AppDomain continues to run.  I can tell ASP.NET to redirect to a specific page through the <customErrors> section of the web.config.  Or, I can catch these exceptions and handle them myself through the global.asax Application_Error method (which is hooking the HttpApplication.Error event):

void Application_Error(object sender, EventArgs e)
{
   Exception
ex = Server.GetLastError();
   Context.ClearError();
  // Stop default error reporting
   
Response.Write(
"Application Error:");
   Response.Write(
"" + Server.HtmlEncode(ex.ToString()) + ""
);
}

A more popular way to display errors is to cache off the last error in a session variable and then execute Server.Transfer to some error.aspx page:

void Application_Error(object sender, EventArgs e)
{
   Exception
ex = Server.GetLastError();
   Session["LastException"] = ex;

   
Server.Transfer("myerrorpage.aspx");

}

Unfortunately, just like Windows Forms, if an unhandled exception occurs on a separate thread (such as a Threadpool thread), or outside the request processing framework, then the AppDomain is terminated.  This has significant consequences for ASP.NET applications - because the website itself is cycled.  This means you have lost session state and your users are going to notice the website outage.  Most of the time, there isn't much information to work off of -- you end up with a cryptic Event Log entry like:

EventType clr20r3, P1 w3wp.exe, P2 6.0.3790.1830, P3 4333d6f1, P4 app_web_5hu0gabf, P5 0.0.0.0, P6 4415a8be, P7 7, P8 a, P9 system.exception, P10 NIL.

In order to get more information, we need to hook the AppDomain.UnhandledException event and then log the information, just like we have for Windows Forms and Console applications.  We could put a handler into our global.asax, but that would only handle that one web application.  It would be better to create a new HTTP Module with the event handler and hook that up through the web.config.  Luckily for me, Microsoft has already published a KB article which shows off this exact solution - http://support.microsoft.com/?id=911816.  In this article, Microsoft details creating a new HttpModule class which will log the exception information to the event log so you will know exactly where the exception occurred and can provide your own exception handling.  Unfortunately, without the above <legacyUnhandledExceptionPolicy> entry, the website will still be cycled.

Bottom line is: be aware of this new, breaking change -- look for places where you might not be handling exceptions properly and implement good audit trail mechanisms to log failures when/if they occur.  This will allow you to find and fix issues before they become production problems as you port your legacy code over to .NET 2.0!

Monday, March 13, 2006 1:07:55 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code
# Thursday, February 16, 2006

I've really gotten into using code snippets and the compiler expansions in VSNET 2005 -- it cuts my typing way down and I love it.  I've always thought it odd that VB.NET had a ton more snippets pre-installed than C# (my language of choice).  But Microsoft has rectified that with the release of C# snippets on MSDN (http://msdn.microsoft.com/vstudio/downloads/codesnippets/default.aspx) which includes most, if not all the VB.NET ones but recoded for C#.

Now, the hard part will be knowing what's there!

Thursday, February 16, 2006 7:17:20 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET

So, at the GNET2 last week, I found out that you can now call Delegate.Invoke instead of using the C# functor syntax.  This makes code much more readable IMO --

delegate void MyCallback(string msg);
...
MyCallback callback;
...
callback += delegate(string msg) { Console.WriteLine(msg); };
...
callback.Invoke("Hello");   // instead of callback("Hello");

Very nice.

Thursday, February 16, 2006 8:58:44 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET
I'm a WPF Disciple
Search
Categories
Archive
<March 2010>
SunMonTueWedThuFriSat
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Mark Smith
Sign In
All Content © 2010, Mark Smith
DasBlog theme 'Business' created by Christoph De Baene (delarou)