开发者

How does one create two mutually excusive checkboxes in WPF (but allow them both to be unchecked)

I've been trying to make it impossible to have two checkboxes checked at the same time in WPF but still allowing them both to be unchecked.

Does anyone know how I can achieve this?

This is what I have at the moment. Unfortunately this has the behaviour that both triggers are called when a checkbox is checked.

<Window.Resources>
    <Style x:Key="style1" TargetType="{x:Type CheckBox}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ElementName=checkBox2, Path=IsChecked}" Value="True">
                <Setter Property="CheckBox.IsChecked" Value="False"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="style2" TargetType="{x:Type CheckBox}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ElementName=checkBox1, Path=IsChecked}" Value="True">
                <Setter Property="CheckBox.IsChecked" Value="False"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

        <Grid>
          开发者_C百科  <CheckBox Style="{StaticResource style1}" Name="checkBox1" Content="Check Box 1" />
            <CheckBox Style="{StaticResource style2}" Name="checkBox2" Content="Check Box 2" />
        </Grid>


Leverage ListBox's exclusive single SelectionMode for this...

 <ListBox x:name="MyListBox"
          xmlns:System="clr-namespace:System;assembly=mscorlib"
          SelectionMode="Single">
        <ListBox.Resources>
            <Style TargetType="{x:Type ListBoxItem}">
                <Style.Resources>
                    <SolidColorBrush
                       x:Key="{x:Static SystemColors.HighlightBrushKey}"
                       Color="Transparent"/>
                </Style.Resources>
            </Style>
        </ListBox.Resources>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel IsItemsHost="True"
                            Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox
                   Content="{Binding}"
                   IsChecked="{Binding
                                 IsSelected,
                                 RelativeSource={RelativeSource
                                    AncestorType={x:Type ListBoxItem}},
                                 Mode=TwoWay}"
                   Margin="5"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemsSource>
            <x:Array Type="{x:Type System:String}">
                <System:String>My Checkbox 1</System:String>
                <System:String>My Checkbox 2</System:String>
            </x:Array>
        </ListBox.ItemsSource>
    </ListBox>

So for "n" mututally exclusive checkboxes simply add those many number of strings to the x:Array above. The above functionality works great fo radioboxes too.

As you have said, the checkboxes will allow none or only one checked. And then to access which one is actually checked, MyListBox.SelectedIndex will help you.


Instead of using a Checkbox, restyle a RadioButton instead.

    <Style TargetType="{x:Type RadioButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RadioButton}">                    
                <CheckBox x:Name="Checkbox" IsChecked="{Binding Path=IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWayToSource}"
                          Content="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
                <ControlTemplate.Triggers>                          
                    <DataTrigger Binding="{Binding Path=IsChecked, RelativeSource={RelativeSource TemplatedParent}}" Value="{x:Null}">
                        <Setter TargetName="Checkbox" Property="IsChecked" Value="False"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=IsChecked, RelativeSource={RelativeSource TemplatedParent}}" Value="False">
                        <Setter TargetName="Checkbox" Property="IsChecked" Value="False"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=IsChecked, RelativeSource={RelativeSource TemplatedParent}}" Value="True">
                        <Setter TargetName="Checkbox" Property="IsChecked" Value="True"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

To allow both to be unchecked, create a trigger that handles the {x:Null} value. I have implement such a trigger, however have not tested if it would work (let me know if you have trouble with it).


You could achieve the desired effect with two lines of C# code:

CheckBox1.Checked += (sender, e) => { CheckBox2.IsChecked = false; };
CheckBox2.Checked += (sender, e) => { CheckBox1.IsChecked = false; };
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜