Derrick Moeller
Derrick Moeller

Reputation: 4970

WPF: Conditional Binding

If my CheckBox is checked, I would like to disable the ComboBox and select "Yes". This works, what I would like to do is make this conditional such that when I uncheck the CheckBox MyBooleanProperty is not updated and "Yes" is still selected. The ComboBox itself should enable allowing me to choose "No" if desired.

<CheckBox Name="chkDefault" IsChecked="{Binding MyBooleanProperty, Mode=OneWayToSource}" />
<ComboBox IsEnabled="{Binding IsChecked, ElementName=chkDefault, Converter={StaticResource InverseBooleanConverter}}">
    <ComboBoxItem Content="No" />
    <ComboBoxItem Content="Yes" IsSelected="{Binding MyBooleanProperty}" />
</ComboBox>

In the past, I've done this with multiple properties(see below) but I'm wondering if there isn't something simpler than can be done in XAML that I am not aware of.

The View...

<CheckBox IsChecked="{Binding MyBooleanProperty, Mode=OneWayToSource}" />
<ComboBox IsEnabled="{Binding MyBooleanProperty, Converter={StaticResource InverseBooleanConverter}}">
    <ComboBoxItem Content="No" />
    <ComboBoxItem Content="Yes" IsSelected="{Binding MyOtherBooleanProperty}" />
</ComboBox>

And the ViewModel...

public bool MyBooleanProperty
{
    get { return _myBooleanProperty; }
    set
    {
        if (_myBooleanProperty != value)
        {
             _myBooleanProperty = value;

             if (_myBooleanProperty)
                MyOtherBooleanProperty = true;

             base.OnPropertyChanged("MyBooleanProperty");
        }
    }
}

public bool MyOtherBooleanProperty
{
    get { return _myOtherBooleanProperty; }
    set
    {
        if (_myOtherBooleanProperty != value)
        {
             _myOtherBooleanProperty = value;

             base.OnPropertyChanged("MyOtherBooleanProperty");
        }
    }
}

Upvotes: 0

Views: 2853

Answers (2)

cunningdave
cunningdave

Reputation: 1480

I would control the logic for this in the viewmodel, and not try to imply the logic via bindings. The View should just care that you've bound the combobox selection to a backing data member (two-way), and that the checkbox's value is bound too.

    public bool IsOverrideProperty
    {
        get { return _IsOverrideProperty; }
        set
        {
            if (_IsOverrideProperty != value)
            {
                _IsOverrideProperty = value;

                if (_IsOverrideProperty)
                    Selection = Options[0];

                base.OnPropertyChanged("IsOverrideProperty");
            }
        }
    }

    bool _IsOverrideProperty;

    public string Selection
    {
        get { return _Selection; }
        set
        {
            if (_Selection != value)
            {
                _Selection = value;

                base.OnPropertyChanged("Selection");
            }
        }
    }

    string _Selection;

    public string[] Options = new[] { "Yes", "No" };

The View:

<CheckBox IsChecked="{Binding IsOverrideProperty}" />
<ComboBox IsEnabled="{Binding IsOverrideProperty, Converter={StaticResource InverseBooleanConverter}}"
          SelectedValue="{Binding Selection}" ItemsSource="{Binding Options}">
</ComboBox>

Options could be in an observablecollection, but this probably works okay.

Upvotes: 0

Rob H
Rob H

Reputation: 1849

You are describing the logic you would like your view to have. To me, at least, that generally means that such logic belongs in the view model.

But, I would not do the bindings the way you have. I would use something like this:

<CheckBox Name="chkDefault" IsChecked="{Binding UseDefault}" />
<ComboBox IsEnabled="{Binding EnableComboBox}}" SelectedItem="{Binding SelectedComboItem}">
    <ComboBoxItem Content="No" />
    <ComboBoxItem Content="Yes" />
</ComboBox>

Then in your view model, you have UseDefault, EnableComboBox, and SelectedComboItem properties which clearly state what the behavior should be.

Also, by doing this in the view model, you are making the behavior unit testable. :)

Upvotes: 1

Related Questions