Posted by: Zeeshan Amjad | July 29, 2010

Range Converter


We have already saw an example of Negative converter here. Now we are going one step further and see how can we make a Range converter. The obvious thing about range converter is that it needs at least two parameters one for minimum value and other for maximum value. But the method Convert in IValueConvert interface has only one parameter. One possible solution is to passed array or structure to that parameter and then type cast it back to get the maximum and minimum value. But it is not very elegant solution, especially with respect to XAML. Of course we can use it in XAML, but for this we have to create an object of structure or array in XAML and then passed it as a parameter.

The other solution is why not passed the maximum and minimum as a parameter in the class which implement IValueConvert interface. We can overload the constructor as well as make properties for storing maximum and minimum values, but there is no easy way to use this in XAML.

Here we are using that converter with the help of our own markup extension. First take a look at our range converter. Here is our range converter.

public class RengeConvertor : IValueConverter
{
    public RengeConvertor()
    {
    }

    public RengeConvertor(int minimum, int maximum)
    {
        Maximum = maximum;
        Mininum = minimum;
    }

    public int Maximum
    { get; set; }

    public int Mininum
    { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int data = (int)value;

        if (data >= Mininum && data <= Maximum)
            return true;
        else
            return false;
    }

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

This class does the very simple thing. If the given data is inside the given range then return true, otherwise return false. Now our next task is to pass the values into this class. For this purpose we are going to make one markup extension. The whole purpose of this markup extension is to create an object of this class with given maximum and minimum values. Here is our range markup extension.

public class RangeExtension : MarkupExtension
{
    public RangeExtension()
    {
    }

    public RangeExtension(int minimum, int maximum)
    {
        Minimum = minimum;
        Maximum = maximum;
    }

    public int Maximum
    { get; set; }

    public int Minimum
    { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return new RengeConvertor(Minimum, Maximum);
    }
}

Usage of this value converter along with markup extension is very simple. Here is a piece of code to demonstrate this.

<DataTrigger Binding="{Binding Path=Populatoin, 
	Converter={local:Range Maximum=2000000, Minimum=1000000}}" Value="true">

Here we are passing  1000000  as a minim value and 2000000  as a maximum value. Here is complete XAML code of the program.

<Window x:Class="TypeConvertor.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TypeConvertor"
    Title="Data Trigger Demo" Height="300" Width="400" Loaded="Window_Loaded">    
    <Window.Resources>
        <Style TargetType="{x:Type ListViewItem}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Populatoin, 
                    Converter={local:Range Maximum=2000000, Minimum=1000000}}" Value="true">
                    <Setter Property="Background" Value="Green"/>
                    <Setter Property="Foreground" Value="White"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <Grid>                
        <ListView Name="lstView">
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="120" Header="State" DisplayMemberBinding="{Binding Path = State}"/>
                    <GridViewColumn Width="120" Header="City" DisplayMemberBinding="{Binding Path = City}"/>
                    <GridViewColumn Width="120" Header="Populatoin" DisplayMemberBinding="{Binding Path = Populatoin}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

And here is complete C# code of the program.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Reflection;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;

namespace TypeConvertor
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            lstView.Items.Add(new CityInfo("California", "Los Angeles", false, true, 3831868));
            lstView.Items.Add(new CityInfo("California", "San Francisco", false, false, 3228605));
            lstView.Items.Add(new CityInfo("California", "Sacramento", true, false, 486189));
            lstView.Items.Add(new CityInfo("California", "San Diego", false, false, 1359132));
            lstView.Items.Add(new CityInfo("Massachusetts", "Boston", true, true, 645169));
            lstView.Items.Add(new CityInfo("Massachusetts", "Newton", false, false, 93447));
        }
    }

    public class CityInfo
    {
        public CityInfo()
        {
        }

        public CityInfo(String state, String city,
            bool isCapital, bool isLargest, int population)
        {
            State = state;
            City = city;
            IsCapital = isCapital;
            IsLargest = isLargest;
            Populatoin = population;
        }

        public String State
        { set; get; }

        public String City
        { set; get; }

        public bool IsCapital
        { set; get; }

        public bool IsLargest
        { set; get; }

        public int Populatoin
        { set; get; }
    }

    public class RengeConvertor : IValueConverter
    {
        public RengeConvertor()
        {
        }

        public RengeConvertor(int minimum, int maximum)
        {
            Maximum = maximum;
            Mininum = minimum;
        }

        public int Maximum
        { get; set; }

        public int Mininum
        { get; set; }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int data = (int)value;

            if (data >= Mininum && data <= Maximum)
                return true;
            else
                return false;
        }

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

    public class RangeExtension : MarkupExtension
    {
        public RangeExtension()
        {
        }

        public RangeExtension(int minimum, int maximum)
        {
            Minimum = minimum;
            Maximum = maximum;
        }

        public int Maximum
        { get; set; }

        public int Minimum
        { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return new RengeConvertor(Minimum, Maximum);
        }
    }
}

 

This program display the cities in green background color whose population is in between  1000000 and  2000000 . Here is the output of the program.

RangeConverter

Advertisements

Responses

  1. […] Here we are going to use the same technique which we used when making the range converter here. I.e. define the value converter return it from the markup extension. Here is our value converter. […]

  2. […] already saw one example of Range Converter here. But in this example we created two different classes, one to implement the IValueConverter […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: