Posted by: Zeeshan Amjad | April 22, 2014

Fibonacci Word


I came across an interesting concept Fibonacci word. It is formed by repeated concatenation of symbols, usually two alphabets, using the Fibonacci numbers way.

For sample lets start with the symbol “a” and “ab”.

Here are the first few words

F0 = a

F1 = ab

F2 = aba

F3 = abaab

F4 = abaababa

F5 = abaababaabaab

Let’s do this coding but first make a integer version of the program.

Code Snippet
static int[] Fibonacci(int no)
{
    var fib = new int[no];

    fib[0] = 0;
    fib[1] = 1;

    for (var i = 2; i < no; i++)
    {
        fib[i] = fib[i - 1] + fib[i - 2];
    }

    return fib;
}

 

Now let’s make the string version of the program.

Code Snippet
static string[] FibonacciString(int no)
{
    var fib = new string[no];

    fib[0] = "a";
    fib[1] = "b";

    for (var i = 2; i < no; i++)
    {
        fib[i] = fib[i - 1] + fib[i - 2];
    }

    return fib;
}

 

The integer version and the string version of the programs are very similar to each other. Let’s try to make a generic  function. This is our first attempt.

Code Snippet
static T[] Fibonacci<T>(int no)
{
    var fib = new T[no];

    fib[0] = 0;
    fib[1] = 1;

    for (var i = 2; i < no; i++)
    {
        fib[i] = fib[i - 1] + fib[i - 2];
    }

    return fib;
}

 

This program has two problem. First the initialization of the first and second elements of Fibonacci word. It can be easily solved by passing the initial values as a parameter. Here is a modified version of the program.

Code Snippet
static T[] Fibonacci<T>(int no, T first, T second)
{
    var fib = new T[no];

    fib[0] = first;
    fib[1] = second;

    for (var i = 2; i < no; i++)
    {
        fib[i] = fib[i - 1] + fib[i - 2];
    }

    return fib;
}

 

But there is still another problem. There is still a compilation error.

Error    1    Operator ‘+’ cannot be applied to operands of type ‘T’ and ‘T’   

We can solve this problem with the dynamic keyword of C#. We can convert the last and second last item of the Fibonacci word using dynamic keyword before applying the concatenation words.

Here is a modified version of Fibonacci word.

Code Snippet
static T[] FibonacciGeneric<T>(int no, T first, T second)
{
    if (no < 2)
        return null;

    var fib = new T[no];

    fib[0] = first;
    fib[1] = second;

    for (var i = 2; i < no; i++)
    {
        dynamic last = fib[i - 1];
        dynamic secondlast = fib[i - 2];

        fib[i] = last + secondlast;
    }

    return fib;
}

Posted by: Zeeshan Amjad | March 12, 2014

Mutual recursion with C++ lambda function


We already saw an example of doing recursion with C++ lambda function here. Here we saw that how can we use std::function to store the function pointer to call lambda function recursively, because lambda function doesn’t have any name.

Things are bit interesting in case of mutual recursion. In case of mutual recursion there are more than one functions calls each other. It means that now we need not one but two function pointers stored in C++ wrapper.

Let’s start with our first attempt to create a simple even and odd function.

Here is a simple equation of mutual recursion.

Even_Function_Equation

In first step let’s create two wrappers for function.

Code Snippet
std::function<bool(int)> isEven;
std::function<bool(int)> isOdd;

 

Now lets create a function for this.

Code Snippet
isEven = [&isEven](int n) -> bool
{
    if (0 == n)
        return true;

    else
        return isOdd(n – 1);
};

isOdd = [&isOdd](int n) -> bool
{
    if (0 == n)
        return false;

    else
        return isEven(n – 1);
};

 

And we got the following error message.

error C3493: ‘isOdd’ cannot be implicitly captured because no default capture mode has been specified

error C3493: ‘isEven’ cannot be implicitly captured because no default capture mode has been specified

Now we have to specify the other lambda function in the lambda capture. Here is a modified version of the lambda function which implement mutual recursion.

Code Snippet
std::function<bool(int)> isEven;
std::function<bool(int)> isOdd;

isEven = [&isEven, &isOdd](int n) -> bool
{
    if (0 == n)
        return true;

    else
        return isOdd(n – 1);
};

isOdd = [&isOdd, &isEven](int n) -> bool
{
    if (0 == n)
        return false;

    else
        return isEven(n – 1);
};

 

Let’s see another example of mutual recursion. Here is a mutual recursive function for baby and adult rabbit pair in fibonacci sequence.

Mutual_Recursion

Here is a C++ lambda function of this.

Code Snippet
std::function<int(int no)> babyPair;
std::function<int(int no)> adultPair;

babyPair = [&babyPair, &adultPair](int no) -> int
{
    if (no == 1)
        return 1;
    else
        return adultPair(no – 1);
};

adultPair = [&adultPair, &babyPair](int no) -> int
{
    if (no == 1)
        return 0;
    else
        return adultPair(no – 1) + babyPair(no – 1);
};

Posted by: Zeeshan Amjad | March 1, 2014

Radio button in MVVM


Using the check box or any other control with MVVM is comparatively easy, because we usually bind one control with one property. But radio button is an interesting control, here we bind more than one control with one property.

When we are creating a radio button, we can defined different groups and all the radio button in one group work independent of other. And we usually bind one property to all radio button control in one group.

At our first step we bind all the radio button controls in one group to one variable, but the problem is how do we know which radio button is clicked. Let’s say we have a radio button group of direction. We have an enumerator for it.

Code Snippet
public enum Direction
{
    North,
    Easth,
    West,
    South
}

 

Which radio button is clicked we can achieve this in different ways. We can use the Converter and Converter Parameter to identify the radio button. We can even make that converter as a markup extension, so we even don’t have to create an object of it in XAML.

Here is a code of our simple enum to boolean convertor markup extension.

Code Snippet
[ValueConversion(typeof(bool), typeof(Enum))]
public class EnumToBoolExtension : MarkupExtension, IValueConverter
{
    #region IValueConverter
    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return parameter.Equals(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((bool) value) == true ? parameter : DependencyProperty.UnsetValue;
    }

    #endregion

    #region MarkupExtension

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    #endregion
}

 

And we can use this markup extension with radio button in this way.

Code Snippet
<RadioButton Grid.Row="0" GroupName="directionText" Margin="5" VerticalAlignment="Center" Content="North"
             IsChecked="{Binding Direction, Converter={local:EnumToBool}, ConverterParameter={x:Static local:Direction.North}}"/>
<RadioButton Grid.Row="1" GroupName="directionText" Margin="5" VerticalAlignment="Center" Content="East"
             IsChecked="{Binding Direction, Converter={local:EnumToBool}, ConverterParameter={x:Static local:Direction.Easth}}"/>
<RadioButton Grid.Row="2" GroupName="directionText" Margin="5" VerticalAlignment="Center" Content="West"
             IsChecked="{Binding Direction, Converter={local:EnumToBool}, ConverterParameter={x:Static local:Direction.West}}"/>
<RadioButton Grid.Row="3" GroupName="directionText" Margin="5" VerticalAlignment="Center" Content="South"
             IsChecked="{Binding Direction, Converter={local:EnumToBool}, ConverterParameter={x:Static local:Direction.South}}"/>

 

Rest of the things are very easy. We can create a enum Direction type property in our view Model to use radio button in MVVM.

Here is a complete C# code of the project.

Code Snippet
namespace WpfRadioButton
{
    using System;
    using System.ComponentModel;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Markup;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ViewModel vm = new ViewModel();
        public MainWindow()
        {
            InitializeComponent();

            DataContext = vm;
        }
    }

    [ValueConversion(typeof(bool), typeof(Enum))]
    public class EnumToBoolExtension : MarkupExtension, IValueConverter
    {
        #region IValueConverter
        
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return parameter.Equals(value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ((bool) value) == true ? parameter : DependencyProperty.UnsetValue;
        }

        #endregion

        #region MarkupExtension

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }

        #endregion
    }

    public enum Direction
    {
           North,
        Easth,
        West,
        South
    }

    public class ViewModel : INotifyPropertyChanged
    {
        public Direction direction;

        public Direction Direction
        {
            get
            {
                return this.direction;
            }

            set
            {
                this.direction = value;
                this.RaisePropertyChanged("Direction");
            }
        }

        #region NotifyPropertyChanged Methods

        public void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

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

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}

 

And here is complete XAML code of the project

Code Snippet
<Window x:Class="WpfRadioButton.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:local="clr-namespace:WpfRadioButton"
        Title="RadioButton" Height="200" Width="300">
    <Grid DataContext="{Binding}">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <RadioButton Grid.Row="0" GroupName="directionText" Margin="5" VerticalAlignment="Center" Content="North"
                     IsChecked="{Binding Direction, Converter={local:EnumToBool}, ConverterParameter={x:Static local:Direction.North}}"/>
        <RadioButton Grid.Row="1" GroupName="directionText" Margin="5" VerticalAlignment="Center" Content="East"
                     IsChecked="{Binding Direction, Converter={local:EnumToBool}, ConverterParameter={x:Static local:Direction.Easth}}"/>
        <RadioButton Grid.Row="2" GroupName="directionText" Margin="5" VerticalAlignment="Center" Content="West"
                     IsChecked="{Binding Direction, Converter={local:EnumToBool}, ConverterParameter={x:Static local:Direction.West}}"/>
        <RadioButton Grid.Row="3" GroupName="directionText" Margin="5" VerticalAlignment="Center" Content="South"
                     IsChecked="{Binding Direction, Converter={local:EnumToBool}, ConverterParameter={x:Static local:Direction.South}}"/>
        <TextBlock Grid.Row="4" Margin="5" VerticalAlignment="Center" Text="{Binding Direction}"/>
    </Grid>
</Window>

 

This is an output of the program.

WpfRadioButtonMVVM

Posted by: Zeeshan Amjad | January 26, 2014

FileDialogViewModel revisited


We saw the first very simple implementation of FileDialogViewModel here. There is still a room of improvement in this class. The first obvious improvement is to get the name of open file. In previous version, we don’t have any indication on the screen that which file is currently open. Now let’s add this functionality.

The first step is to add the property in our FileService helper class because that class actually uses the OpenFileDialog and SaveFileDialog classes. Here is an updated version of our class.

Code Snippet
public sealed class FileService
{
    public string FileName
    {
        get;
        set;
    }

    public Stream OpenFile(string defaultExtension, string filter)
    {
        OpenFileDialog fd = new OpenFileDialog();
        fd.DefaultExt = defaultExtension;
        fd.Filter = filter;
        fd.Multiselect = false;

        bool? result = fd.ShowDialog();
        this.FileName = fd.FileName;

        return result.Value ? fd.OpenFile() : null;
    }

    public Stream SaveFile(string defaultExtension, string filter)
    {
        SaveFileDialog fd = new SaveFileDialog();
        fd.DefaultExt = defaultExtension;
        fd.Filter = filter;               

        bool? result = fd.ShowDialog();
        this.FileName = fd.FileName;

        return result.Value ? fd.OpenFile() : null;
    }        
}

 

Now we have to add this property in our FileDialogViewModel too. Here is our updated version of FileDialogViewModel class.

Code Snippet
public class FileDialogViewModel : ViewModelBase
{
    private string extension;
    private string filter;
    private string fileName;

    public FileDialogViewModel()
    {
        this.SaveCommand = new RelayCommand(this.SaveFile);
        this.OpenCommand = new RelayCommand(this.OpenFile);            
    }

    #region Properties

    public Stream Stream
    {
        get;
        set;
    }

    public string Extension
    {
        get
        {
            return this.extension;
        }

        set
        {
            this.extension = value;
            this.RaisePropertyChanged("Extension");
        }
    }

    public string Filter
    {
        get
        {
            return this.filter;
        }

        set
        {
            this.filter = value;
            this.RaisePropertyChanged("Filter");
        }
    }

    public string FileName
    {
        get
        {
            return this.fileName;
        }

        set
        {
            this.fileName = value;
            this.RaisePropertyChanged("FileName");
        }
    }

    public ICommand OpenCommand
    {
        get;
        set;
    }

    public ICommand SaveCommand
    {
        get;
        set;
    }

    #endregion

    private void OpenFile()
    {
        FileService fileServices = new FileService();
        this.Stream = fileServices.OpenFile(this.Extension, this.Filter);
        this.FileName = fileServices.FileName;
    }

    private void SaveFile()
    {
        FileService fileServices = new FileService();
        this.Stream = fileServices.SaveFile(this.Extension, this.Filter);
        this.FileName = fileServices.FileName;
    }
}

 

Now we can use this new property in another view model or even in XAML. In our previous example, we are creating an instance of FileDialogViewModel inside the MainViewModel. Let’s use the same approach and use this new property.

Code Snippet
public class MainViewmodel : ViewModelBase
{
    private string text;
    private string fileName;

    public MainViewmodel()
    {
        this.SaveCommand = new RelayCommand(this.SaveFile);
        this.OpenCommand = new RelayCommand(this.OpenFile);            
    }

    #region Properties

    public string Text
    {
        get
        {
            return this.text;
        }

        set
        {
            this.text = value;
            this.RaisePropertyChanged("Text");
        }
    }

    public string FileName
    {
        get
        {
            return string.IsNullOrEmpty(this.fileName) ? "No file selected" : this.fileName;
        }

        set
        {
            this.fileName = value;
            this.RaisePropertyChanged("FileName");
        }
    }

    public ICommand OpenCommand
    {
        get;
        set;
    }

    public ICommand SaveCommand
    {
        get;
        set;
    }

    #endregion

    private void OpenFile()
    {
        FileDialogViewModel fdvm = new FileDialogViewModel();
        fdvm.Extension = "*.txt";
        fdvm.Filter = "Text documents (.txt)|*.txt";

        fdvm.OpenCommand.Execute(null);

        if (fdvm.Stream == null)
            return;

        this.FileName = fdvm.FileName;

        using (StreamReader sr = new StreamReader(fdvm.Stream, Encoding.ASCII))
        {
            this.Text = sr.ReadToEnd();
        }
    }

    private void SaveFile()
    {
        FileDialogViewModel fdvm = new FileDialogViewModel();
        fdvm.Extension = "*.txt";
        fdvm.Filter = "Text documents (.txt)|*.txt";

        fdvm.SaveCommand.Execute(null);

        if (fdvm.Stream == null)
            return;

        this.FileName = fdvm.FileName;

        using (StreamWriter sw = new StreamWriter(fdvm.Stream, Encoding.ASCII))
        {
            sw.Write(this.Text.ToString(CultureInfo.InvariantCulture));    
        }           
    }
}

 

In XAML we just bind the new property to the tile of the main window to display the currently open file name in the title bar. Here is our XAML code of updated simple text editor.

Code Snippet
<Window x:Class="WpfFileDialog.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="{Binding FileName}" Height="350" Width="525">
    <Grid DataContext="{Binding}">
        <Grid.RowDefinitions>
            <RowDefinition Height="4*"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Margin="10"
                 TextWrapping="Wrap" AcceptsReturn="True"
                 HorizontalScrollBarVisibility="Auto"
                 VerticalScrollBarVisibility="Auto"
                 Text="{Binding Text}"/>
        <Button Grid.Column="0" Grid.Row="2" Margin="10"
                Command="{Binding OpenCommand}">
            Open
        </Button>
        <Button Grid.Column="1" Grid.Row="2" Margin="10"
                Command="{Binding SaveCommand}">
            Save
        </Button>
    </Grid>
</Window>

 

This is a screen shot of the program. Notice the file name is displayed at the title bar.

FileDialogViewModel2

Posted by: Zeeshan Amjad | January 25, 2014

File Dialog ViewModel


During one of my WPF application, I came across a situation to display the File dialog to open and save the file. My first abstraction is to make a ViewModel for File dialog so I can reuse it. Although I can use the OpenFileDialog and SaveFileDialog classes from the FileViewModel, but I want to make the user interface logic separate from the ViewModel. To make the user interface logic separate, I created a small utility or helper class to to wrap the OpenFileDialog and SaveFileDialog functionality. Here is my class.

Code Snippet
public sealed class FileService
{
    public Stream OpenFile(string defaultExtension, string filter)
    {
        OpenFileDialog fd = new OpenFileDialog();
        fd.DefaultExt = defaultExtension;
        fd.Filter = filter;

        bool? result = fd.ShowDialog();

        return result.Value ? fd.OpenFile() : null;
    }

    public Stream SaveFile(string defaultExtension, string filter)
    {
        SaveFileDialog fd = new SaveFileDialog();
        fd.DefaultExt = defaultExtension;
        fd.Filter = filter;

        bool? result = fd.ShowDialog();

        return result.Value ? fd.OpenFile() : null;
    }        
}

 

Now my next step is to FileDialogViewModel. Assuming that I already have a ViewModelBase class that implements the INotifyPropertyChanged interface, here is a simple implementation of FileDialogViewModel.

Code Snippet
public class FileDialogViewModel : ViewModelBase
{
    public FileDialogViewModel()
    {
        this.SaveCommand = new RelayCommand(this.SaveFile);
        this.OpenCommand = new RelayCommand(this.OpenFile);            
    }

    #region Properties

    public Stream Stream
    {
        get;
        set;
    }

    public string Extension
    {
        get;
        set;
    }

    public string Filter
    {
        get;
        set;
    }
    public ICommand OpenCommand
    {
        get;
        set;
    }

    public ICommand SaveCommand
    {
        get;
        set;
    }

    #endregion

    private void OpenFile()
    {
        FileService fileServices = new FileService();
        this.Stream = fileServices.OpenFile(this.Extension, this.Filter);
    }

    private void SaveFile()
    {
        FileService fileServices = new FileService();
        this.Stream = fileServices.SaveFile(this.Extension, this.Filter);
    }
}

 

Because the return type of Execute method in ICommand interface doesn’t return anything, therefore, we created a Stream property to store the stream of file. This small FileDialogViewModel class encapsulate the functionality of opening and saving file without knowing anything about the user interface.

Now comes to our main view model that uses the FileDialogViewModel. Here is a simple implementation of our main view model that uses the FileDialogViewModel to open and save the file to make a simple text editor.

Code Snippet
public class MainViewmodel : ViewModelBase
{
    private string text;

    public MainViewmodel()
    {
        this.SaveCommand = new RelayCommand(this.SaveFile);
        this.OpenCommand = new RelayCommand(this.OpenFile);            
    }

    #region Properties

    public string Text
    {
        get
        {
            return this.text;
        }

        set
        {
            this.text = value;
            this.RaisePropertyChanged("Text");
        }
    }

    public ICommand OpenCommand
    {
        get;
        set;
    }

    public ICommand SaveCommand
    {
        get;
        set;
    }

    #endregion

    private void OpenFile()
    {
        FileDialogViewModel fdvm = new FileDialogViewModel();
        fdvm.Extension = "*.txt";
        fdvm.Filter = "Text documents (.txt)|*.txt";

        fdvm.OpenCommand.Execute(null);

        using (StreamReader sr = new StreamReader(fdvm.Stream, Encoding.ASCII))
        {
            this.Text = sr.ReadToEnd();
        }
    }

    private void SaveFile()
    {
        FileDialogViewModel fdvm = new FileDialogViewModel();
        fdvm.Extension = "*.txt";
        fdvm.Filter = "Text documents (.txt)|*.txt";

        fdvm.SaveCommand.Execute(null);

        using (StreamWriter sw = new StreamWriter(fdvm.Stream, Encoding.ASCII))
        {
            sw.Write(this.Text.ToString(CultureInfo.InvariantCulture));    
        }           
    }
}

 

Here is a complete XAML code of the program.

Code Snippet
<Window x:Class="WpfFileDialog.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="FileViewModel" Height="350" Width="525">
    <Grid DataContext="{Binding}">
        <Grid.RowDefinitions>
            <RowDefinition Height="4*"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Margin="10"
                 TextWrapping="Wrap" AcceptsReturn="True"
                 HorizontalScrollBarVisibility="Auto"
                 VerticalScrollBarVisibility="Auto"
                 Text="{Binding Text}"/>
        <Button Grid.Column="0" Grid.Row="2" Margin="10"
                Command="{Binding OpenCommand}">
            Open
        </Button>
        <Button Grid.Column="1" Grid.Row="2" Margin="10"
                Command="{Binding SaveCommand}">
            Save
        </Button>
    </Grid>
</Window>

And here is a complete C# code of this simple text editor using FileDialogViewModel

Code Snippet
namespace WpfFileDialog
{
    using System;
    using System.ComponentModel;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using System.Windows;
    using System.Windows.Input;
    using Microsoft.Win32;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private MainViewmodel mvm = new MainViewmodel();

        public MainWindow()
        {
            InitializeComponent();

            DataContext = mvm;
        }
    }

    public class MainViewmodel : ViewModelBase
    {
        private string text;

        public MainViewmodel()
        {
            this.SaveCommand = new RelayCommand(this.SaveFile);
            this.OpenCommand = new RelayCommand(this.OpenFile);            
        }

        #region Properties

        public string Text
        {
            get
            {
                return this.text;
            }

            set
            {
                this.text = value;
                this.RaisePropertyChanged("Text");
            }
        }

        public ICommand OpenCommand
        {
            get;
            set;
        }

        public ICommand SaveCommand
        {
            get;
            set;
        }

        #endregion

        private void OpenFile()
        {
            FileDialogViewModel fdvm = new FileDialogViewModel();
            fdvm.Extension = "*.txt";
            fdvm.Filter = "Text documents (.txt)|*.txt";

            fdvm.OpenCommand.Execute(null);

            if (fdvm.Stream == null)
                return;

            using (StreamReader sr = new StreamReader(fdvm.Stream, Encoding.ASCII))
            {
                this.Text = sr.ReadToEnd();
            }
        }

        private void SaveFile()
        {
            FileDialogViewModel fdvm = new FileDialogViewModel();
            fdvm.Extension = "*.txt";
            fdvm.Filter = "Text documents (.txt)|*.txt";

            fdvm.SaveCommand.Execute(null);

            if (fdvm.Stream == null)
                return;

            using (StreamWriter sw = new StreamWriter(fdvm.Stream, Encoding.ASCII))
            {
                sw.Write(this.Text.ToString(CultureInfo.InvariantCulture));    
            }           
        }
    }

    public class FileDialogViewModel : ViewModelBase
    {
        public FileDialogViewModel()
        {
            this.SaveCommand = new RelayCommand(this.SaveFile);
            this.OpenCommand = new RelayCommand(this.OpenFile);            
        }

        #region Properties

        public Stream Stream
        {
            get;
            set;
        }

        public string Extension
        {
            get;
            set;
        }

        public string Filter
        {
            get;
            set;
        }
        public ICommand OpenCommand
        {
            get;
            set;
        }

        public ICommand SaveCommand
        {
            get;
            set;
        }

        #endregion

        private void OpenFile()
        {
            FileService fileServices = new FileService();
            this.Stream = fileServices.OpenFile(this.Extension, this.Filter);
        }

        private void SaveFile()
        {
            FileService fileServices = new FileService();
            this.Stream = fileServices.SaveFile(this.Extension, this.Filter);
        }
    }

    public sealed class FileService
    {
        public Stream OpenFile(string defaultExtension, string filter)
        {
            OpenFileDialog fd = new OpenFileDialog();
            fd.DefaultExt = defaultExtension;
            fd.Filter = filter;

            bool? result = fd.ShowDialog();

            return result.Value ? fd.OpenFile() : null;
        }

        public Stream SaveFile(string defaultExtension, string filter)
        {
            SaveFileDialog fd = new SaveFileDialog();
            fd.DefaultExt = defaultExtension;
            fd.Filter = filter;

            bool? result = fd.ShowDialog();

            return result.Value ? fd.OpenFile() : null;
        }        
    }

    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        #region NotifyPropertyChanged Methods

        public void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

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

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

    public sealed class RelayCommand : ICommand
    {
        private Action function;

        public RelayCommand(Action function)
        {
            this.function = function;
        }

        public bool CanExecute(object parameter)
        {
            return this.function != null;
        }

        public void Execute(object parameter)
        {
            if (this.function != null)
            {
                this.function();
            }
        }

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

 

Here is an output of the program.

FileDialogViewModel

Posted by: Zeeshan Amjad | November 26, 2013

Logical Multivalue Converter with LINQ


We just studied the logical multivalve converter here. Now we are going to do the same thing but instead of doing it manually traversing every values and apply the “AND” or “OR” logical operation, we can achieve the same thing with LINQ. We can use the Extension methods “All” and “Any” defined for IEnumerable type to do the same thing.

Here is an updated version of our Logical And converter.

Code Snippet
using System.Linq;

namespace MyConverter
{
    using System.Windows.Data;

    [ValueConversion(typeof(bool), typeof(bool))]
    public class AndConverter : IMultiValueConverter
    {
        public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return values.Cast<bool>().All(value => value);
        }

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

 

Similarly here is an updated version of Logical Or operator.

Code Snippet
using System.Linq;

namespace MyConverter
{
    using System.Windows.Data;

    [ValueConversion(typeof(bool), typeof(bool))]
    public class OrConverter : IMultiValueConverter
    {
        public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return values.Cast<bool>().Any(value => value);
        }

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

 

Rest of the code of this application and out put is exactly the same as previous program. Here is our C# code.

 

Code Snippet
namespace MyConverter
{
    using System.Linq;
    using System.ComponentModel;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new MyConditions();
        }
    }

    public class MyConditions : INotifyPropertyChanged
    {
        private bool _condition1;

        #region NotifyPropertyChanged Methods

        public void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;

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

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public bool Condition1
        {
            get
            {
                return _condition1;
            }

            set
            {
                _condition1 = value;
                RaisePropertyChanged("Condition1");
            }
        }

        public bool Condition2
        {
            get
            {
                return _condition1;
            }

            set
            {
                _condition1 = value;
                RaisePropertyChanged("Condition2");
            }
        }

        public bool Condition3
        {
            get
            {
                return _condition1;
            }

            set
            {
                _condition1 = value;
                RaisePropertyChanged("Condition3");
            }
        }

        public bool Condition4
        {
            get
            {
                return _condition1;
            }

            set
            {
                _condition1 = value;
                RaisePropertyChanged("Condition4");
            }
        }
    }
}

 

And here is our XAML.

Code Snippet
<Window x:Class="MyConverter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:local="clr-namespace:MyConverter"
        Title="And Or Converters" Height="300" Width="400">
    <Window.Resources>
        <local:AndConverter x:Key="AndConverter"/>
        <local:OrConverter x:Key="OrConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <CheckBox Grid.Row="0" VerticalAlignment="Center"
                  Name="Condition1" Margin="5" IsChecked="{Binding Condition1}"
                  Content="Conditin 1"/>
        <CheckBox Grid.Row="1" Grid.Column="0" VerticalAlignment="Center"
                  Name="Condition2" Margin="5" IsChecked="{Binding Condition2}"
                  Content="Conditin 2"/>
        <CheckBox Grid.Row="2" Grid.Column="0" VerticalAlignment="Center"
                  Name="Condition3" Margin="5" IsChecked="{Binding Condition3}"
                  Content="Conditin 3"/>
        <CheckBox Grid.Row="3" Grid.Column="0" VerticalAlignment="Center"
                  Name="Condition4" Margin="5" IsChecked="{Binding Condition4}"
                  Content="Conditin 4"/>
        <TextBox Grid.Row="4" Grid.Column="0" VerticalAlignment="Center"
                   Margin="5" Text="And Value Converter">
            <TextBox.IsEnabled>
                <MultiBinding Converter="{StaticResource AndConverter}">
                    <Binding Path="Condition1"/>
                    <Binding Path="Condition2"/>
                    <Binding Path="Condition3"/>
                    <Binding Path="Condition4"/>
                </MultiBinding>
            </TextBox.IsEnabled>
        </TextBox>
        <TextBox Grid.Column="1" Grid.Row="4" VerticalAlignment="Center"
                   Margin="5" Text="Or Value Converter">
            <TextBox.IsEnabled>
                <MultiBinding Converter="{StaticResource OrConverter}">
                    <Binding Path="Condition1"/>
                    <Binding Path="Condition2"/>
                    <Binding Path="Condition3"/>
                    <Binding Path="Condition4"/>
                </MultiBinding>
            </TextBox.IsEnabled>
        </TextBox>
    </Grid>
</Window>

 

Here is an output of the program.

LogicalMultiValueConverter

Posted by: Zeeshan Amjad | November 15, 2013

Logical Multi value Converter


During one of my project, I came across a situation where I should enable or disable a control based on not one condition, but more than one conditions. For example, do not enable the submit button until user input all the required information. Or do not enable the button to move the next page of the wizard until you select all the required information from all the combo boxes and check boxes in the current screen.

As like other things, this can be done in different ways in WPF. I decided to use multi value converter for this purpose. The reason is because it is very lightweight and can be make generic enough to reuse and unlike markup extension can be applied at run time when the value of properties changes.

We already have an example of not converter here. There is only one operand to not operator, therefore we can implement it using IValueConverter interface. However, And, Or, operator needs at least two operators, therefore it has to be IMultiValueConverter interface.

Making “And” and “Or” logical operator are very straight forward. Here is a code for “And Converter”.

Code Snippet
namespace MyConverter
{
    using System.Windows.Data;

    [ValueConversion(typeof(bool), typeof(bool))]
    public class AndConverter : IMultiValueConverter
    {
        public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool result = true;

            foreach (var item in values)
            {
                bool value = (bool)item;

                if (!value)
                {
                    return false;
                }
            }

            return result;
        }

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

 

The “Or Converter” is also very similar. Here is a code for “Or Converter”.

 

Code Snippet
namespace MyConverter
{
    using System.Windows.Data;

    [ValueConversion(typeof(bool), typeof(bool))]
    public class OrConverter : IMultiValueConverter
    {
        public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool result = false;

            foreach (var item in values)
            {
                bool value = (bool)item;

                if (value)
                {
                    return true;
                }
            }

            return result;
        }

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

 

Now how we are going to use it. Its usage is very similar to any other converter. First creates and object of this class, usually in XAML in resource section then pass bind the conditions to it. Here is a usage of it.

Code Snippet
<TextBox Grid.Row="4" VerticalAlignment="Center"
           Margin="5" Text="And Value Converter">
    <TextBox.IsEnabled>
        <MultiBinding Converter="{StaticResource andConverter}">
            <Binding Path="Condition1"/>
            <Binding Path="Condition2"/>
            <Binding Path="Condition3"/>
            <Binding Path="Condition4"/>
        </MultiBinding>
    </TextBox.IsEnabled>
</TextBox>

 

Here we bind the enable property of TextBox to 4 conditions. Because we are using And converter, therefore the textbox will enable if all the condition will be true. These conditions can be set using any other UI element, some business logic or even based on other conditions. Usage of Or converter is also very similar.

Here is complete XAML of this simple program.

Code Snippet
<Window x:Class="MyConverter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:local="clr-namespace:MyConverter"
        Title="And Or Converters" Height="300" Width="400">
    <Window.Resources>
        <local:AndConverter x:Key="andConverter"/>
        <local:OrConverter x:Key="orConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <CheckBox Grid.Row="0" VerticalAlignment="Center"
                  Name="condition1" Margin="5" IsChecked="{Binding Condition1}"
                  Content="Conditin 1"/>
        <CheckBox Grid.Row="1" VerticalAlignment="Center"
                  Name="condition2" Margin="5" IsChecked="{Binding Condition2}"
                  Content="Conditin 2"/>
        <CheckBox Grid.Row="2" VerticalAlignment="Center"
                  Name="condition3" Margin="5" IsChecked="{Binding Condition3}"
                  Content="Conditin 3"/>
        <CheckBox Grid.Row="3" VerticalAlignment="Center"
                  Name="condition4" Margin="5" IsChecked="{Binding Condition4}"
                  Content="Conditin 4"/>
        <TextBox Grid.Row="4" VerticalAlignment="Center"
                   Margin="5" Text="And Value Converter">
            <TextBox.IsEnabled>
                <MultiBinding Converter="{StaticResource andConverter}">
                    <Binding Path="Condition1"/>
                    <Binding Path="Condition2"/>
                    <Binding Path="Condition3"/>
                    <Binding Path="Condition4"/>
                </MultiBinding>
            </TextBox.IsEnabled>
        </TextBox>
        <TextBox Grid.Column="1" Grid.Row="4" VerticalAlignment="Center"
                   Margin="5" Text="Or Value Converter">
            <TextBox.IsEnabled>
                <MultiBinding Converter="{StaticResource orConverter}">
                    <Binding Path="Condition1"/>
                    <Binding Path="Condition2"/>
                    <Binding Path="Condition3"/>
                    <Binding Path="Condition4"/>
                </MultiBinding>
            </TextBox.IsEnabled>
        </TextBox>
    </Grid>
</Window>

 

And here is a C# code of the program.

Code Snippet
namespace MyConverter
{
    using System.ComponentModel;
    using System.Windows;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new MyConditions();
        }
    }

    public class MyConditions : INotifyPropertyChanged
    {
        private bool condition1;
        private bool condition2;
        private bool condition3;
        private bool condition4;

        #region NotifyPropertyChanged Methods

        public void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

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

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public bool Condition1
        {
            get
            {
                return this.condition1;
            }

            set
            {
                this.condition1 = value;
                this.RaisePropertyChanged("Condition1");
            }
        }

        public bool Condition2
        {
            get
            {
                return this.condition1;
            }

            set
            {
                this.condition1 = value;
                this.RaisePropertyChanged("Condition2");
            }
        }

        public bool Condition3
        {
            get
            {
                return this.condition1;
            }

            set
            {
                this.condition1 = value;
                this.RaisePropertyChanged("Condition3");
            }
        }

        public bool Condition4
        {
            get
            {
                return this.condition1;
            }

            set
            {
                this.condition1 = value;
                this.RaisePropertyChanged("Condition4");
            }
        }
    }
}

 

Here is an output of the program.

LogicalMultiValueConverter

Posted by: Zeeshan Amjad | September 28, 2013

Editable ComboBox in MVVM


Creating an editable combo box in WPF is not very difficult, just set the IsEditable property to true. What makes it interesting is when we are trying to add a new item in the combo box that is not a part of it before using data binding or MVVM pattern. In other words doing it without any code behind.

Let’s first step to create a MVVM application using editable combo box without adding any new item in it. It is quite straight forward task.

This is simple and standard view model with two properties. First one is an observable collection stored the list of cities and the other one is selected city.

Code Snippet
public class ViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> cities = new ObservableCollection<string>();
    private string selectedItem;

    public ViewModel()
    {
        this.Cities.Add("Boston");
        this.Cities.Add("Los Angeles");
        this.cities.Add("Frederick");
        this.cities.Add("Houston");

        this.SelectedCity = "Boston";
    }

    public ObservableCollection<string> Cities
    {
        set
        {
            this.cities = value;
            this.RaisePropertyChanged("Cities");
        }
        get
        {
            return this.cities;
        }
    }

    public string SelectedCity
    {
        set
        {
            this.selectedItem = value;
            this.RaisePropertyChanged("SelectedCity");
        }
        get
        {
            return this.selectedItem;
        }
    }

    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;

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

    public event PropertyChangedEventHandler PropertyChanged;
}

 

The reason to create a selected city property is two fold. First we want to show the selected item in the textbox (or any other control). But the most important one is when we are going to add the functionality of add items in the combo box, then it will be more useful, because we don’t only add the items in the combo box, but also set that value as a selected item. Obviously it doesn’t make sense that first user entered a new entry, then select it from the combo box, it should be one step.

Now lets see the fun part i.e. going to add a new city in the editable combo box. To do this we are going to use the Text property of the combo box. We already used the ItemsSource and SelectedItems property and this time we are going to introduce one more property in my view model class to bind with TextProperty of the combo box.

And here rubber meets the road. We will add the new entry in the city collection. In addition to this, we return the selected city as a getter of that property, because there is no field to backup this. It would be something like this.

Code Snippet
public string NewCity
{
    set
    {
        if (!string.IsNullOrEmpty(value))
        {
            this.Cities.Add(value);
            this.SelectedCity = value;
        }
    }
    get
    {
        return this.SelectedCity;
    }
}

 

Here is a complete XAML of our program.

Code Snippet
<Window x:Class="WpfEditableCombo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="Editable ComboxBox" Height="300" Width="400">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ComboBox Grid.Row="0" Margin="5" VerticalAlignment="Center" IsEditable="True"
                  ItemsSource="{Binding Cities}"
                  SelectedItem="{Binding SelectedCity}"
                  Text="{Binding NewCity, UpdateSourceTrigger=LostFocus}"/>
        <TextBox Grid.Row="1" Margin="5" VerticalAlignment="Center"
                   Text="{Binding SelectedCity}"/>
    </Grid>
</Window>

 

The only important thing to note here is the UpgradeSourceTrigger property. We set it to LostFocus, so it will call the setter of NewItems property only when we lost the focus from the combobox. In other words, we only add items in the collection when we are done with out editing. But you should have another control there to get the focus and that is exactly the reason I have TextBox, not TextBlock here.

Here is the initial screen shot of the program.

EditableCombo_01

And here is a screen shot after adding “New York” in the combo box.

EditableCombo_02

Posted by: Zeeshan Amjad | August 23, 2013

Using Timer in MVVM


Currently I came across a problem where I am supposed to use timer in my MVVM based application. Initially i was little concern that where should i put the event handler to response the timer tick, but eventually settled up to write event handler in my ViewModel. By making timer tick event handler in ViewModel, we are not making it UI specific or even UI aware anyway. Once i settled this then rest of the exercise is very straight forward.

Let’s first do some infrastructure work. Here is my simple implementation of ICommand interface. This is not a general purpose implementation of ICommand interface, because we simply ignore the predicate and command parameter, but for this small project this is enough. You can see the more general implementation here.

Code Snippet
public class RelayCommand : ICommand
{
    private Action Function;
    private Func<bool> Predicate;

    public RelayCommand(Action Function)
    {
        this.Function = Function;
    }

    public RelayCommand(Action Function, Func<bool> Predicate)
    {
        this.Function = Function;
        this.Predicate = Predicate;
    }

    #region NotifyPropertyChanged Methods

    public bool CanExecute(object parameter)
    {
        if (this.Predicate != null)
        {
            return this.Predicate();
        }

        return true;
    }

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

    public void Execute(object parameter)
    {
        if (this.Function != null)
        {
            this.Function();
        }
    }

    #endregion
}

 

Now comes the fun part, ViewModel. In our ViewModel, i introduced four properties. Two of them are ICommand type properties to start and stop the timer and one is Text property to display the current time on the screen. I also made the duration property although currently we set its value 1000 and not setting it, but it would be useful in a program where we even want to set the duration of our time tick.

The interesting part is to set the event handler in out start timer method.

Code Snippet
public void StartTimer()
{
    timer = new DispatcherTimer();
    timer.Interval = TimeSpan.FromMilliseconds(this.Duration);
    timer.Tick += new EventHandler(TimerTick);
    timer.Start();
}

 

In our event handler, we simply set the Text to current time. Here is complete implementation of our ViewModel.

Code Snippet
public class TimerViewModel : INotifyPropertyChanged
{
    private int duration;
    private string text;
    private DispatcherTimer timer = null;

    public TimerViewModel()
    {
        this.Duration          = 1000;
        this.Text              = DateTime.Now.ToString("HH:mm:ss tt");
        this.StartTimerCommand = new RelayCommand(this.StartTimer);
        this.StopTimerCommand  = new RelayCommand(this.StopTimer);
    }

    #region Properties
    
    public int Duration
    {
        get
        {
            return this.duration;
        }
        set
        {
            this.duration = value;
            RaisePropertyChanged("Duration");
        }
    }

    public string Text
    {
        get
        {
            return this.text;
        }
        set
        {
            this.text = value;
            RaisePropertyChanged("Text");
        }
    }

    public ICommand StartTimerCommand
    {
        get;
        set;
    }

    public ICommand StopTimerCommand
    {
        get;
        set;
    }

    #endregion

    #region NotifyPropertyChanged Methods

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;

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

    #endregion

    public void StartTimer()
    {
        timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromMilliseconds(this.Duration);
        timer.Tick += new EventHandler(TimerTick);
        timer.Start();
    }

    public void StopTimer()
    {
        if (timer != null)
        {
            timer.Stop();
            timer = null;
        }
    }

    private void TimerTick(object send, EventArgs e)
    {
        this.Text = DateTime.Now.ToString("HH:mm:ss tt");
    }
}

 

Our XAML code is very straight forward, we just do the binding with Button and TextBlock. Here is our XAML code.

Code Snippet
<Window x:Class="WpfMvvmTimer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="Timer ViewModel" Height="200" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="45"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Margin="5"
                   VerticalAlignment="Center" HorizontalAlignment="Center"
                   FontSize="32" FontWeight="Bold"
                   Text="{Binding Text}"/>
        <Button Grid.Column="0" Grid.Row="1" Margin="5"
                Command="{Binding StartTimerCommand}"
                Content="Start Timer"/>
        <Button Grid.Column="1" Grid.Row="1" Margin="5"
                Command="{Binding StopTimerCommand}"
                        Content="Stop Timer"/>
        </Grid>
</Window>

 

In our main, we simply create an object of our ViewMode and set the DataContext property to our view Model. Here is a complete C# code of our project

Code Snippet
namespace WpfMvvmTimer
{
    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Threading;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new TimerViewModel(); ;
        }
    }

    public class TimerViewModel : INotifyPropertyChanged
    {
        private int duration;
        private string text;
        private DispatcherTimer timer = null;

        public TimerViewModel()
        {
            this.Duration          = 1000;
            this.Text              = DateTime.Now.ToString("HH:mm:ss tt");
            this.StartTimerCommand = new RelayCommand(this.StartTimer);
            this.StopTimerCommand  = new RelayCommand(this.StopTimer);
        }

        #region Properties
        
        public int Duration
        {
            get
            {
                return this.duration;
            }
            set
            {
                this.duration = value;
                RaisePropertyChanged("Duration");
            }
        }

        public string Text
        {
            get
            {
                return this.text;
            }
            set
            {
                this.text = value;
                RaisePropertyChanged("Text");
            }
        }

        public ICommand StartTimerCommand
        {
            get;
            set;
        }

        public ICommand StopTimerCommand
        {
            get;
            set;
        }

        #endregion

        #region NotifyPropertyChanged Methods

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

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

        #endregion

        public void StartTimer()
        {
            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(this.Duration);
            timer.Tick += new EventHandler(TimerTick);
            timer.Start();
        }

        public void StopTimer()
        {
            if (timer != null)
            {
                timer.Stop();
                timer = null;
            }
        }

        private void TimerTick(object send, EventArgs e)
        {
            this.Text = DateTime.Now.ToString("HH:mm:ss tt");
        }
    }

    public class RelayCommand : ICommand
    {
        private Action Function;
        private Func<bool> Predicate;

        public RelayCommand(Action Function)
        {
            this.Function = Function;
        }

        public RelayCommand(Action Function, Func<bool> Predicate)
        {
            this.Function = Function;
            this.Predicate = Predicate;
        }

        #region NotifyPropertyChanged Methods

        public bool CanExecute(object parameter)
        {
            if (this.Predicate != null)
            {
                return this.Predicate();
            }

            return true;
        }

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

        public void Execute(object parameter)
        {
            if (this.Function != null)
            {
                this.Function();
            }
        }

        #endregion
    }
}

 

When we run the program it shows the current time and do nothing. But if we press the Start Timer button, then it will updating the current time every second. Here is an output of the program.

TimerViewModel

Posted by: Zeeshan Amjad | July 31, 2013

Using Mediator to communicate between user controls: Part 8


The mediator pattern we created here works quite well for most of my scenario where i am suppose to use int message not string messages. Changing the class is not a big deal, i can easily change the source of Mediator class to use int and create Dictionary of int instead of string. But this raise a question, what if in future i want to use a different type? Do I have to do it again. Why not make it such a way that it can be used with more than one type without changing the code, or at best minimal changes of code.

I decided to make message generic just like i did with Action parameter. Its quite simple solution and can be done in few minutes. Here is a new version of Mediator class that uses generic messages.

Code Snippet
namespace MVVMBase
{
    using System;
    using System.Collections.Generic;

    public sealed class Mediator<TMessage>
    {
        private Dictionary<TMessage, List<WeakReferenceWrapper>> actions =
             new Dictionary<TMessage, List<WeakReferenceWrapper>>();

        public Mediator()
        {
        }

        public void Register<TParameter>(TMessage message, object receiver, Action<TParameter> action)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            lock (this.actions)
            {
                if (!this.actions.ContainsKey(message))
                {
                    this.actions[message] = new List<WeakReferenceWrapper>();
                }

                this.actions[message].Add(new WeakReferenceWrapper(receiver, action));
            }
        }

        public void Unregister<TParameter>(TMessage message, object receiver, Action<TParameter> action)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            lock (this.actions)
            {
                if (this.actions.ContainsKey(message))
                {
                    List<WeakReferenceWrapper> actionlist = this.actions[message];

                    actionlist.Remove(new WeakReferenceWrapper(receiver, action));

                    if (actionlist.Count == 0)
                    {
                        this.actions.Remove(message);
                    }
                }
            }
        }

        public void Send<TParameter>(TMessage message, TParameter parameter)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            lock (this.actions)
            {
                if (this.actions.ContainsKey(message))
                {
                    List<WeakReferenceWrapper> actionslist = this.actions[message];

                    foreach (var action in actionslist)
                    {
                        action.Action.DynamicInvoke(parameter);
                    }
                }
            }
        }
    }
}

So far so good, but now I have to change the Mediator property too in all of my ViewModel and UserControl classes to use the type. Let’s first create a Mediator object with additional information.

Code Snippet
Mediator = new Mediator<int>();

Mediator.Register<object>(1, myvm, myvm.Notify);

 

And here is a change we are suppose to do in ViewModel or UserControl code behing class.

Code Snippet
public Mediator<int> Mediator
{
    get;
    set;
}

 

Remember the type should be the same, otherwise you will get a compilation error. Let’s force it by making a contract that every class that need to send message or be notified used a proper signature by introducing interface. We can make an interface that does this. Here is a code of our interface

Code Snippet
namespace MVVMBase
{
    interface IMediator<TMessage, TParameter>
    {
        Mediator<TMessage> Mediator
        {
            get;
            set;
        }

        void Send(TMessage message, TParameter parameter);

        void Notify(TParameter parameter);
    }
}

 

In this way we also document that which classes are taking part of this approach. Here is an example of one class that implement this interface.

Code Snippet
public class SettingsViewModel : ViewModelBase, IMediator<int, object>
{

    // other stuff

    public Mediator<int> Mediator
    {
        get;
        set;
    }

    public ICommand GetSettingsCommand
    {
        get;
        set;
    }

    public void Send(int message, object o)
    {
        Mediator.Send<object>(message, o);
    }

    public void Notify(object o)
    {

    }

    private void GetSettings()
    {
        Send(1, "testmessage");
    }
}

 

But this will create one interesting problem. Now we can select the message type, but our message is restricted. If we want to pass different types of messages, then we have to implement IMediator interface with different second generic parameter.

Let’s remove the second parameter from IMediator interface and make it generic only for message type. In this case we have to modify the Send and Nofity methods and and make those generic. Here is updated version of our IMediator interface.

Code Snippet
namespace MVVMBase
{
    public interface IMediator<TMessage>
    {
        Mediator<TMessage> Mediator
        {
            get;
            set;
        }

        void Send<TParameter>(TMessage message, TParameter parameter);

        void Notify<TParameter>(TParameter parameter);
    }
}

 

Here is a usage of our new IMediator interface

Code Snippet
namespace ADFDesktopTool
{
    using System.Collections.ObjectModel;
    using System.Windows.Input;
    using MVVMBase;

    public class SettingsViewModel : ViewModelBase, IMediator<int>
    {
        // other stuff

        public Mediator<int> Mediator
        {
            get;
            set;
        }

        public void Send<TParameter>(int message, TParameter arg)
        {
            Mediator.Send<TParameter>(message, arg);
        }

        public void Notify<TParameter>(TParameter args)
        {

        }

    }
}

 

Let’s make one small change in our Mediator class. Currently our Mediator class can register any class. Let’s make it more specific to register classes which implement IMediator interface only. Here is a new version of our Mediator class.

Code Snippet
namespace MVVMBase
{
    using System;
    using System.Collections.Generic;

    public sealed class Mediator<TMessage>
    {
        private Dictionary<TMessage, List<WeakReferenceWrapper>> actions =
             new Dictionary<TMessage, List<WeakReferenceWrapper>>();

        public Mediator()
        {
        }

        public void Register<TParameter>(TMessage message, IMediator<TMessage> receiver, Action<TParameter> action)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            lock (this.actions)
            {
                if (!this.actions.ContainsKey(message))
                {
                    this.actions[message] = new List<WeakReferenceWrapper>();
                }

                this.actions[message].Add(new WeakReferenceWrapper(receiver, action));
            }
        }

        public void Unregister<TParameter>(TMessage message, IMediator<TMessage> receiver, Action<TParameter> action)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            lock (this.actions)
            {
                if (this.actions.ContainsKey(message))
                {
                    List<WeakReferenceWrapper> actionlist = this.actions[message];

                    actionlist.Remove(new WeakReferenceWrapper(receiver, action));

                    if (actionlist.Count == 0)
                    {
                        this.actions.Remove(message);
                    }
                }
            }
        }

        public void Send<TParameter>(TMessage message, TParameter parameter)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            lock (this.actions)
            {
                if (this.actions.ContainsKey(message))
                {
                    List<WeakReferenceWrapper> actionslist = this.actions[message];

                    foreach (var action in actionslist)
                    {
                        action.Action.DynamicInvoke(parameter);
                    }
                }
            }
        }
    }
}

 

This is more powerful version of mediator than previous version can accept any type of message type and define contract to use with mediator.

The output of the program is same as previous program.

mediator_02_output

Older Posts »

Categories

Follow

Get every new post delivered to your Inbox.

Join 512 other followers