ToggleButton组选中零或一个切换按钮

时间:2012-02-28 11:56:25

标签: c# wpf silverlight xaml

我想创建一组togglebuttons,一次检查零或一个切换按钮。

如果我使用带有togglebutton样式的radiobutton,那么至少一个togglebutton将在特定的时间处理,我想允许选择不检查togglebutton。

我为togglebutton和以下togglebuttons创建了以下样式,但由于某种原因 togglebutton在调用时不会改变缺血性质。

<Window x:Class="ClearMvvmDeltaItem.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Model="clr-namespace:ClearMvvmDeltaItem.Model" Title="MainWindow"
    Height="300"
    Width="300"
    DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
    <Model:NotConverter x:Key="NotConverter" />
    <Style TargetType="{x:Type CheckBox}">
        <Style.Triggers>
            <DataTrigger Value="False">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource NotConverter}" UpdateSourceTrigger="PropertyChanged">
                        <Binding RelativeSource="{RelativeSource Mode=Self}" Path="Name"></Binding>
                        <Binding Path="CurrentCheckedItem"></Binding>
                    </MultiBinding>
                </DataTrigger.Binding>
                <DataTrigger.Setters>
                    <Setter Property="Background" Value="Red"></Setter>
                    <Setter Property="IsChecked" Value="False"></Setter>
                </DataTrigger.Setters>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <CheckBox x:Name="first"  Content="First"
                  Command="{Binding FirstCheckedChanged}"  CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}" 
                  IsChecked="{Binding IsFirstChecked }" 
                  >

    </CheckBox>
    <CheckBox x:Name="second" Command="{Binding SecondCheckedChanged}"  CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}" 
                  IsChecked="{Binding IsSecondChecked}"
                  Content="Second" 
                  Grid.Row="1"></CheckBox>
        <CheckBox x:Name="third" Content="Third" Grid.Row="2"
                  Command="{Binding ThirdCheckedChanged}"  CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}" 
                  IsChecked="{Binding IsThirdChecked}"
                  ></CheckBox>
</Grid>

Viewmodel命令代码:

FirstCheckedChanged = new RelayCommand<string>(newName =>
        {
            if (_isFirstChecked)
                CurrentCheckedItem = newName;
        });
        SecondCheckedChanged = new RelayCommand<string>(newName =>
        {
            if (_isSecondChecked)
                CurrentCheckedItem = newName;
        });
        ThirdCheckedChanged = new RelayCommand<string>(newName =>
        {
            if (_isThirdChecked)
                CurrentCheckedItem = newName;
        });

调用datatrigger是因为我可以看到相关togglebuttons的背景颜色变为红色但是缺陷属性根本不受影响。

...谢谢

3 个答案:

答案 0 :(得分:2)

就个人而言,我会使用ListBox并设置样式,以便项目为ToggleButtons

<Style x:Key="ToggleButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <ToggleButton Content="{TemplateBinding ContentPresenter.Content}"  
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

<ListBox ItemsSource="{Binding MyOptions}"
         SelectedItem="{Binding CurrentCheckedItem}"
         Style="{StaticResource ToggleButtonListBoxStyle}"/>

这样,一次只能切换一个按钮,您可以取消选中CurrentCheckedItem,使null等于ToggleButton

它还会稍微清理您的代码,因为您不需要跟踪3个单独的RelayCommands来跟踪选择更改的时间。

作为旁注,原始代码无法正常工作,因为控件的<Tag>中设置的属性优先于DataTrigger中设置的属性。要使其工作,您必须将默认值(绑定)设置为<Style>中的设置器。您可以了解有关依赖属性优先级here的更多信息。

答案 1 :(得分:1)

编程严格的MVVM并不总是可行的......这里和那里的一点解决方法没有错。这就是我解决它的方法(不使用单选按钮或列表框)。这是从共享的togglebutton点击事件调用的,传递按钮名称:

    private void ToggleToolBarButtons(string button)
    {
        foreach (Object o in this.stkToolBar.Children)
        {
            if (o.GetType() == typeof(ToggleButton))
            {
                ToggleButton t = o as ToggleButton;
                if (t.Name != button)
                    t.IsChecked = false;
                else
                    t.IsChecked = true;
            }
        }
    }

答案 2 :(得分:0)

我相信如果您在其定义(通过该绑定完成)中对复选框的IsChecked属性应用特定值,则会忽略您尝试通过样式应用的值。

鉴于您的复选框都绑定到视图模型属性,最简单的方法是更新这些视图模型属性而不是使用触发器。因此,将FirstCheckboxChecked属性设置为true,也会将SecondCheckboxChanged和ThirdCheckboxChanged属性更新为false,并将其传递给复选框本身。