comparing two dynamic values in DataTrigger

amit jha picture amit jha · May 18, 2016 · Viewed 8.3k times · Source

I want to compare two dynamic values User_id and user_id for equality and setting one property Cursor. Also, when the cursor is hand, I have to execute one function. How to do it? This is the code that I am using:

<DataTrigger Binding="{Binding Path=User_id}" Value="{Binding Path=user_id}">
  <Setter Property="Cursor" Value="Hand"/>
</DataTrigger>

Answer

Jason Tyler picture Jason Tyler · May 18, 2016

There are a couple options to attack this.

#1. Multibinding Converter

You can use Multibindingto input the two values into a IMultiValueConverter. To use this type of binding in your DataTrigger, you would use follow the following syntax.

<DataTrigger Value="True">
     <DataTrigger.Binding>
         <MultiBinding>
             <MultiBinding.Converter>
                 <local:EqualityConverter />
             </MultiBinding.Converter>
             <Binding Path="User_id" />
             <Binding Path="user_id" />
         </MultiBinding>
     </DataTrigger.Binding>
     <Setter Property="Window.Cursor" Value="Hand"/>
</DataTrigger>

The MultiBinding.Converteris set to a new instance of EqualityConverter, which is a class I created that implements the IMultiValueConverter interface. This class will do the comparison for you. The DataTrigger triggers when this converter returns true.

public class EqualityConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values.Length < 2)
            return false;

        return values[0].Equals(values[1]);

    }

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

#2. MVVM Pattern

I'm not sure where your DataContext is coming from, but if possible, you may want to consider using a view model for your binding. The view model could expose a property that does the equality comparison for you. Something like this.

   public class UserViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private int _User_id;
    private int _user_id;

    public int User_id
    {
        get
        {
            return _User_id;
        }
        set
        {
            if (_User_id != value)
            {
                _User_id = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("User_id"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsUserIdsEqual"));
                DoSomething();
            }
        }
    }
    public int user_id
    {
        get
        {
            return _user_id;
        }
        set
        {
            if (_user_id != value)
            {
                _user_id = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("user_id"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsUserIdsEqual"));
                DoSomething();
            }
        }
    }

    public bool IsUserIdsEqual
    {
        get { return _user_id == _User_id; }
    }

    private void DoSomething()
    {
        if (this.IsUserIdsEqual)
        {
            //Do something when they are equal.
        }
    }

}

If using a view model like this, your DataTrigger could simplify to..

<DataTrigger Binding="{Binding Path=IsUserIdsEqual}" Value="True">
    <Setter Property="Window.Cursor" Value="Hand"/>
</DataTrigger>

Regarding executing a function on the trigger, I added a DoSomething method to highlight how the view model could be used to execute a function when the two IDs are equal. I'm not sure if that would work for your case because I'm not sure what the intent of the function call is, but it is a way to execute a function when a condition changes.