在XAML中使用单选按钮启用/禁用WPF控件

4
我的问题是我有一组单选按钮,我想根据选中的单选按钮禁用另一个控件。
关键是如果选中了“多个”单选按钮之一,我仍能够禁用控件。
例如:
[] Enabled one
[] Enabled two
[] Disabled one
[] Disabled two

如果选择了最后两个按钮中的一个,则应将控件禁用。

注意

我打算自己回答这个问题(根据这个链接是可以接受的),但如果其他答案以更好的方式解决了问题,我也会接受这些答案。

2个回答

6

如果这只是你需要的地方,那么使用简单的解决方案就可以了,但我认为在真实应用中,你可能会多次遇到这种情况,所以我更喜欢使用通用解决方案来使事情变得更简单。 对于我来说,我会使用 MultiConverter 来计算从几个其他布尔值使用逻辑 OR 得出的结果布尔值,就像这样:

<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>

使用的是 MultiBoolOrConverter.cs 转换器类:

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();
        }
    }
}

有时您可能需要使用AND而不是OR,这时可以使用MultiBoolAndConverter转换器:

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();
        }
    }
}

我希望这能帮到你。
更新 ---------------------
在我的以前的解决方案中,我使用了以下逻辑:
如果选择了前两个按钮之一,则应启用控件。
而不是您字面上所要求的:
如果选择了最后两个按钮之一,则应禁用控件。
当然,它确实有效,但如果您想要完全按照您所描述的来做,那么代码将需要进行一些更改,使用转换器来否定 IsChecked 布尔值。
<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);
        }
    }
}

2
这也是我的首选解决方案。使用多值转换器可以将此行为扩展到无限数量的布尔值。 - Patrick
这实际上是比我的解决方案更整洁的解决方案。正如你所说,它适用于更多的情况。感谢您的贡献! - FishySwede

2
我想到的解决方案是:
<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>

除非我确信这是最佳解决方案,否则我不会将自己的答案标记为被接受的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接