创建平面复选框样式

时间:2017-06-05 02:22:18

标签: c# wpf xaml user-interface

我正在尝试复制此图片中显示的复选框:

css-custom-checkboxes

我一直在使用此示例中的xaml作为起点:

web.archive.org - WPF CheckBox style (inspired by android)

我的要求:

  • 稳固的背景。
  • 没有边界。
  • 复选标记区域和复选标记通过控件调整大小。
  • 复选标记位于复选框区域的中心位置。

我的代码:

<Style TargetType="{x:Type local:DMStyle2CheckBox}">
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="OverridesDefaultStyle" Value="true" />
    <Setter Property="Height" Value="32" />
    <Setter Property="Width" Value="138" />
    <Setter Property="FocusVisualStyle" Value="{DynamicResource MyFocusVisualStyte}" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <BulletDecorator>
                    <BulletDecorator.Bullet>
                        <Grid Background="{x:Null}" Height="{TemplateBinding Height}" Width="{Binding RelativeSource={RelativeSource Self}, Path=Height, UpdateSourceTrigger=PropertyChanged}" 
                              MinHeight="30" MinWidth="30" ShowGridLines="False">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="4*" />
                                <ColumnDefinition Width="2*" />
                                <ColumnDefinition Width="1*" />
                                <ColumnDefinition Width="4*" />
                                <ColumnDefinition Width="1*" />
                                <ColumnDefinition Width="5*" />
                                <ColumnDefinition Width="2*" />
                                <ColumnDefinition Width="2*" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="3*" />
                                <RowDefinition Height="1*" />
                                <RowDefinition Height="1*" />
                                <RowDefinition Height="1*" />
                                <RowDefinition Height="4*" />
                                <RowDefinition Height="6*" />
                                <RowDefinition Height="1*" />
                                <RowDefinition Height="4*" />
                            </Grid.RowDefinitions>

                            <!-- Checkmark Box -->
                            <Border Name="InnerBorder" Grid.Column="1" Grid.ColumnSpan="5" Grid.Row="2" Grid.RowSpan="5" BorderThickness="1" 
                                    BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}"/>

                            <!-- Checkmark -->
                            <Path x:Name="CheckMark" Data="F1 M 9.97498,1.22334L 4.6983,9.09834L 4.52164,9.09834L 0,5.19331L 1.27664,3.52165L 4.255,6.08833L 8.33331,
                                  1.52588e-005L 9.97498,1.22334 Z" Fill="{Binding CheckMarkColor, RelativeSource={RelativeSource Mode=TemplatedParent}}" Opacity="0" 
                                  Stretch="Uniform" Grid.Column="2" Grid.ColumnSpan="4" Grid.Row="3" Grid.RowSpan="3" />

                            <Path Name="InderminateMark"  Grid.Column="3" Grid.Row="4" Data="M0,4 L1,5 5,1 4,0" Opacity="0" 
                                  Stretch="Fill" StrokeThickness="0" Fill="#808080" />
                        </Grid>
                    </BulletDecorator.Bullet>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CheckStates">
                            <VisualState x:Name="Checked">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="CheckMark" Duration="0:0:0.2" To="1" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Unchecked" >
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="CheckMark" Duration="0:0:0.2" To="0" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Indeterminate">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="InderminateMark" Duration="0:0:0.2" To="1" />
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ContentPresenter Margin="4,0,4,0" VerticalAlignment="Center" HorizontalAlignment="Left" RecognizesAccessKey="True" />
                </BulletDecorator>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter TargetName="InnerBorder" Property="BorderBrush" Value="{Binding BorderBrush, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="CheckMark" Property="Fill" Value="{StaticResource Color.Black}" />
                        <Setter TargetName="CheckMark" Property="Stroke" Value="{StaticResource Color.Black}" />
                        <Setter TargetName="InderminateMark" Property="Fill" Value="{StaticResource Color.Black}" />
                        <Setter TargetName="InnerBorder" Property="BorderBrush" Value="{StaticResource Color.Black}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

在大多数情况下,这段代码可以满足我的需求。选中标记对我来说是最大的问题。它没有居中或可调整大小,它溢出了复选标记区域。

我尝试过使用带有复选标记的网格列和行,但它变得越来越令人沮丧。理想情况下,我想摆脱网格列和行,但也没有太多运气。

我已经查看了每个关于我可以找到的wpf复选框样式的问题,并且已经搜索了其他任何在线资源,但是大多数都没有接近我想要的。我甚至尝试使用Expression Blend修改默认模板,但这也没有用。

2 个答案:

答案 0 :(得分:0)

你可以设置一种风格

<Style TargetType="CheckBox" x:Key="Flat_CheckBox">            
    <Setter Property="HorizontalAlignment" Value="Stretch"/>            
    <Setter Property="VerticalAlignment" Value="Top"/>
    <Setter Property="MinWidth" Value="60"/>
    <Setter Property="UIElement.SnapsToDevicePixels" Value="True"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
    <Setter Property="TextElement.Foreground" Value="Black"/>
    <Setter Property="FrameworkElement.FocusVisualStyle" Value="{x:Null}"/>            
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Background" Value="White" />       

    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">                    
            <Setter Property="Background" Value="LightSkyBlue" />
        </Trigger>                
    </Style.Triggers>

</Style>

答案 1 :(得分:0)

我最终根据我找到的这个模板搞清楚了:Circle-checkbox-style-in-WPF

样式模板

<Style TargetType="{x:Type local:FlatCheckBox}">
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="OverridesDefaultStyle" Value="true" />
    <Setter Property="Height" Value="32" />
    <Setter Property="Width" Value="138" />
    <Setter Property="FocusVisualStyle" Value="{DynamicResource MyFocusVisualStyte}" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <Grid Background="Transparent">
                    <Grid.RowDefinitions>
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="24" />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>

                    <Border Background="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}" 
                            BorderBrush="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" 
                            BorderThickness="{Binding BorderThickness, RelativeSource={RelativeSource TemplatedParent}}" 
                            CornerRadius="0" Width="20" Height="20" VerticalAlignment="Center">
                        <Grid>
                            <Path x:Name="CheckMark" Data="F1 M 9.97498,1.22334L 4.6983,9.09834L 4.52164,9.09834L 0,5.19331L 1.27664,3.52165L 4.255,
                                6.08833L 8.33331,1.52588e-005L 9.97498,1.22334 Z" Fill="{Binding CheckMarkColor, RelativeSource={RelativeSource Mode=TemplatedParent}}" 
                                Margin="3" Opacity="0" Stretch="Fill" />
                        </Grid>
                    </Border>
                    <ContentPresenter Grid.Column="1" x:Name="content" Margin="5,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter TargetName="CheckMark" Property="Opacity" Value="1" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

自定义依赖项属性的类

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Control_Styles.Styles
{
    public partial class FlatCheckBox : CheckBox
    {
        public static readonly DependencyProperty CheckMarkColorProperty =
            DependencyProperty.Register("CheckMarkColor", typeof(Brush), typeof(FlatCheckBox));

        public Brush CheckMarkColor
        {
            get { return (Brush)GetValue(CheckMarkColorProperty); }
            set { SetValue(CheckMarkColorProperty, value); }
        }
    }
}