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

Advertisements

Responses

  1. […] 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 […]


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: