Search code examples
c#wpfmultibindingimultivalueconverter

How to bind Start, End and Duration with Multibinding?


I have two properties in my ViewModel:

public double Start { get; set; }
public double Duration { get; set; }

I have three textboxes in my View:

<TextBox Name="StartTextBox" Text="{Binding Start}" />
<TextBox Name="EndTextBox" />
<TextBox Name="DurationTextBox" Text="{Binding Duration} />

I want to achieve the following behavior:

  • When the user changes the content of the Start- or the EndTextBox, the DurationTextBox should be updated accordingly (Duration = End - Start).
  • When the user changes the DurationTextBox, the EndTextBox should be updated accordingly (End = Start + Duration).

I can achieve this by listening to the TextChanged events in code behind. I would prefer to achieve this via MultiBinding, though. Is it possible?

The problems I encounter, when I try to use MultiBinding:

  • If I put the MultiBinding on the DurationTextBox I cannot bind it to the Duration property.
  • If I put the MultiBinding on the EndTextBox and the user changes the StartTextBox, the EndTextBox gets updated instead of the DurationTextBox.
  • In any case I'm not able to implement the ConvertBack method.

Solution

  • I think blow codes are much easier to achieve the behavior which you want:

    XAML:

    <TextBox Name="StartTextBox" Text="{Binding Start}" />
    <TextBox Name="EndTextBox" Text="{Binding End}" />
    <TextBox Name="DurationTextBox" Text="{Binding Duration}" />
    

    ViewModel:

        private double _start;
        private double _duration;
        private double _end;
        public double Start
        {
            get
            {
                return _start;
            }
            set
            {
                if (_start != value)
                {
                    _start = value;
                    Duration = _end - _start;
                    OnPropertyChanged("Start");
                }
            }
        }
        public double Duration
        {
            get
            {
                return _duration;
            }
            set
            {
                if (_duration != value)
                {
                    _duration = value;
                    End = _duration + _start;
                    OnPropertyChanged("Duration");
                }
            }
        }
        public double End
        {
            get
            {
                return _end;
            }
            set
            {
                if (_end != value)
                {
                    _end = value;
                    Duration = _end - _start;
                    OnPropertyChanged("End");
                }
            }
        }
    

    The OnPropertyChanged in ViewModel implements the INotifyPropertyChanged interface like this:

    public class ViewModelBase:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }