Enable/disable WPF controls using RadioButtons in XAML

10,016

Solution 1

If this is the only place where you need it, then it is ok to use your simple solution, but I think in a real application you will probably face this situation many times, so I prefer to use a general solution to make things simpler. For me, I will use a MultiConverter to calculate a result boolean from several other booleans using logical OR, like this:

<Window.Resources>
    <converters:MultiBoolOrConverter x:Key="MultiBoolOrConverter" />
</Window.Resources>
<StackPanel>
    <RadioButton GroupName="group" x:Name="enabledOne">Enabled one</RadioButton>
    <RadioButton GroupName="group" x:Name="enabledTwo">Enabled two</RadioButton>
    <RadioButton GroupName="group" x:Name="disabledOne">Disabled one</RadioButton>
    <RadioButton GroupName="group" x:Name="disabledTwo">Disabled two</RadioButton>

<TextBox Text="Test">   
    <TextBox.IsEnabled>
        <MultiBinding Converter="{StaticResource MultiBoolOrConverter}">
            <Binding Path="IsChecked" ElementName="enabledOne" />
            <Binding Path="IsChecked" ElementName="enabledTwo" />
        </MultiBinding>
    </TextBox.IsEnabled>
</TextBox>

</StackPanel>

and the used MultiBoolOrConverter.cs converter class:

using System;
using System.Linq;
using System.Globalization;
using System.Windows.Data;

namespace StackOverFlowTest.Converters
{
    class MultiBoolOrConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return values.Cast<bool>().Any(value => value);
        }

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

you also may face a situation where you need to use AND instead of OR , here is the MultiBoolAndConverter converter:

using System;
using System.Linq;
using System.Globalization;
using System.Windows.Data;

namespace StackOverFlowTest.Converters
{
    class MultiBoolAndConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return values.Cast<bool>().All(value => value);
        }

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

I wish this will help you.

UPDATE ---------------------

In my previous solution, I have used the logic:

The control should be enabled if one of the first two buttons are selected.

Instead of what you have asked literally:

The control should be disabled if one of the last two buttons are selected.

It is working of course, but if you want it exactly as you’ve described then the code will need little change to use a converter to negate IsChecked boolean value:

<Window.Resources>
<converters:MultiBoolAndConverter x:Key="MultiBoolAndConverter" />
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
</Window.Resources>
<StackPanel>
    <RadioButton GroupName="group" x:Name="enabledOne">Enabled one</RadioButton>
    <RadioButton GroupName="group" x:Name="enabledTwo">Enabled two</RadioButton>
    <RadioButton GroupName="group" x:Name="disabledOne">Disabled one</RadioButton>
    <RadioButton GroupName="group" x:Name="disabledTwo">Disabled two</RadioButton>

<TextBox Text="Test">   
    <TextBox.IsEnabled>
        <MultiBinding Converter="{StaticResource MultiBoolAndConverter}">
            <Binding Path="IsChecked" ElementName="disabledOne" Converter="{StaticResource BoolNegationConverter}" />
            <Binding Path="IsChecked" ElementName="disabledTwo" Converter="{StaticResource BoolNegationConverter}" />
        </MultiBinding>
    </TextBox.IsEnabled>
</TextBox>

</StackPanel>

BoolNegationConverter.cs :

using System;
using System.Globalization;
using System.Windows.Data;

namespace StackOverFlowTest.Converters
{
    class BoolNegationConverter: IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !(value is bool && (bool)value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !(value is bool && (bool)value);
        }
    }
}

Solution 2

The solution I came up with is:

<Window.Resources>
    <Style TargetType="TextBox" x:Key="enableDisableStyle">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsChecked, ElementName=disabledOne}" Value="True">
                <Setter Property="IsEnabled" Value="False" />
            </DataTrigger>
            <DataTrigger Binding="{Binding IsChecked, ElementName=disabledTwo}" Value="True">
                <Setter Property="IsEnabled" Value="False" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<StackPanel>
    <RadioButton GroupName="group" x:Name="enabledOne">Enabled one</RadioButton>
    <RadioButton GroupName="group" x:Name="enabledTwo">Enabled two</RadioButton>
    <RadioButton GroupName="group" x:Name="disabledOne">Disabled one</RadioButton>
    <RadioButton GroupName="group" x:Name="disabledTwo">Disabled two</RadioButton>

    <TextBox Text="Test" Style="{StaticResource enableDisableStyle}" />
</StackPanel>

I will not mark my own answer as accepted until I'm convinced it is the best solution.

Share:
10,016
FishySwede
Author by

FishySwede

Swedish software developer with a masters degree and a couple of years of experience.

Updated on June 07, 2022

Comments

  • FishySwede
    FishySwede almost 2 years

    My problem is that I have a set of RadioButtons and I want to disable another control depending on which RadioButton is selected.

    It is important that I can disable the control if of one of several RadioButton is selected.

    E.g.

    [] Enabled one
    [] Enabled two
    [] Disabled one
    [] Disabled two
    

    The control should be disabled if one of the last two buttons are selected.

    Note

    I intend to answer this question myself (Which should be ok according to this link) but I will accept other answers if they solve the problem in a better way.

  • Patrick
    Patrick about 10 years
    This would be my preferred solution as well. Using the multivalueconverter allows you to expand this behavior to an unlimited number of booleans
  • FishySwede
    FishySwede about 10 years
    This is actually a much neater solution than mine. As you say it is useable in more situations. Thanks for the input!