无法使用自定义ControlTemplate在单选按钮上绑定IsChecked

时间:2011-03-21 18:13:44

标签: c# wpf templatebinding

我一直在使用带有ToggleButton的自定义RadioButton控件作为控件模板。这就是xaml的样子:

    <RadioButton.Template>
        <ControlTemplate>
            <ToggleButton x:Name="tb" IsChecked="{Binding IsChecked, Mode=TwoWay, 
                                RelativeSource={RelativeSource TemplatedParent}}" 
                                      Content="{TemplateBinding RadioButton.Content}"
                          PreviewMouseDown="tb_PreviewMouseDown">
            </ToggleButton>
        </ControlTemplate>
    </RadioButton.Template>

它一直运行良好,除非我尝试以编程方式设置按钮的IsChecked属性,或者使用它进行绑定。然后应该检查的按钮在视觉上没有响应 - 它似乎没有按下,并且不会出现Aero鼠标悬停效果。 Clicked事件处理程序仍然有效,当我检查它们的值时,RadioButton和ControlTemplate的切换按钮的IsChecked属性都是真的。艾米,我的绑定有问题吗?有什么想法吗?

以下是我在应用程序中使用它的示例:

<local:RadioToggleButton Content="1Hr" GroupName="Interval" x:Name="oneHrBtn" 
IsChecked="{BindingPath=oneHrBtnIsChecked, Mode=TwoWay}" Margin="2 5 3 5" 
IsEnabled="{Binding Path=oneHrBtnIsEnabled, Mode=TwoWay}"/>

3 个答案:

答案 0 :(得分:1)

你所拥有的是非常奇怪的。 RadioButton类派生自ToggleButton。因此,您可以有效地将按钮放在按钮中。你只是想让RadioButton看起来像ToggleButton吗?如果是这样,为什么不直接使用ToggleButton?

如果你想使RadioButton看起来像ToggleButton所以你可以使用GroupName功能,那么你必须复制ToggleButton控件模板并使用它(不在控件模板中嵌入ToggleButton)。

您可以从here获取默认模板。然后搜索ToggleButton样式并复制它的ControlTemplate。

编辑:

以下示例说明了如何完成此操作。您只需要添加对PresentationFramework.Aero的引用。

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>

        <LinearGradientBrush x:Key="ButtonNormalBackground" StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
                <GradientStop Color="#F3F3F3" Offset="0" />
                <GradientStop Color="#EBEBEB" Offset="0.5" />
                <GradientStop Color="#DDDDDD" Offset="0.5" />
                <GradientStop Color="#CDCDCD" Offset="1" />
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
        <SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070" />

            <Style x:Key="ButtonFocusVisual">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Rectangle Margin="2" StrokeThickness="1" Stroke="Black" StrokeDashArray="1 2" SnapsToDevicePixels="true" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style x:Key="{x:Type RadioButton}" TargetType="{x:Type RadioButton}">
            <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
            <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}" />
            <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="Padding" Value="1" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type RadioButton}">
                        <theme:ButtonChrome Name="Chrome" Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding Button.IsDefaulted}"
                                RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}"
                                SnapsToDevicePixels="true">
                            <ContentPresenter Margin="{TemplateBinding Padding}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </theme:ButtonChrome>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsKeyboardFocused" Value="true">
                                <Setter TargetName="Chrome" Property="RenderDefaulted" Value="true" />
                            </Trigger>
                            <Trigger Property="ToggleButton.IsChecked" Value="true">
                                <Setter TargetName="Chrome" Property="RenderPressed" Value="true" />
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="#ADADAD" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <StackPanel>
        <RadioButton GroupName="TestGroup">Option 1</RadioButton>
        <RadioButton GroupName="TestGroup">Option 2</RadioButton>
    </StackPanel>
</Window>

答案 1 :(得分:1)

如果你想要的只是一个看起来像RadioButton的{​​{1}},你实际上可以通过其类型隐式地将ToggleButton的样式称为静态资源:

ToggleButton

这似乎有效,因为RadioButton来自ToggleButton。因此,您无法使用<RadioButton Style="{StaticResource {x:Type ToggleButton}}" />

我无法追踪使用{StaticResource {x:Type ComboBox}}作为x:Type资源的任何文档;我有兴趣看到它,如果有人知道在哪里看。

答案 2 :(得分:0)

因此我的自定义RadioToggleButton控件的问题是由非常奇怪的事情引起的。我将在下面描述我的解决方案,不是因为我希望其他人遇到这个特定的问题,而只是作为一个似乎与问题无关的解决方案的例子。

包含按钮组的GroupBox的IsEnabled属性存在绑定。此绑定似乎工作正常,在适当时启用和禁用所有内部控件。但是一旦我删除了这个绑定,我上面描述的问题就消失了。这不是理想的,但我认为我在这个问题上花了太多时间,所以我将各个控件的IsEnabled属性绑定到GroupBox绑定的相同属性,现在至少我有行为我想要的。