WPF Scheduler

Several years ago I found a Silverlight sample application on one of the sites of Microsoft, that application was called something like Patient Journey Demonstrator and didn’t serve any real purpose but to show what can be created by using Silverlight.
I remember that I decompiled the source code and tried to build something similar, but eventually I didn’t used those controls in any of my applications. Anyway, here is one of the interesting controls:

This controls looks good by the way: you can expand and collapse items representing hours, you can drag and drop appointments from one time to another, also there are some unavailable gray cells which it is not allowed to drag items to. The only one inconvenience is that all items should take the same amount of time and can’t cross the border of an hour.

This code is 2 years old and isn’t implemented well, but at least it works. Maybe some day I’ll rewrite it and make it more useful, as soon as I have a time.
Source code: WpfSchedulerSample.zip

Advertisements

WPF Drag and Drop implementation

Some time ago I searched how to implement the drag and drop functionality in my WPF application. But all examples that I found either contained much of unmaintenable code or worked only for a specific task and it was difficult to add that code into my existing application.

But recently in the Microsoft training course book (10262A Developing Windows Applications) I’ve found quite good example how to implement this functionality by using expression blend behaviors. By the way, the actual implementation were taken from this post.

Now it is very easy to use the drag and drop out of the box, just add the following 3 lines to a source element:

<i:Interaction.Behaviors>
    <dd:DragDropBehavior IsDragSource="True"/>
</i:Interaction.Behaviors>

And the following 3 lines to a target element:

<i:Interaction.Behaviors>
    <dd:DragDropBehavior IsDropTarget="True" Dropped="DragDropBehavior_Dropped"/>
</i:Interaction.Behaviors>

The i prefix is defined as xmlns:i=”clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity”, you can use this library after you install Expression Blend SDK or you can find it in the archive attached to this post.

Which element is the source and which one is the target – you should determine it logically. For example, if you want to move items from one ListBox to another one, the drag source will be the item template of the first ListBox (because it is the item which is dragged), the drop target will be the second ListBox itself (although it is still possible to set the drop target to the item template, it doesn’t work well for the empty listbox).
The code will look something like this:

<ListBox ItemsSource="{Binding Items1}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Background="Transparent">
                <i:Interaction.Behaviors>
                    <dd:DragDropBehavior IsDragSource="True"/>
                </i:Interaction.Behaviors>
                        
                <Run Text="{Binding Title}" /><Run Text=": "/><Run Text="{Binding Value}" />
            </TextBlock>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
        
<ListBox ItemsSource="{Binding Items2}" Grid.Column="1" DisplayMemberPath="Title">
    <i:Interaction.Behaviors>
        <dd:DragDropBehavior IsDropTarget="True" Dropped="DragDropBehavior_Dropped"/>
    </i:Interaction.Behaviors>
</ListBox>

And here is how it looks after you run the application:
wpf drag and drop sample

The source code of the behavior and sample application you can download here: WpfDragDrop.zip
If you want some extra features – you can freely write your suggestions in comments, I’ll think what I can do.

The necessity of a ViewModel class for each Model class

It is well known that you need a ViewModel if you want to add property change notification or validation to a Model. But what if the Model and ViewModel classes don’t differ at all? Should you create a ViewModel class if it has the same set of properties that the Model class has? The answer is yes, absolutely. The brief reasons are separation of layers and loose coupling. But I know that these abstract terms don’t sound very convincing so I’ll describe my point of view more particularly in this post.

As an example I’ll use this data source class (which can be either a web service, or a database, or a file, whatever) and this model:

public interface IModelSource
{
    SettingsModel GetSettings();
}

public class SettingsModel
{
    public string DefaultPage { get; set; }

    public string DownloadsFolder { get; set; }

    public bool AutoStart { get; set; }
}

So we should choose which approach to use.
Just to bind the model as it is:

SettingsModel model = source.GetSettings();
this.DataContext = model;

Or to use the extra ViewModel layer and convert the model before binding:

SettingsModel model = source.GetSettings();
SettingsViewModel viewModel = ConvertModelToViewModel(model);
this.DataContext = viewModel;

Let’s examine some cases and look at the differences between the approaches above.

 

1. Remove a property from the model class.
It happens quite often during development, this type of changes can be performed on the service side or in the database. So if to remove the AutoStart property, what will happens then?

The model-only approach
You will not be aware of the error and will not notice it until you run your application, navigate to the corresponding view and look at the Output window. There among messy messages you will see the notification about the binding error:
Runtime binding error
Also you should run your application in the Debug mode. If you start it by using the Ctrl+F5 combination, you will never find the error.

The viewmodel approach
You will be notified about the error almost immediately before you run the application. And you know: the earlier the bug is found – the easier to fix it.

 

2. Add a property of a complicated data type to the model class.
For example, this property of the Enum type:

NumberFormatCulture NumberFormat { get; set; }

The model-only approach
It isn’t clear how to bind this enum to the ComboBox control (I think, you will not display such programming language related values as “EnglishUS” to end users, won’t you?), so you’ll search it on Google or StackOverflow and eventually you’ll choose either a hacky solution (which will work only for the particular case) or you’ll agree to use the ViewModel (and admit wasting the time).

The viewmodel approach
Just add a few lines to the mapping configuration which can be easily bound to the ComboBox:

//Mapper.CreateMap ... 
.ForMember(vm => vm.NumberFormats, option => option.UseValue(
    EnumExtensions.GetValues<NumberFormatCulture>().Select(TranslateEnum)))
.ForMember(vm => vm.SelectedNumberFormat, option => option.MapFrom(
    m => TranslateEnum(m.NumberFormat)))

 

3. Change the structure of the model class.
For example, if to change some property of the string type to the property of another model type:

public PageModel DefaultPage { get; set; }

public class PageModel
{
    public string Url { get; set; }
}

The model-only approach
Again, you will not notice the error until you run the application and look at the Ouput Window (see p.1). Then you should run over all the xaml-markup in the view and correct bindings. And of course launch the application once again to assure that everything is fine after the changes.

The viewmodel approach
Just fix one line of the code in the mapping configuration:

//Mapper.CreateMap ... 
.ForMember(vm => vm.DefaultPage, option => option.MapFrom(m => m.DefaultPage.Url))

I must say that in this case the mapper doesn’t perform compile-time checking, but you can configure it so that it throws an exception if you try to map from the object type to the string type. And exceptions are any easier to notice and understand than debug messages in the Output window.

 

4. Project structure and maintenability
It isn’t a big advantage of the viewmodel approach in comparison with the above described points, but anyway, it is much better to have a good project structure when each view has a corresponding view model with the same class name prefix. You will not search which model class is bound to, for example, the SettingsView class (which model class: UserSettingsModel, ServiceSettingsModel? I don’t remember so I’ll take some time to find it out). You’ll just open the folder with view models and immediately see the corresponding SettingsViewModel class.

 

The most popular exuse not to create the extra layer is because it allegedly takes much time. But if to calculate the exact amount, the statement will be far from the truth.
– Add the AutoMapper library by using the NuGet package manager – 20 second (this task is performed only once)
– Create a new ViewModel class and just copypaste all of the properties of the model – 30 seconds
– Configure the mapping by using code-snippets – 5 seconds per property.

So it’ll take something about 1-2 minutes to create a ViewModel and I can’t say that it is a “huge amount of time”. And this amount is nothing in comparison with the time wasted on the above described points if to use the wrong approach. Don’t afraid to spend few minutes now, it will save many hours in the future.

WPF and Silverlight design patterns

In this post I’ll describe the design patterns which are used in large and complex applications in order to simplify their development and maintenance.

Model View ViewModel
Separates Model and View by introducing the intermediate layer which is called ViewModel. It is a some kind of a “super converter” which adds additional properties and behavior to the model. Also commonly used as a replacement of code-behind.
The most common features of ViewModel:

  • Property changes notification with the INotifyPropertyChanged interface
  • Validation with the IDataErrorInfo or INotifyDateErrorInfo interfaces
  • Event handling of View events
  • Invocation of WCF services
  • Converting of model properties from one data type to another

Example of Model and ViewModel:

public class UserModel
{
	public string Name { get; set; }
}

public class UserViewModel : IDataErrorInfo, INotifyPropertyChanged
{
	private string name;

	public string Name
	{
		get { return name; }
		set
		{
			name = value;
			RaisePropertyChanged(&quot;Name&quot;);
		}
	}

	public ICommand ChangeNameCommand { get; set; }

	public string Error
	{
		get { throw new NotImplementedException(); }
	}

	public string this[string columnName]
	{
		get { return this._validator.GetErrors(columnName).FirstOrDefault(); }
	}

	public event PropertyChangedEventHandler PropertyChanged;

	private void RaisePropertyChanged(string propertyName)
	{
		if (this.PropertyChanged != null)
			this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
	}
}

Links:
Wikipedia. Model View ViewModel
Developer’s Guide to Microsoft Prism. Implementing the MVVM Pattern
Never In Doubt: MVVM Backlash

 

Dependency Injection
The purpose of this pattern is to get rid of using of external classes and to use interfaces instead.
This pattern adds the following benefits:

  • Allows to write unit tests because interfaces can be replaced by “fake” classes
  • Allows to change one interface implementation by another without affecting or changing existing objects

For example, this class:

public class MyViewModel
{
	public MyViewModel()
	{
		this.SomeProperty = Resources.String1; // the static class call
	}

	public void Refresh()
	{
		var model = new MyWcfServiceClient().GetModelById(this.Id); // the service creation

        // initialize the corresponding properties of the view model
	}
}

should be rewritten so:

public class MyViewModel
{
	public MyViewModel(IResourceManager resourceManager, IServiceClient serviceClient)
	{
		this._resourceManager = resourceManager;
		this._serviceClient =  serviceClient;

		this.SomeProperty = this._resourceManager.String1;
	}

	public void Refresh()
	{
		var model = this._serviceClient.GetModelById(this.Id);

        // initialize the corresponding properties of the view model
	}
}

Links:
Wikipedia. Dependency injection
MSDN Magazine. Design Patterns: Dependency Injection

 

Modular Application
This concept is based on the logical division of application components and if you use several projects with different functionality, you already use a some kind of modules. For example, if your solution has projects like Application.Mail, Application.Calendar, Application.Tasks – it has 3 modules as well.

Besides the above mentioned logical division, the Prism framework adds the following features:

  • Allows to add modules after the application is released (some kind of plug-ins)
  • Allows to defer module loading and load some of them on demand

Links:
Developer’s Guide to Microsoft Prism. Modular Application Development

 

Event Aggregator
This pattern is known as Messenger in the MVVM Light Toolkit. Implements the “publish-subscribe” model. For example, if one view model should call a method of another view model, it can be done by using two ways:
1. Bad practice: The first view model gets the second view model as the constructor parameter and then calls the necessary methods directly by using the code like this._otherModel.OnUserUpdated(this).
2. The preferred approach: The second view model publishes an event, the first one subscribes to it and handles appropriately.

Links:
Martin Fowler. Event Aggregator
Developer’s Guide to Microsoft Prism. Communicating Between Loosely Coupled Components

 

Command
Allows to get rid of the code-behind and handle button clicks inside a view model. Also it is useful when the same action is invoked from the application menu, context menu, toolbar and buttons, so you don’t need to write separate event handlers and you can use just a single command everywhere.
Besides the method invocation, commands in WPF affects the IsEnabled property of buttons and menu items as well: if a command can’t be executed, all the invoke buttons will be disabled.

Links:
Wikipedia. Command pattern
MSDN. Commanding QuickStart

WPF and Silverlight Validation with IDataErrorInfo and INotifyDataErrorInfo

In this post I’ll describe how to use the IDataErrorInfo and INotifyDataErrorInfo interfaces to perform validation in WPF and Silverlight.
There are several kinds of validations and the preferrable approach in the MVVM pattern is using the IDataErrorInfo or INotifyDataErrorInfo interface.
But this approach doesn’t behave as expected: it performs validation immediately after the launch of the view, whereas it would be better if the validation started only after a user has changed values. Also I would like to reuse some commonly used rules.

So I’ve created the helper class which performs all the necessary work. This class is similar to the class from the FluentValidation library, but it has less code and more flexible to me.
Here is the example of such validation:

    public class PersonViewModel : IDataErrorInfo, INotifyPropertyChanged
    {
        private ModelValidator _validator = new ModelValidator();

        public PersonViewModel()
        {
            //Six validation rules
            this._validator.AddValidationFor(() => this.FirstName).NotEmpty()
				.Show("Enter a First Name");
            this._validator.AddValidationFor(() => this.LastName).NotEmpty()
				.Show("Enter a Last Name");

            this._validator.AddValidationFor(() => this.Age).NotEmpty()
				.Show("Enter an age");
            this._validator.AddValidationFor(() => this.Age).Between(0,99)
				.Show("The age must be between 0 and 99");

            this._validator.AddValidationFor(() => this.Email)
				.When(() => this.IsSubscribe).NotEmpty()
				.Show("Enter an email address");
            this._validator.AddValidationFor(() => this.Email)
				.When(() => this.IsSubscribe).EmailAddress()
				.Show("Enter a valid email address");
            //Validates on changes of properties
            this.PropertyChanged += (s, e) => this._validator.ValidateProperty(e.PropertyName);
        }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get { return this._validator.GetErrors(columnName).FirstOrDefault(); }
        }

There is only 4 steps:
1. Create a variable of the ModelValidator type
2. Add necessary validation rules
3. Update validation every time when a property has been changed
4. Return cached errors inside the indexer property.

Actually it is not so obligatory to implement the 3rd step and update validation inside the PropertyChanged event handler. You can remove that line and call the ValidateAll method after a user clicks the Save button. But validation on changes is more preferrable solution.

I’ve added some predefined validation rules, if they aren’t enough, you can use the Must method with your own functions.
1. NotNull – the property value shouldn’t be null.
2. NotEmpty – if the property is of the string type, checks whether the string is null or consists of whitespaces. If of any other type – this rule is the same as NotNull.
3. Between – checks whether the property value is within a specific range. Works with strings as well as with numbers, so it’s not necessary to parse strings in view models.
4. EmailAddress – if the string value isn’t null, it should be a valid e-mail address.
5. Must – any user-defined validation function. For example: this._validator.AddValidationFor(() => this.LastName).Must(() => this.LastName.Length < 10).Show("Last name should not exceed 10 characters");

To implement this validation, you should copy 3 files with 2 classes to your project.
Here is the completed project where you can take all the necessary classes: WpfValidation.zip

Update
I’ve also added the validation for Silverlight both with IDataErrorInfo and INotifyDataErrorInfo:
The image illustrating validation errors in Silverlight
The source code you can download here: SilverlightValidation.zip

WPF and Silverlight TabControl with scrolling and with the New Tab button.

Everyone who has ever used the TabControl class knows that it doesn’t look as expected if it has large number of tabs. If the number of tabs exceeds the size of the visible area, they are distributed among several lines. But many people prefer to place tabs in one line and scroll headers like it is implemented in Firefox.

The attempt to solve this issue was made here by one guy, but his solution is far from ideal. It doesn’t work with the ObservableCollection class, has uncommon design and doesn’t change buttons correctly. So after some work I have created my own TabControl which, I hope, works properly.


The left and right buttons change their visibility and accessibility automatically when the number of tabs or size of the control is changed. The buttons are visible if the number of tabs is large, but one of them can be disabled if it is not possible to move further.

Also there is the button with the plus sign (+). It doesn’t add new tab automatically and must be coded manually. It makes sense because I use MVVM, and it is not possible to create a new tab because each tab is related with a view model. You have to use the AddItemCommand property and bind a function with the command. I use the RelayCommand from the MVVM Light Toolkit. Also there is another implementation of the command pattern which is called DelegateCommand and it is the part of the Prism. Here is the code example:
Inside the constructor of the view model:

this.AddCommand = new RelayCommand(AddNewItemFunction);

A function of the view model:

private void AddNewItemFunction()
{
    var newItem = new TabItemViewModel();
    this.Items.Add(newItem);
    this.SelectedItem = newItem;
}

The view:

<tab:ExtendedTabControl ItemsSource="{Binding Items}"
                        SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                        AddItemCommand="{Binding AddCommand}"

Also I’ve implemented the WPF counterpart of this control:

Silverlight source code: ExtendedTabControl.zip
WPF source code: WpfScrollableTabControl.zip

Silverlight and WPF ComboBox with TreeView inside

The TreeView is useful control, but it has one shortcoming: it occupies too much space in the application. That’s why I’ve decided to create the custom control which looks like a ComboBox but displays the TreeView instead of the list.

Here is the final result:

Although this control looks quite simple, the actual implementation isn’t clear and takes long time.
Here is the sequence of steps:

1) Custom TreeView and TreeViewItem. They provide the following functionality:

  • Allow to expand and  select an item from a view model (It isn’t possible to select an item of the TreeView using other ways)
  • The event which is fired when a user clicks a TreeViewItem (so it will be possible to close the ComboBox)

2) Interface for an item of the ItemsSource collection

public interface ITreeViewItemModel
{
	string SelectedValuePath { get; }
	string DisplayValuePath { get; }

	bool IsExpanded { get; set; }
	bool IsSelected { get; set; }

	IEnumerable<ITreeViewItemModel> GetHierarchy();
	IEnumerable<ITreeViewItemModel> GetChildren();
}

Members of this interface:

  • IsExpanded – allows to expand the TreeViewItem from the bound view model. Must be implemented as the INotifyPropertyChanged property.
  • IsSelected – allows to select the TreeViewItem from the bound view model. Must be implemented as the INotifyPropertyChanged property.
  • SelectedValuePath – the unique string (unique item id) that will be used to select and expand the treeview control
  • DisplayValuePath – the content that will be displayed at the header when the combobox is closed
  • GetHierarchy – returns the item and its parents
  • GetChildren – returns child items of the current item

3. Create the Combobox

It is the most difficult part of the implementation. I was forced to create many methods to provide the connection between Combobox and TreeView. But although there is many private methods, there is only two public properties:

  • SelectedItem – now it is possible to get or set this item and it will be selected in the treeview.
  • SelectedHierarchy – it wasn’t necessary to create this property, but it wasn’t difficult so I’ve decided to implement it. Use list of strings instead of the actual item.

4. Add it to a view and bind with a view model:

<UserControl.Resources>
    <Windows:HierarchicalDataTemplate x:Key="treeViewDataTemplate" 
                   ItemsSource="{Binding Children}">
        <TextBlock Text="{Binding Title}" />
    </Windows:HierarchicalDataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
        <local:ComboBoxTreeView ItemsSource="{Binding Items}" 
             SelectedItem="{Binding SelectedItem}" 
             ItemTemplate="{StaticResource treeViewDataTemplate}"
             HorizontalAlignment="Center" VerticalAlignment="Top" />
</Grid>

The ItemTemplate property is obligatory property and must be of the HierarchicalDataTemplate type.

Silverlight version: ComboBoxTreeView.zip
WPF version: WpfComboboxTreeview.zip
The updated source code which supports the ‘SelectionChanged’ event of the combobox: ComboBoxTreeViewEventsSupport.zip