JiKra
JiKra

Reputation: 1790

How to bind IsEnabled or IsVisible property to a method or property get?

I have some controls which I need to hide or disable based on results of some calculations. I'd like to bind IsEnabled or IsVisible property to a result of some method or property get of parent form class. Something like this:

<TabItem Name="MyTab" Header="This should be enabled when result is 2" IsEnabled="{Binding MyMethod}">
    <!--Some other stuff-->
</TabItem>

and in the code behind:

public bool MyMethod()
{
    return _valueA + _valueB == 2;
}

Can you help me find a proper way to achieve this, please?

Thx, JiKra

Upvotes: 2

Views: 4802

Answers (3)

Daniel Moore
Daniel Moore

Reputation: 1126

You need to create a new property that represents the value you are trying to achieve here. This is the entire purpose of a view model. I strongly advise you to avoid using a converter here, even though it will work. Converters should be used to handle view-only concerns, whereas this is a view state concern.

A potential view model would look like this: (I am using my BindableBase)

class AddingViewModel : BindableBase {
    private int _valueA;
    public int ValueA {
        get { return _valueA; }
        set { SetProperty(ref _valueA, value, "ValueA", OnValueAChanged); }
    }

    private void OnValueAChanged() { UpdateIsTabEnabled(); }

    private int _valueB;
    public int ValueB {
        get { return _valueB; }
        set { SetProperty(ref _valueB, value, "ValueB", OnValueBChanged); }
    }

    private void OnValueBChanged() { UpdateIsTabEnabled(); }

    private bool _isTabeEnabled;
    public bool IsTabEnabled {
        get { return _isTabEnabled; }
        private set { SetProperty(ref _isTabEnabled, value, "IsTabEnabled"); }
    }

    private void UpdateIsTabEnabled() {
        IsTabEnabled = _valueA + _valueB == 2;
    }
}

This may seem a bit verbose, but I'd like to highlight a few reasons for this:

  • As requirements change, it's easy to find and change UpdateIsTabsEnabled.
  • As ValueA and ValueB become components to other features, it's easy to add hooks into their respected OnChanged methods.
  • It's easy to bind IsTabEnabled to either IsEnabled or Visibility as desired.

Upvotes: 2

Hoang Dang
Hoang Dang

Reputation: 298

You can't bind to a method directly. It will need to be a property. With that said there are some other tricks to bind to a method shown in this question Bind to a method in WPF?.

Back to your question, what I would do is to make MyMethod a property.

public double SumAB
{
    get{ return _valueA + _valueB;}
}

Then add a converter for your binding:

<TabItem Name="MyTab" Header="This should be enabled when result is 2" IsEnabled="{Binding SumAB, Converter={StaticResource SumValueToBoolConverter}}">

Your converter code would look like this:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    double sumValue = (double)value;
    if(sumValue==2)
    {
        return true;
    }
    return false;
}

Upvotes: 1

Damascus
Damascus

Reputation: 6651

You may need to use a MultiBinding:

<TabItem Name="MyTab" Header="This should be enabled when result is 2">
  <TabItem.IsEnabled>
     <MultiBinding Converter={StaticResource MyAddConverter}>
         <Binding Path=ValueA UpdateSourceTrigger=PropertyChanged />
         <Binding Path=ValueB UpdateSourceTrigger=PropertyChanged />
     </MultiBinding>
  </TabItem.IsEnabled>
    <!--Some other stuff-->
</TabItem>

In your ViewModel, you should have the following (assuming your ViewModel implements INotifyPropertyChanged ):

public double ValueA
{
  get { return _valueA; }
  set 
  {
    _valueA = value;
    OnPropertyChanged("ValueA");
  }
}

And same for ValueB, which would allow WPF to update the Binding every time either ValueA or ValueB changes

Your converter should look like this:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
  double valueA = (double)values[0];
  double valueB = (double)values[1];
  return valueA + valueB == 2;
}

This would allow you to have one external method defined in the Converter, which will be called again every time ValueA or ValueB would change.

I'd say that's all you need =)

Upvotes: 3

Related Questions