WPF中CheckBox的自定义鼠标点击区域

时间:2014-05-07 22:02:59

标签: c# wpf checkbox wpf-style

我为我的复选框设置了一个自定义样式,它看起来像这样(未选中状态):

Image of an expander with a border around it and dog-ear signifying a checkbox

当复选框被"选中"时,它应如下所示:

Image of an expander with a border around it and dog-ear highlighted green.

我想要发生的是用户应该只能通过点击右上角的复选标记来切换它。现在,复选框将切换用户点击框内部而不是扩展器内部的任何位置。

我有没有办法设置鼠标点击区域以便将复选框切换到右上角的复选标记周围?

这是我的代码:

<SolidColorBrush x:Key="SelectedCheckboxColor" Color="Green"/>
<SolidColorBrush x:Key="UnselectedCheckboxColor" Color="Gray"/>
<Style x:Key="SelectBoxCheckBoxStyle" TargetType="{x:Type CheckBox}">
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <Border x:Name="border" BorderThickness="2" BorderBrush="#FF666666">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <ContentPresenter Grid.Column="0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        <Image x:Name="image" Width="24" Height="24" Grid.Column="1" VerticalAlignment="Top" Source="Resources/checkbox-dogear-unchecked.png"/>
                    </Grid>

                    <!--<BulletDecorator Background="Transparent" SnapsToDevicePixels="true">
                        <BulletDecorator.Bullet>
                            <Themes:BulletChrome BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" IsChecked="{TemplateBinding IsChecked}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}"/>
                        </BulletDecorator.Bullet>
                    </BulletDecorator>-->
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasContent" Value="true">
                        <Setter Property="Padding" Value="4,0,0,0"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter Property="Source" TargetName="image" Value="Resources/checkbox-dogear-checked.png"/>
                        <Setter Property="BorderBrush" TargetName="border" Value="#FF00D212"/>
                    </Trigger>
                    <Trigger Property="IsMouseCaptureWithin" Value="True">
                        <Setter Property="BorderBrush" TargetName="border" Value="#FFA200FF"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

2 个答案:

答案 0 :(得分:2)

我认为雷切尔的答案是正确的方法,因为它不是我之前尝过的东西,我以为我有一个裂缝并且敲了一个快速尝试(批评欢迎)。

我没有你正在使用的图像,所以我使用PolygonPath来代替复选框 - 所以风格变成了这样:

        <SolidColorBrush x:Key="SelectedCheckboxColor" Color="#FF00D212"/>
        <SolidColorBrush x:Key="UnselectedCheckboxColor" Color="Gray"/>
        <Style TargetType="{x:Type CheckBox}">
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type CheckBox}">
                        <Border x:Name="border" BorderThickness="2" BorderBrush="{StaticResource ResourceKey=UnselectedCheckboxColor}">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <ContentPresenter Grid.Column="0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>

                                <!-- Tickbox Mockup -->
                                <Polygon x:Name="checkPoly" Points="0,0 24,24 24,0 0,0" Stroke="Purple" StrokeThickness="0" Width="24" Height="24" 
                                         VerticalAlignment="Top" HorizontalAlignment="Right" Fill="{StaticResource ResourceKey=UnselectedCheckboxColor}" />
                                <Path Stroke="White" Data="M 6,6 L 9, 9 L 16,2" StrokeThickness="2" Margin="0, 1, 1, 0"
                                      VerticalAlignment="Top" HorizontalAlignment="Right" />
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="HasContent" Value="true">
                                <Setter Property="Padding" Value="4,0,0,0"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Fill" TargetName="checkPoly" Value="{StaticResource ResourceKey=SelectedCheckboxColor}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource ResourceKey=SelectedCheckboxColor}" />
                            </Trigger>
                            <Trigger Property="IsMouseCaptureWithin" Value="True">
                                <Setter Property="BorderBrush" TargetName="border" Value="#FFA200FF"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

然后在Expander内托管了ContentControl(包含一些测试内容):

<ContentControl Width="100" Height="100">
        <Grid>
            <!-- Make sure the Checkbox is the foremost element -->
            <CheckBox Grid.ZIndex="99" />
            <Expander Header="Test" >
                <StackPanel>
                    <TextBlock Text="Test" />
                    <TextBlock Text="Test" />
                    <TextBlock Text="Test" />
                </StackPanel>
            </Expander>
        </Grid>
</ContentControl>

看起来像这样:

enter image description here

根据您打算使用Control的位置,您的里程可能会有所不同。需要注意的一点是,如果单击边框,复选框仍会切换 - 如果出现问题,可以从CheckBox中删除边框宽度,将其粘贴在ContentControl上,然后使用一些绑定来挂接Border的{​​{1}}画笔颜色。

答案 1 :(得分:-1)

也许您可以为复选框设置on_click侦听器,然后检查鼠标位置,如果鼠标位于正确的相对范围内,则只更改复选框状态?