Archives for : WPF

Live Filter Design Pattern in XAML

GetTheCode

I decided I should start titling my posts with XAML instead of WPF as they are applicable regardless of whether you are developing in Windows 7 with WPF or Windows 8. I’m going to take the BreadCrumb design pattern sample and extend it to include the Live Filter design pattern.

The premise behind the Live Filter design pattern is pretty simple, show the user everything and then allow them to filter the results, immediately showing how the filter affects the results. As noted in the BreadCrumb post dense trees can easily become overwhelming to users. Providing a simple, easy to use live filter makes the experience significantly better.LiveFilter

In the above image you can see there we have a search text box with two filter parameters. As the user types into the search box the results are immediately filtered.

<Grid Grid.Row="0" Grid.ColumnSpan="3" Margin="5">
    <xctk:WatermarkTextBox Margin="2" Watermark="Search" Text="{Binding SearchValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    <Button Margin="5 0 5 0" Width="16" Height="16" HorizontalAlignment="Right" FontFamily="Segoe UI Symbol" Opacity=".75" ToolTip="Clear" Command="{Binding ClearCommand}">
        <TextBlock Margin="0 -3.5 0 0" Foreground="#FF63A3B2">👽</TextBlock>
    </Button>
</Grid>
<StackPanel Grid.Row="1" Grid.ColumnSpan="3" Margin="5" Orientation="Horizontal">
    <CheckBox Margin="5" IsChecked="{Binding SearchProperty2, Mode=TwoWay}" Content="Include Property 2 In Search" />
    <CheckBox Margin="5" IsChecked="{Binding SearchProperty3, Mode=TwoWay}" Content="Include Property 3 In Search" />
</StackPanel>

Above is the XAML for the search controls. Most of it is standard MVVM binding. The problem with standard MVVM binding is that for textbox it only updates the underlying view model property on lost focus. That doesn’t help us as we want to update the results in real-time. To fix this the UpdateSourceTrigger is set to PropertyChanged. This way as soon as the user types a letter the property is changed and we can perform a search. (I’m actually using the nuget package for the Extended WPF Toolkit to provide a watermark textbox but it works like a regular textbox).

<TreeView Grid.Row="2" Grid.RowSpan="2" Margin="5" 
        ItemsSource="{Binding ChildNodes}"
        VirtualizingStackPanel.IsVirtualizing="True"
        VirtualizingStackPanel.VirtualizationMode="Recycling"
        SelectedItemChanged="TreeView_SelectedItemChanged">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="Visibility" Value="{Binding Visibility, Mode=TwoWay}" />
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <StackPanel>
                <TextBlock Text="{Binding Property1}" FontSize="18" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

The first important part is the TreeViewItemContainerStyle. The nodes implement the properties IsExpanded and Visibility. This is extremely important. We don’t want to have to deal with the ItemContainerGenerator. This can be a major pain the rear and will make the code extremely sluggish. If we’re going to go with binding the nodes in the tree let’s take full advantage of it. The other important part is setting up the VirtualizingStackPanel values. The search is really rather trivial and usually works extremely fast. The slow part is updating the UI. We leave that to the masters at Microsoft by binding everything and letting them figure out how to render it. But we can help things out a bit. By setting up the VirtualizingStackPanel the control doesn’t have to render all the children in the tree. Now use this with some caution. Because the nodes will only be updated as the user drags the scroll bar you can get some choppy and sluggish operations as the control updates.

string searchValue;
public string SearchValue
{
    get { return searchValue; }
    set
    {
        if (SetProperty(ref searchValue, value))
        {
            PerformSearch();
        }
    }
}

bool searchProperty2 = false;
public bool SearchProperty2
{
    get { return searchProperty2; }
    set 
    {
        if (SetProperty(ref searchProperty2, value))
        {
            PerformSearch();
        }
    }
}

bool searchProperty3 = false;
public bool SearchProperty3
{
    get { return searchProperty3; }
    set 
    { 
        if(SetProperty(ref searchProperty3, value))
        {
            PerformSearch();
        }
    }
}

These are the properties in the view model. We’re using BindableBase from Prism for the view model. Thus SetProperty returns a true if there was a change. We need to minimize extraneous calls to PerformSearch as much as possible.

private static object lockObj = new object();
private CancellationTokenSource CancellationTokenSource { get; set; }
private void PerformSearch()
{
    //if we're doing a search then we probably have some new search term
    clearCommand.RaiseCanExecuteChanged();

    lock (lockObj)
    {
        if (CancellationTokenSource != null)
            CancellationTokenSource.Cancel();

        CancellationTokenSource = new CancellationTokenSource();

        resultCount = 0;
    }

    Task.Run(() =>
    {
        DateTime now = DateTime.Now;
        try
        {
            if (string.IsNullOrEmpty(SearchValue))
            {
                ClearAllNodes(ChildNodes, Visibility.Visible, CancellationTokenSource.Token);
                return;
            }
            else
            {
                ClearAllNodes(ChildNodes, Visibility.Collapsed, CancellationTokenSource.Token);
            }

            var options = new ParallelOptions { CancellationToken = CancellationTokenSource.Token };
            try
            {
                Parallel.ForEach(ChildNodes, options, (childNode) =>
                {
                    PerformSearch(childNode, options);
                });
            }
            catch (OperationCanceledException)
            {
                //Noop
            }
        }
        finally
        {
            LastSearchTookInMilliseconds = (DateTime.Now - now).Milliseconds;
            OnPropertyChanged(() => ResultCount);
        }
    }, CancellationTokenSource.Token);
}

private void PerformSearch(RandomValueNode childNode, ParallelOptions options)
{
    if (options.CancellationToken.IsCancellationRequested)
        return;

    if (childNode.Property1.StartsWith(SearchValue) ||
        (SearchProperty2 && childNode.Property2.StartsWith(SearchValue)) ||
        (SearchProperty3 && childNode.Property3.StartsWith(SearchValue)))
    {
        Interlocked.Increment(ref resultCount);
        childNode.IsExpanded = true;
        childNode.Visibility = Visibility.Visible;
    }
    foreach (RandomValueNode node in childNode.Children)
    {
        if (options.CancellationToken.IsCancellationRequested)
            break;

        PerformSearch(node, options);
    }
}

And finally we do the search. To make this as responsive as possible we need to cancel the search each time as quickly as possible. Thus I’m using a CancellationToken in the Task.Run and the Parallel.ForEach to do the search. Remember that it is only effective to spin off threads from the thread pool if you can give them enough work. In my case there will only be ten nodes but I give each of those plenty to do. I’m passing the options into the PerformSearch so that we kill the search as quick as possible. As the code recurses I want to kill everything. It may seem like overkill to check for options.CancellationToken.IsCancellationRequested at the top of the method and in the foreach, and it may very well be.

So this pattern is pretty straightforward, simply update live results as the user changes the filter parameters. The key here is taking into account the result set size and to stop any existing search quickly, really try and take advantage of all that the TPL provides. As you can see in the image at the top I can iterate over 700,000 nodes pretty quickly and the UI is still pretty responsive. Of course that is really more because of the Task.Run and using VirtualizingStackPanel.

There is, of course, another way to do this. If you find that things are moving much too sluggish the other alternative is to show a minimal amount of results (like when doing a Google search and it begins to suggest terms). Then in the background have a thread that starts to update the results.

I would encourage you to get the code from the “GET THE CODE” button at the top.

Thanks for reading,
Brian

Bind a ComboBox to an enum while using Display attribute

I found a lot of different tutorials on binding a ComboBox to an enum but none of them worked. In every case the ComboBox would not stay selected to the value I chose, instead always reverting back to the previous selected value. Couple that with the fact that I wanted to use the Display attribute and, well, all hell broke loose.

So here I am with a brief write-up on my solution.

Let’s start with our model. In this case we’ll be designing a shirt. We’ll only be defining a shirt type but maybe in the future I might do something else with the sample. You’ll need to make sure you add the “System.ComponentModel.DataAnnotations” reference to your project if it’s not already there. That is where the Display attribute is.

public enum ShirtType
{
    [Display(Name="Dress Shirt")]
    DressShirt,
    [Display(Name="T-Shirt")]
    TShirt,
    CampShirt,
    Polo,
    Jersey
}

public class Shirt : INotifyPropertyChanged
{
    ShirtType type = ShirtType.DressShirt;
    public ShirtType Type
    {
        get { return type; }
        set { SetProperty(ref type, value); }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (object.Equals(storage, value)) 
            return false;

        storage = value;
        OnPropertyChanged(propertyName);

        return true;
    }

    protected void OnPropertyChanged(string propertyName)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion
}

The shirt model is unremarkable. Since this is just a basic sample I’ve implemented INotifyPropertyChanged instead of using the BindableBase from Prism. What is interesting is the use of the DisplayAttribute on the enum values. The Display attribute allows you to define a name and optional resource for localization. There are some other properties but those are the two we care about. Next we’ll use a converter to change this attribute into a value for the ComboBox.

public class EnumToDisplayAttribConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!value.GetType().IsEnum)
        {
            throw new ArgumentException("Value must be an Enumeration type");
        }

        var fieldInfo = value.GetType().GetField(value.ToString());
        var array = fieldInfo.GetCustomAttributes(false);

        foreach (var attrib in array)
        {
            if (attrib is DisplayAttribute)
            {
                DisplayAttribute displayAttrib = attrib as DisplayAttribute;

                //if there is no resource assume we don't care about localization
                if (displayAttrib.ResourceType == null)
                    return displayAttrib.Name;

                // per http://stackoverflow.com/questions/5015830/get-the-value-of-displayname-attribute
                ResourceManager resourceManager = new ResourceManager(displayAttrib.ResourceType.FullName, displayAttrib.ResourceType.Assembly);
                var entry =
                    resourceManager.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true)
                      .OfType<DictionaryEntry>()
                      .FirstOrDefault(p => p.Key.ToString() == displayAttrib.Name);

                var key = entry.Value.ToString();
                return key;
            }
        }

        //if we get here than there was no attrib, just pretty up the output by spacing on case
        // per http://stackoverflow.com/questions/155303/net-how-can-you-split-a-caps-delimited-string-into-an-array
        string name = Enum.GetName(value.GetType(), value);
        return Regex.Replace(name, "([a-z](?=[A-Z0-9])|[A-Z](?=[A-Z][a-z]))", "$1 ");
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

Now this is where the magic happens. The converter takes in the enum bound to the row in the ComboBox and converts it to a string. If a custom DisplayAttribute can be found and it has a resource then it attempts to get the value for localization. Otherwise it just uses the value straight up. If there is no DisplayAttribute then it tries to be smart and converts a Pascal Cased enum to have spaces.

Okay, now we’ve got the enums, we’ve got the converter, now how do we wire it up? We’re going to bind to an ObjectDataProvider in the XAML.

<Window x:Class="BindingToEnum.MainWindow"
        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:local="clr-namespace:BindingToEnum"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:Shirt />
    </Window.DataContext>
    <Window.Resources>
        <local:EnumToDisplayAttribConverter x:Key="enumToDisplayAttribConverter" />
        <ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="dataFromShirtType">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:ShirtType" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <ComboBox Grid.Row="0" MinWidth="100" HorizontalAlignment="Left" 
                            FontSize="20"
                            ItemsSource="{Binding Source={StaticResource dataFromShirtType}}"
                            SelectedItem="{Binding Type}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding ., Converter={StaticResource enumToDisplayAttribConverter}}" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>
</Window>

So lets look at the important bits of this:

Line 04: We have to add the sys namespace.
Line 05: Our local namespace.
Line 11: The converter we’re going to use.
Line 12: The ObjectDataProvider. This will get the values of the enum to be used later.
Line 14: The actual type of the enum we’re retrieving.
Line 24: We bind the ItemsSource of the ComboBox to the key of the ObjectDataProvider defined on line 12.
Line 25: We bind the Selected Item to the “Type” property of our model.
Line 26: We want to define a custom data template so we can use our converter.
Line 28: We bind the text of the text block to “.”. This just means use the data context we’re bound to. Since each row in a ComboBox will be bound to an enum, this just means we’re using the enum for the row.
And finally use the converter we defined at line 11.

Of all of this, probably the biggest take-away is binding the TextBlock.Text to “.”. This way the enum will be passed off to our converter. Attached is the code.

Thanks for reading.
Brian

Binding a Dependency Property of a View to its ViewModel

UPDATE 07/30/2014:
Please be sure to check out the second part to this at Binding a Dependency Property of a View to its ViewModel, part Deux which contains a working sample solution of the code here.

I like MVVM in concept and I had prepared a long, off-topic rant about MVVM because of a bit of trouble I’m having with it at the moment.  I deleted it, however.  Maybe I’ll make it an on-topic post at some point in the future.  Regardless, one of the issues I had was I needed to make a user control that could not only be the primary control of a view but I needed it to be a child control of another view.  There are a lot of complex operations that the view model controls in terms of handling states and progress bars.  It made sense, therefore, when I needed almost the exact same operations but with four different classes that inherit from the same model to use the same view.

To do this I needed a way to define a “ViewMode” of the user control.  For the default view where it would be the full version of the control the mode would be “Full” and for where I was using it as a child control the mode would be “Compact”.    Given that I think one of the things we should strive for is re-use it seemed like this should be an easy problem.  After some googling around though the general consensus seemed to be that you should just incorporate this into your new view model.  This just seems stupid to me.

Not about incorporating it into the view model.  That much is obvious but that there wasn’t some easy, obvious solution on how to bind a dependency property to a property in the view model.  Fortunately my StackOverflow foo seemed to be working with me and I found the right answer.

You have to manually bind your dependency property to the property on your view model.  It should have been obvious and I’m not sure why I hit on so many wrong answers but here is my solution:

Add the dependency property to MyView that will bind to the view model

public ViewMode ViewMode
{
	get { return (ViewMode)GetValue(ViewModeProperty); }
	set { SetValue(ViewModeProperty, value); }
}

public static readonly DependencyProperty ViewModeProperty =
	DependencyProperty.Register("ViewMode", typeof(ViewMode), typeof(MyView), new PropertyMetadata(ViewMode.Full));

I’ve defined an enum “ViewMode” that has two values, “Full” and “Compact” and I utilize it here.

Then in the ctor of MyView I have

public MyView()
{
	InitializeComponent();

	//http://stackoverflow.com/questions/15132538/twoway-bind-views-dependencyproperty-to-viewmodels-property
	string propertyInViewModel = "ViewMode";
	var bindingViewMode = new Binding(propertyInViewModel) { Mode = BindingMode.TwoWay };
	this.SetBinding(ViewModeProperty, bindingViewMode);
}

This manually sets the binding to a property “ViewMode” that is in my view model. So “ViewMode” exists in both the view and the view model and the manual binding will keep everything in sync.

In my XAML where I use the control as a stand-alone view the XAML looks like

<views:MyView Grid.Row="1" Margin="50" />

and in my XAML where I use the control as a child control the XAML looks like

<views:MyView Grid.Row="0" Grid.Column="0" ViewMode="Compact" />

MMVVVMVMI have also added some converters to help that bind the visibility of controls to the “ViewMode” of the view model. Now I have to point out that what I need to show and/or hide based on the ViewMode was fairly minimalistic. It might make more sense to have different control but in my case it made more sense to use the same control.

This is great and allows us to customize the view based on the ViewMode, but it doesn’t keep MyParentViewModel of the parent control in sync with MyViewModel of the child control when it’s being used as a child control. To do this we need to add another dependency property in MyView and bind it like we did the ViewMode. Then in MyParentView we have to bind that property to the property of MyParentViewModel in XAML.  The kind of crappy part is there is some manual work you have to do to make this work right.  Not only that but the binding works out to be fairly ugly.

The view model of “MyViewModel” looks like:

class MyViewModel
	ViewMode ViewMode
	ObjectGroup ActiveObject

The view model of “MyParentViewModel” looks like:

class MyParentViewModel
	ObjectGroup ActiveObjectOne
	ObjectGroup ActiveObjectTwo
	ObjectGroup ActiveObjectThree
	ObjectGroup ActiveObjectFour

In “MyView” I add the following dependency property:

public ObjectGroup ActiveObject
{
	get { return (ObjectGroup)GetValue(ActiveObjectProperty); }
	set { SetValue(ActiveObject, value); }
}

public static readonly DependencyProperty ActiveObjectProperty =
	DependencyProperty.Register("ActiveObject", typeof(ObjectGroup), typeof(MyView), new FrameworkPropertyMetadata(null, OnActiveObjectChanged));

private static void OnActiveObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
	((MyViewModel)((MyView)d).DataContext).ActiveObject = (ObjectGroup)e.NewValue;
}

which is incredibly ugly. The problem is that when I do the binding on the dependency it directly calls SetValue and ignores my setter. As such I have to set things up with the property changed call-back to make everything tie together correctly.

Unfortunately I still need to add the manual binding to my view

propertyInViewModel = "ActiveObjectGroup";
var bindingActiveObjectGroup = new Binding(propertyInViewModel) { Mode = BindingMode.TwoWay };
this.SetBinding(ActiveObjectGroupProperty, bindingActiveObjectGroup);

Okay, so now everything works correctly right? Nope. The problem is that the binding on MyView sees the local data context, not the binding I want to give the control from MyParentView. As such I need to play with the binding to make sure we’re all on the same page.

The XAML basically ends up looking like

<UserControl x:Class="MyParentView">
	<UserControl.DataContext>
		<viewModels:MyParentViewModel />
	</UserControl.DataContext>
	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition />
			<RowDefinition />
			<RowDefinition />
			<RowDefinition />
    		</Grid.RowDefinitions>
		<views:MyView Grid.Row="0"
				 ViewMode="Compact" 
				 ActiveObject="{Binding DataContext.ActiveObjectOne, Mode=TwoWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
		<views:MyView Grid.Row="1"
				 ViewMode="Compact" 
				 ActiveObject="{Binding DataContext.ActiveObjectTwo, Mode=TwoWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
		<views:MyView Grid.Row="2"
				 ViewMode="Compact" 
				 ActiveObject="{Binding DataContext.ActiveObjectThree, Mode=TwoWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
		<views:MyView Grid.Row="3"
				 ViewMode="Compact" 
				 ActiveObject="{Binding DataContext.ActiveObjectFour, Mode=TwoWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
	</Grid>
</UserControl>

MMVVVMVM2What we’re doing here is changing the default “ActiveObject” in the child control from the one created by its view model to the one created by the parent view model. This way everything is in sync due to the bindings we created in the constructor of “MyView”.

When I bind like I do above the ObjectGroup instances from MyParentViewModel end up being the same as the instance of ObjectGroup in the MyViewModel.

The cool thing about all this is that I can create a new instance of MyParentViewModel as needed and it will set everything up as it should.

And that’s it. Maybe this is one of those answers that is so obvious no one felt the need to write about it. Or maybe everyone’s found the same answer I did. Or maybe this is the wrong approach. After all, it’s not very “MVVM-like”, having to manually create the bindings and then having to manually set the ActiveObject in the dependency property. If you know of a better way to do this let me know.

Thanks,
Brian

Part One: Starting with MVVM
Part Two: The MVVM solution structure and basic framework
Part Three: Base Classes
Part 4: Sampler View, View Model and Model

There is a new version of the solution available.

Finally, before getting in the actual TPL samples there is one last thing to cover. How do we run the samples? Well, as previously discussed the Submit button in SamplerView is bound to the SamplerViewModel.Submit().

public async void Submit()
{
	CurrentState = "Running";
	await Sampler.RunSamples();
	CurrentState = "Completed";
}

Using async/await, the model then runs the samples in the model via Sampler.RunSamples(). The async/await is critical here so the UI isn’t locked while the samples are run.

Here is Sampler.RunSamples()

public async Task RunSamples()
{
	await Task.Run(() =>
	{
		System.Drawing.Bitmap bmp = null;
		foreach (var sample in Samples)
		{
			if(!sample.IsEnabled)
				continue;

			if (sample.ImageRequired)
			{
				UpdateResults("Reseting Image");
				ResetDestinationImage();
				bmp = GetBitmapFromDestinationImage();
			}
			UpdateResults("Starting " + sample.SampleName);
			sample.Run(bmp, UpdateResults);
			UpdateResults("Completed " + sample.SampleName);
			UpdateResults(sample.SampleName + " ran in " + sample.RunTime.ToString() + Environment.NewLine);
		}

		if (bmp != null)
		{
			SetDestinationImageFromBitmap(bmp);
		}
	});
}

private void UpdateResults(string result)
{
	Results += result + Environment.NewLine;
}

The async keyword in the method declaration is what allows the ViewModel to run this method asynchronously. In order to define a method as asynchronous, it must contain an await call. To do this I call Task.Run with an await so the framework knows to spin off a thread and wait for it to return. There’s a bit more than that but I’ll discuss async/await in more detail in the TPL sample for it.

The really interesting thing here is passing the “UpdateResults” method into the run method of the sample model. You’ll recall in the “base classes” post that the abstract sample model takes a bitmap and Action<string>. The SamplerView has a text box that is bound to the Results property of our Sampler model. This way we can get real-time updating from the samples as they run. Since their running in their own thread (via the await Task.Run) it won’t block the UI and the binding takes care of invoking the update to the text so that it happens on the main thread without having to worry about updating the UI on the wrong thread.

And that’s it. It’s pretty simple. Next up I’ll go over the first three samples included in the solution that demonstrate when to and when not to use Parallel.For (and by extension Parallel.ForEach).

Thanks,
Brian

Part One: Starting with MVVM
Part Two: The MVVM solution structure and basic framework
Part Three: Base Classes

I want to go over the main view (SamplerView), view model (SamplerViewModel) and model (Sampler) classes next. I’ve gone over the ItemsControl that populates the TPL samples but I wanted to cover the other MVVM aspects as well as what isn’t MVVM here. There are two other primary MVVM components to this. One is the image chooser, the other is the log that is populated as the samples run. Remember that the DataContext of the SamplerView is a SamplerViewModel. This means that any binding is done on this object.

The Image Chooser:
Near the top of SamplerView is a TextBox that contains the path to the image that is used when a sample needs an image. Next to that is a Button that opens an OpenFileDialog to choose an image.

<Border Grid.Row="0" Grid.ColumnSpan="2" >
	<Grid>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="*" />
			<ColumnDefinition Width="Auto" />
		</Grid.ColumnDefinitions>
		<TextBox Grid.Column="0" Grid.Row="0" VerticalAlignment="Bottom" Text="{Binding Sampler.ImagePath, Mode=TwoWay}" />
		<Button Grid.Column="1" Content="Change Image">
			<i:Interaction.Triggers>
				<i:EventTrigger EventName="Click">
					<ei:CallMethodAction TargetObject="{Binding}" MethodName="ChangeImagePath" />
				</i:EventTrigger>
			</i:Interaction.Triggers>
		</Button>
	</Grid>
</Border>

Like the sample view model, the Sampler model is directly exposed in the SamplerViewModel. As such the binding of the TextBox is to the ImagePath property of the Sampler model. The mode is set to two-way so that if a user wishes they could just paste a path into the TextBox directly. What’s new here is the Interaction.Trigger. This allows you to define a method to call for the EventTrigger, in this case the “Click” event.

Here is the SamplerViewModel.ChangeImagePath():

public void ChangeImagePath()
{
	OpenFileDialog ofd = new OpenFileDialog();
	ofd.CheckFileExists = true;
	ofd.CheckPathExists = true;
	ofd.Multiselect = false;
	if (ofd.ShowDialog() == true)
	{
		Sampler.ImagePath = ofd.FileName;
	}
}

This has the standard OpenFileDialog code but when the user chooses a file, that path is set to the model’s ImagePath. Since the ImagePath is bound to the TextBox in the view, setting the path will update the TextBox to the correct path. Setting this image path has the side-effect that the images within the application get updated.

Sampler.ImagePath:

string imagePath = "";
public string ImagePath
{
	get { return this.imagePath; }
	set
	{
		if (this.imagePath != value)
		{
			this.ValidateProperty("ImagePath", value);
			this.imagePath = value;
			this.RaisePropertyChanged("ImagePath");
			SetImageSources();
		}
	}
}

There are three important aspects to this.

One is the ValidateProperty:

protected override void ValidateProperty(string propertyName, object value)
{
	if (propertyName == "ImagePath")
	{
		var errors = new List();
		string path = value as string;
		if (string.IsNullOrEmpty(path))
		{
			errors.Add("Image path must be set.");
		}
		else if (!File.Exists(path))
		{
			errors.Add("The image indicated does not exist.");
		}

		this.ErrorsContainer.SetErrors(propertyName, errors);
	}
	else
	{
		base.ValidateProperty(propertyName, value);
	}
}

When ValidateProperty is called it verifies that there is an image path and that the file exists. If either of these are not true than an error is added to the error container in the base domain object that allows the application to provide feedback to the user that there is an error.

Two is the RaisePropertyChanged event. This is pretty standard when binding as this notifies any observers that are bound to this object that the property has changed, that way they can change the value as they need to.

Finally is the Sampler.SetImageSources():

private void SetImageSources()
{
	if(!File.Exists(ImagePath))
		return;

	BitmapImage sourceBitmapImage = new BitmapImage();
	sourceBitmapImage.BeginInit();
	sourceBitmapImage.UriSource = new Uri(ImagePath);
	sourceBitmapImage.EndInit();
	SourceImage = sourceBitmapImage;

	ResetDestinationImage();
}

public void ResetDestinationImage()
{
	if(!File.Exists(ImagePath))
		return;

	if (Application.Current.Dispatcher.Thread != Thread.CurrentThread)
	{ 
		Application.Current.Dispatcher.Invoke(() => 
		{
			ResetDestinationImage();
		});
		return;
	}
	BitmapImage destBitmapImage = new BitmapImage();
	destBitmapImage.BeginInit();
	destBitmapImage.UriSource = new Uri(ImagePath);
	destBitmapImage.EndInit();
	DestinationImage = destBitmapImage;
}

This is the side-effect of updating the image path. It causes the two images in the view, which are bound to the SourceImage and DestinationImage, to get updated. Since the ValidateProperty takes care of providing the user with the feedback that a file may not exists we don’t have to do any error handling beyond just making sure the image exists.

The last MVVM component of interest is the Submit button.

<Button  Content="Submit" Height="23" IsEnabled="{Binding CanSubmit}" Margin="5"  HorizontalAlignment="Right" Width="75">
	<i:Interaction.Triggers>
		<i:EventTrigger EventName="Click">
			<ei:CallMethodAction TargetObject="{Binding}" MethodName="Submit"/>
		</i:EventTrigger>
	</i:Interaction.Triggers>
</Button>

Like the ChangeImage button above, this is bound to a method in the SamplerModelView.

SamplerModelView.Submit()

public async void Submit()
{
	CurrentState = "Running";
	await Sampler.RunSamples();
	CurrentState = "Completed";
}

This method is run with async/await so the UI isn’t locked when the samples are run. I’ll discuss async/await in detail later in this series. It just runs the method to run the samples in the Sampler model. In the next post I’ll go more into depth on running samples.

Finally I want to discuss what is not MVVM here. The images are defined in SamplerView as:

<Border MinHeight="100" Grid.Row="1" Grid.Column="0" BorderBrush="Black" BorderThickness="2">
	<Image ClipToBounds="True" Source="{Binding Sampler.SourceImage}">
		<Image.RenderTransform>
			<TransformGroup>
				<ScaleTransform x:Name="imgScaleTransformSource" ScaleX="1" ScaleY="1" />
				<TranslateTransform x:Name="imgTranslateTransformSource"  />
			</TransformGroup>
		</Image.RenderTransform>
	</Image>
</Border>
<Border MinHeight="100" Grid.Row="1" Grid.Column="1" BorderBrush="Black" BorderThickness="2">
	<Image ClipToBounds="True" Source="{Binding Sampler.DestinationImage}">
		<Image.RenderTransform>
			<TransformGroup>
				<ScaleTransform x:Name="imgScaleTransformDest" ScaleX="1" ScaleY="1" />
				<TranslateTransform x:Name="imgTranslateTransformDest"  />
			</TransformGroup>
		</Image.RenderTransform>
	</Image>
</Border>
<StackPanel Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Bottom">
	<RepeatButton x:Name="btnPlus" Width="25" Margin="5" Click="btnPlus_Click">+</RepeatButton>
	<RepeatButton x:Name="btnMinus" Width="25" Margin="5" Click="btnMinus_Click">-</RepeatButton>
	<RepeatButton x:Name="btnUp" Width="25" Margin="5" Click="btnUp_Click">?</RepeatButton>
	<StackPanel Orientation="Horizontal">
		<RepeatButton x:Name="btnLeft" Width="25" Margin="5" Click="btnLeft_Click">?</RepeatButton>
		<RepeatButton x:Name="btnRight" Width="25" Margin="5" Click="btnRight_Click">?</RepeatButton>
	</StackPanel>
	<RepeatButton x:Name="btnDown" Width="25" Margin="5" Click="btnDown_Click">?</RepeatButton>
</StackPanel>

These are bound to the SourceImage and DestinationImage properties of the Sampler model, standard MVVM stuff. What’s not MVVM are the repeat buttons that move/zoom the images around. I opted for this approach, using regular code-behind, because the moving/zooming of the images doesn’t really have anything to do with our models. It doesn’t have anything to do with running samples or any data associated with the samples. Because of this it didn’t make sense to bind the buttons that move the images using an event trigger to methods in the SamplerViewModel. In this case it would have convoluted our ModelViews just for the sake of using MVVM. This is what I meant in the first post where I referred to this as a composite application. MVVM for the sake of MVVM is counter-intuitive and counter-productive. The purpose of our ModelViews and Models is to focus on running TPL samples and giving the results of those samples back to the user.

Up next is running samples, getting the data to the samples and getting the results back from the samples.

Thanks,
Brian

The Task Parallel Library Sampler – Part Three: Base Classes

Part One: Starting with MVVM
Part Two: The MVVM solution structure and basic framework

Let’s take a look at SampleView, SampleViewModel and the base Sample class all of our models extend from so we can get a better understanding of how this works.

In the first set of samples included with the code the only controls we need are a checkbox to identify which samples should be run. As we expand the capabilities of the samples to demonstrate more functionality of the TPL we’ll need to increase that. For now, however, you’ll see that the SampleView.xaml is really as simple as can be.

<UserControl x:Class="TPLSamples.Views.SampleView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             >
    <Grid>
        <CheckBox IsChecked="{Binding Sample.IsEnabled, Mode=TwoWay}" Content="{Binding Sample.SampleName}" ToolTip="{Binding Sample.SampleName}" />
    </Grid>
</UserControl>

We have the boilerplate WPF code with the standard references and <Grid> as well as our checkbox. The code-behind is the boilerplate created code with nothing added. Important here is how the checkbox data gets populated. Remember that in the ItemsControl of the SamplerView, each ViewModel that is added to the observable list the framework will bind to a view which, conversely, has as it’s data context the view model it’s bound to. Additionally, when constructing the ViewModels, they take an instance of a sample. This is how we get our View <-> ViewModel <-> Model. Let’s take a look at our SampleViewModel so we can understand what is happening in it.

public class SampleViewModel : NotificationObject
{
	private readonly Sample sample;
	public Sample Sample
	{
		get { return sample; }
	}

	public SampleViewModel(Sample sample)
	{
		if(sample == null)
			throw new ArgumentNullException("Sample is null");

		this.sample = sample;
	}
}

That’s it. It just exposes our sample directly. Looking back at the xaml for our view, you can see that the content of the checkbox is bound to “Sample.SampleName”. Since the view has the view model as it’s data context that means we are bind the content of the checkbox to the name of the sample model. Note that there are instances when you’re not dealing in clear-cut models that it makes sense to simply incorporate the aspects of a model into the view model. It also makes sense when you want to limit the exposure of your model that you may not expose the model directly but may wrap properties in calls to the model (for example if you need to handle multi-threaded scenarios where you have to lock on properties because there may be only one instance of the model). In this case we are dealing with very obvious models and there is no reason here to limit the exposure of the model so the model is just exposed directly for binding.

One of the critical aspects of this binding is the IsChecked property. You can see that we have a “Mode=TwoWay” parameter on the binding. This means that not only does the value of the IsChecked property get set from the model, but if the value of the IsChecked property changes it will update the model. In terms of the purest implementation of MVVM this is what is problematic with exposing the model directly. The view model is supposed to act as a controller for the interface from the view and to the model. Exposing the model directly means the the view model is no longer controlling the model but instead the view is. With our samples we could have rolled the model into the model view. To simplify what is already a fairly complex set of code for something so simple as well as showing how view models work in MVVM I created view models but exposed the model.

Finally we need to look at the Sample base model that all samples derive from.

public abstract class Sample : DomainObject
{
	public bool IsEnabled { get; set; }
	public string Results { get; set; }
	public TimeSpan RunTime { get; set; }

	public abstract string SampleName { get; }
	public abstract bool ImageRequired { get; }
	public abstract void Run(System.Drawing.Bitmap bmp = null, Action<string> updateLog = null);
}

The vast majority of my samples need a consistent set of data to work on so we can compare times of execution. The easiest way to do this is just take an image on the Run method. This way, if we want to test our samples under different loads we can just use a bigger or smaller image. The Results property is unused and will be removed from future sets of the code. Originally I had envisioned that as the sample needed to display something to the user it would just update the Results property. Obviously this doesn’t work as the user doesn’t get immediate feedback but instead will only get updated when the sample completes its run. I replaced this with an Action that takes a string and in my SamplerViewModel the action updates the results in the Sampler model. This way the user gets continuous feedback from the sample as it updates.

As the samples run, if they use an image they modify that image. The ImageRequired property is important because it is potentially expensive on the front-end to reload the image if a sample doesn’t need it. Especially in cases where a large image is used.

And that’s it for our Sample model. I realize that the initial set-up of MVVM can be complex. Even some of the implementation of the View through ViewModel to Model work-arounds that have be put into place to handle things that are fairly simple when working with code-behind can be downright ugly. The pay-off is that supporting long-term maintenance should be a lot easier. That’s the tough part to get across to a lot of people. You will have a lot more overhead when initally spinning up an MVVM solution but in the end you will find that it is all worth it during maintenance as you fix bugs and add features. If nothing else then because of how cleanly separate your tiers are.

Up next is a more in-depth explanation of our SamplerView, SamplerViewModel and Sampler model.

Thanks,
Brian

WP7, ApplicationBar, ImageUri and the Icon not showing up

I know this may sound stupid but when working with the WP7 ApplicationBar make sure the images you are using have the following properties:

Build Action: Content
Build Action: Content
Copy to Output: Copy always (or ‘Copy if newer’, either should work)

I spent a half an hour trying to figure out why my application bar was showing an “X” instead of the image I was putting in IconUri. When first adding images the properties default to:

Build Action: Resource
Copy to Output: Do not copy

Since the application bar is referencing the image by Uri it can’t seem to find it embedded in the application.

My xaml looks like:

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton
            IconUri="/Images/appbar.feature.settings.rest.png"
            Text="Settings"/>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Had some trouble with using a converter when databinding on a GridView yesterday so I thought I’d do a quick write up.

Imagine for one instance you have the following class:

public class EntityDataItem
{
    public string Name { get; set; }
    public string Type { get; set; }
    public DateTime CreatedTS { get; set; }
}

Now imagine you have the following xaml:

<ListView Name="EntitiesGrid">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Type" DisplayMemberBinding="{Binding Type}"/>
<GridViewColumn Header="CreatedTS" DisplayMemberBinding="{Binding CreatedTS}"/>
</GridView>
</ListView.View>
</ListView>

To bind to the grid all you would have to do on the window load event is:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    List<EntityDataItem> items = new List<EntityDataItem>();
    items.Add(new EntityDataItem { Name = "A", Type = "Person", CreatedTS = DateTime.Now });
    items.Add(new EntityDataItem { Name = "B", Type = "Equipment", CreatedTS = DateTime.Now });
    items.Add(new EntityDataItem { Name = "C", Type = "Location", CreatedTS = DateTime.Now });
    items.Add(new EntityDataItem { Name = "D", Type = "Unit", CreatedTS = DateTime.Now });
    EntitiesGrid.ItemsSource = items;
}

Well now, that’s all fine and good. But now imagine you were, oh, I don’t know, working on some military project that wanted you do use a specific format for the date. The way it is now when the binding happens it will use the default ToString() which isn’t acceptable in this case.

So we need to use a converter. Converters let you go from any object to any object on databinding. Let’s start by creating the converter:

[ValueConversion(typeof(DateTime), typeof(String))]
public class DateToMilitaryConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return "";
        DateTime date = (DateTime)value;
        return date.ToString("dd MMM yyyy HHmm", DateTimeFormatInfo.InvariantInfo);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string strValue = value.ToString();
        DateTime resultDateTime;
        if (DateTime.TryParse(strValue, out resultDateTime))
        {
            return resultDateTime;
        }
        return value;
    }
}

then in the resources for your xaml define:

<local:DateToMilitaryConverter x:Key="dateConverter"/>

assuming the local namespace is defined as your local assembly or whatever namespace you used for the converter.

Here’s where things get a bit tricky. You can’t put a converter directly on a GridViewColumn. Where you can put it is on the Binding. To do that make your xaml look like:

<ListView Name="EntitiesGrid">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
            <GridViewColumn Header="Type" DisplayMemberBinding="{Binding Type}"/>
            <GridViewColumn Header="CreatedTS">
                <GridViewColumn.DisplayMemberBinding>
                    <Binding Path="CreatedTS" Converter="{StaticResource dateConverter}"/>
                </GridViewColumn.DisplayMemberBinding>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

You can see here we are tapping into the DisplayMemberBinding propery of the GridViewColumn and assigning a Binding to it. On the Binding we can use a converter. As I mentioned though you can go from any object to any other object. Remember, however, regardless of what you go to, the ToString() will be called on it. A couple of points of interest on the converter. The source of the data in the real binding, not my contrived example, is a DateTime? which means the value could be null. Thus I have accounted for that in the converter. Additionally I allow for a class cast exception rather then doing:

DateTime date = value as DateTime;
if (value == null)
    return "";

in case someone else were to use my class where it doesn’t belong. Basically the converter handles DateTime? but nothing else, as it should be.

Well, I meant this one to be short and sweet and it was.

Later,
Brian

UPDATE:
It has been brought to my attention that you can do converters inline with the DisplayMemberBinding.

<GridViewColumn 
    Header="CreatedTS" 
    DisplayMemberBinding="{Binding Path=CreatedTS, Converter={StaticResource dateConverter}}"
/>

Live and learn 🙂
Brian

WPF – ContentProperty, it’s that simple

So there I am, creating a custom control called “RequiredLabel” that
interestingly enough is a label that has a cool icon in it to show that
whatever it is being used for is required. The control has two
properties, Text that is the text of the label and Style that is the
style of the label. Both are registered as dependency properties so
that they can be set in the xaml. I suppose it would have been fine to
simply leave good enough as good enough but I wanted it so that in the
xaml you can put the text for the label between the start and end tag
for required label. It is simply expected behavior the the content of
your control can be put in that way.

After much soul searching (i.e. Googling) I still couldn’t find the
answer. How do I make one of my dependency properties the content that
is between the tags? Well, thankfully I had an epiphany and remembered
that somewhere deep in one of my WPF books the answer was held. It is
as simple as putting the attribute above the class declaration with the
dependency property name.

[ContentProperty("Text")]
public partial class RequiredLabel : UserControl
{
    //see full code below
}

This makes it so that when I use my custom control it will look like:

<customControls:RequiredLabel x:Name="lblType" Style="{StaticResource LabelGradient}">
    Defendant's Name:
</customControls:RequiredLabel>

It also makes it so that if I decide to extend the content to support
user controls instead of just text really easy since I can switch out
the TextBlock that makes up the user control to a panel.

Also if you want to get a glimmer of using dependency properties see
attached code.

RequiredLabel.zip

Brian

WPF and Silverlight

 Check out the link below.  It is a bunch of tutorials on everything you could want to know about Silverlight plus a whole bunch of cool WPF stuff.

http://channel9.msdn.com/posts/Dan/Mike-Taulty-44-Silverlight-20-Screencasts/