如何为RadioButton的ControlTemplate添加GroupName

时间:2016-11-21 15:20:28

标签: c# wpf mvvm

我为RadioButton定义了一个Style,它包含一个由BulletDecorator,VisualStateManager和Triggers组成的ControlTemplate。我目前在XAML代码中的RadioButton上定义了GroupName。

运行代码时选择单选按钮并不相互排斥。

我已阅读其他帖子说该问题是ControlTemplate中定义的第二个RadioButton。我没有定义第二个RadioButton。

以下是所选按钮的图片,它们应互相排斥:

enter image description here

这是我的风格:

 <Style x:Key="RadioButtonStyle" TargetType="RadioButton">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Height" Value="15"/>
    <Setter Property="Margin" Value="5"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="RadioButton">
                <BulletDecorator>
                    <BulletDecorator.Bullet>
                        <Grid Height="{TemplateBinding Height}" Width="{Binding RelativeSource={RelativeSource Self}, Path=Height, UpdateSourceTrigger=PropertyChanged}" MinHeight="15" MinWidth="15">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="3*"/>
                                <ColumnDefinition Width="1*"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="1*"/>
                                <RowDefinition Height="3*"/>
                                <RowDefinition Height="1*"/>
                            </Grid.RowDefinitions>
                            <Ellipse Name="EllipseMain"
                                     Grid.Column="0" Grid.ColumnSpan="3"
                                     Grid.Row="0" Grid.RowSpan="3"
                                     Fill="Transparent"
                                     StrokeThickness="{TemplateBinding BorderThickness}"
                                     Stroke="DimGray"/>
                            <Ellipse Name="CheckMark"
                                     Grid.Column="1"
                                     Grid.Row="1"
                                     Opacity="0"
                                     Fill="#029cc7"/>
                        </Grid>
                    </BulletDecorator.Bullet> 
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="CheckMark" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" To="LightGray" Duration="0:0:0.3"/>
                                    <ColorAnimation Storyboard.TargetName="CheckMain" Storyboard.TargetProperty="(Ellipse.Stroke).(SolidColorBrush.Color)" To="LightGray" Duration="0:0:0.3"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="CheckStates">
                            <VisualState x:Name="Checked">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="CheckMark" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="UnChecked">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="CheckMark" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.3"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Indeterminate">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="CheckMark" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3"/>
                                    <ColorAnimation Storyboard.TargetName="CheckMain" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" To="Gray" Duration="0:0:0.3"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ContentPresenter Margin="4,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" RecognizesAccessKey="True"/>
                </BulletDecorator>
                <ControlTemplate.Triggers>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="EllipseMain" Property="Fill" Value="#55029cc7"/>
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter TargetName="EllipseMain" Property="Stroke" Value="#88029cc7"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这是XAML:

 <RadioButton Grid.Row="0" Grid.Column="0" Content="Normal" Foreground="WhiteSmoke" Style="{StaticResource RadioButtonStyle}"  GroupName="gpHeadingMode" Margin="0,0,0,0"/>
 <RadioButton Grid.Row="1" Grid.Column="0" Content="Weather Vane" Foreground="WhiteSmoke" Style="{StaticResource RadioButtonStyle}"  GroupName="gpHeadingMode" Margin="0,0,0,0"/>

尝试将其作为解决方法(在XAML中):

<RadioButton Grid.Row="0" Grid.Column="0" x:Name="Normal" Content="Normal" Foreground="WhiteSmoke" GroupName="gpHeadingMode1"
                    Style="{StaticResource RadioButtonStyle}"
                     IsChecked="{Binding HeadingModeChecked, ElementName=HeadingDialog, Converter={StaticResource RbCheckedConverter}, ConverterParameter=Normal, FallbackValue=False}" 
                     Click="RbHeadingMode_Click"/>
<RadioButton Grid.Row="1" Grid.Column="0" x:Name="WeatherVane" Content="Weather Vane" Foreground="WhiteSmoke" GroupName="gpHeadingMode2" 
                    Style="{StaticResource RadioButtonStyle}"
                     IsChecked="{Binding HeadingModeChecked, ElementName=HeadingDialog, Converter={StaticResource RbCheckedConverter}, ConverterParameter=WeatherVane, FallbackValue=False}" 
                     Click="RbHeadingMode_Click"/>

在RbHeadingMode_Click中,依赖对象HeadingModeChecked设置为RadioButton.Name的值。如果我删除“样式”,转换器将触发并执行切换IsClicked值的工作。

不幸的是,使用Style,转换器不会触发。

现在问题变成了,如何将XAML中的IsChecked属性绑定到样式?

注意:实际上,转换器会在指定Style的情况下触发,但在XAML中对IsChecked的更改对RadioButton没有影响。

1 个答案:

答案 0 :(得分:0)

必须从Style中删除以下代码才能正常工作:

<VisualStateGroup x:Name="CheckStates">
    <VisualState x:Name="Checked">
       <Storyboard>
           <DoubleAnimation Storyboard.TargetName="CheckMark" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3"/>
       </Storyboard>
    </VisualState>
    <VisualState x:Name="UnChecked">
       <Storyboard>
           <DoubleAnimation Storyboard.TargetName="CheckMark" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.3"/>
       </Storyboard>
     </VisualState>
     <VisualState x:Name="Indeterminate">
       <Storyboard>
            <DoubleAnimation Storyboard.TargetName="CheckMark" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3"/>
            <ColorAnimation Storyboard.TargetName="CheckMain" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" To="Gray" Duration="0:0:0.3"/>
        </Storyboard>
     </VisualState>
</VisualStateGroup>

注意:转换器不仅可以处理IsChecked属性,而且现在我可以删除该转换器,只需使用Groupname来实现无线电按钮的互斥!