... a journey through WPF, MVVM and .NET4 RSS 2.0
# Friday, April 16, 2010

… and available on codeplex in beta form:  http://mvvmhelpers.codeplex.com

There are several new features in this release that I've been tinkering with for a while.  First, I now use MEF to link things together.  I waited until .NET 4.0 was released to push this out because MEF is part of the framework now.  If you don't want to take a dependency on it (in 3.5) then please stay with 1.06 which is also available. 

Managing Services with the Service Locator pattern + MEF

The advantage to MEF are several.  First, you can easily add or replace services.  To add a new service to the service locator, you can just add your class and then decorate it with [ExportServiceProvider]:

[ExportServiceProvider(typeof(PlaySoundService))]

public class PlaySoundService

{

    public void Beep()

    {

        new SoundPlayer(@"./media/ding.wav").Play();

    }

}

 

There’s no need to register it, and if you want to replace an existing service (such as the IUIVisualizer) you can simply supply the interface type to the attribute – the ServiceProvider will automatically defer to your version instead of the built-in one.  This also means there’s no need to register default services – so the RegisterDefaultServices call is gone.

To consume the service you can use the traditional syntax:

public MainViewModel()

{

    BeepCommand = new DelegatingCommand(() => Resolve<PlaySoundService>().Beep());

}

 

or you can rely on MEF to do dependency injection if you’d like to decouple from the service provider altogether.  To do this, simply declare a field or property and mark it with an [Import] attribute, and make sure to add an [Export] to the service declaration:

[ExportServiceProvider(typeof(PlaySoundService))]

[Export]

public class PlaySoundService

{

}

...

public class MainViewModel : ViewModel

{

   [Import] private PlaySoundService _playSoundService;

 

   public ICommand BeepCommand { get; private set; }

   public MainViewModel()

   {

      BeepCommand = new DelegatingCommand(() => _playSoundService.Beep());

   }

}

How cool is that?  All the pre-defined services are already exported through the interface itself, so if you want to import a built-in service such as the IUIVisualizer, you can simply create a field and mark it as an [Import] and MEF will take care of the rest.  As I mentioned, you can continue to use Resolve<T> if you prefer a more obvious approach, or like me, prefer to not cache off common services in fields.  Be aware that the instance supplied to you for the predefined services will always be global – i.e. you will get a copy of the exact same instance that the service provider hands out through Resolve<T>.

View First Creation with MEF

The next new thing is VM + View creation.  The library supports both ViewModel first and View first creation.  The MainWindow is typically created using View-first mechanics (since it is normally created by the application startup process).  To hook up a ViewModel to it you use the ViewModelCreator markup extension, in prior versions of the library you supplied the type to create (and optionally the designer type):

<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"

   DataContext="{julmar:ViewModelCreator {x:Type ViewModels:MainViewModel}, DesignerViewModelType={x:Type ViewModels:.DesignTimeViewModel}}"

   Title="Test Project" Height="400" Width="500">

 

Notice that this requires we push knowledge of the VM into the view – this isn’t necessarily a bad thing and you can still use this approach, but Version 2.0 adds in the ability to decouple them further.  Now you can specify the shared Key to use to connect them together.  If you add this, the type (if supplied) will be ignored:

<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"

   DataContext="{julmar:ViewModelCreator Key=MainWindow}"

   Title="Test Project" Height="400" Width="500">

 

The key is just a shared string – so it’s not compile-time safe which is a downside to this approach.  However now we have no dependency at all on the type being created by the developer.  A design-time DLL could supply any type as long as it exports the proper key.  Here’s how we associate the ViewModel:

[ExportViewModel("MainWindow")]

public class MainViewModel : ViewModel

{

 

Note the shared key being used here.  With this in place, the ViewModelCreator extension will go through MEF to locate and create the ViewModel.  Any imports/exports on that type would be satisfied as normal.

ViewModel First creation with MEF + IUIVisualizer

You can also go the other direction – where the VM is created first and you want to associate the view dynamically.  The approach I’ve taken here is to piggy back on the existing IUIVisualizer service.  Recall from prior posts that it is responsible for creating new popup windows (either modal or modaless) inside the VM – to display child dialogs for example.  Prior to this release, you were responsible for registering each view with the service.  With the magic of MEF you can now simply decorate the View with [ExportUIVisualizer]:

[ExportUIVisualizer("ChildWindow")]

public partial class ChildWindow : Window

{

 

This will cause the window to be registered automatically with the IUIVisualizer service so that in some VM you can show it:

ShowChild = new DelegatingCommand(() => Resolve<IUIVisualizer>().ShowDialog("ChildWindow"));

 

Again, the key is a string that you must synchronize, not unlike the registration process in V1 of the library.  You can pass the ViewModel into the child dialog (Show and ShowDialog both take a parameter for this), or if you place the {ViewModelCreator} tag onto your child window it will be located dynamically.

Closing Thoughts

Finally, another minor change is the base ViewModel class now automatically registers with the message mediator, so the call to register is not necessary in derived classes.  It has been removed so any existing code will get a compile error if you try to call it – just remove your call.

I hope you find the library easy to use – the source, binaries and templates are all on codeplex.  There is a project template for Visual Studio 2008 and another for Visual Studio 2010 – make sure to copy them into the appropriate template directories.  As always, comments are welcome!

Here’s the sample if you want to peruse it:  V2SampleApp.zip

Friday, April 16, 2010 11:19:29 AM (Central Daylight Time, UTC-05:00)  #    Comments [1] -

# Tuesday, April 13, 2010

I have updated MVVM Helpers against the RTM of Visual Studio 2010.  I will be updating the codeplex site (http://mvvmhelpers.codeplex.com) shortly, but in the meantime, here’s the project template for Visual Studio 2010.  Copy the .zip into your templates directory, mine is located at:

C:\Users\Mark\Documents\Visual Studio 2010\Templates\ProjectTemplates\Visual C#

Here’s the file.

Tuesday, April 13, 2010 10:34:06 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | MVVM | WPF
# Monday, March 22, 2010

Today I was building a simple simulator to test some events to a new piece of hardware I’m working on.  Of course, I’m using WPF to show the simulator – and I wanted to create a topmost window that did not have a Close button on it.  Imagine my surprise when I realized there was not a set of flags you could supply to the Window object to actually achieve this result!

However, with a little Win32 mojo we can get the desired effect:

public partial class MainWindow
{
    public MainWindow()
    {
        SourceInitialized += MainWindow_SourceInitialized;
        InitializeComponent();
    }

    void MainWindow_SourceInitialized(object sender, EventArgs e)
    {
        WindowInteropHelper wih = new WindowInteropHelper(this);
        int style = GetWindowLong(wih.Handle, GWL_STYLE);
        SetWindowLong(wih.Handle, GWL_STYLE, style & ~WS_SYSMENU);
    }

    private const int GWL_STYLE = -16;
    private const int WS_SYSMENU = 0x00080000;

    [DllImport("user32.dll")]
    private extern static int SetWindowLong(IntPtr hwnd, int index, int value);
    [DllImport("user32.dll")]
    private extern static int GetWindowLong(IntPtr hwnd, int index);
}

The key here is hooking the SourceInitialized event and then using the SetWindowLong function to strip off the WS_SYSMENU bit.  You can just cut/paste this code right into your solution.

Monday, March 22, 2010 3:32:02 PM (Central Daylight Time, UTC-05:00)  #    Comments [2] -
.NET | Code | WPF
# 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

I’ve published it to http://mvvmhelpers.codeplex.com/ where I’ll continue to maintain and add to it.  Get the latest release from there!

Saturday, February 06, 2010 9:20:51 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -

# 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'm a WPF Disciple
Search
Categories
Archive
<September 2010>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789
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)