Styling the indeterminate state of a WPF checkbox

后端 未结 9 1928
情话喂你
情话喂你 2021-02-04 07:30

I want to style the indeterminate state of a WPF checkbox. We have a treeview control with checkboxes, and we want the indeterminate state to represent that some descendants are

相关标签:
9条回答
  • 2021-02-04 07:35

    The below code is a sample check box with three state.

    <Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <!-- Focus Style -->
    
        <SolidColorBrush x:Key="InputBackgroundFocused" Color="Orange"></SolidColorBrush>
    
        <Style x:Key="CheckBoxFocusVisualStyle">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Border CornerRadius="2" Margin="0,0,4,3" BorderThickness="2" BorderBrush="{StaticResource InputBackgroundFocused}" Background="Transparent"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <!-- Fill Brushes -->
    
        <LinearGradientBrush x:Key="NormalBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FFF" Offset="0.0"/>
                    <GradientStop Color="#CCC" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="HorizontalNormalBrush" StartPoint="0,0" EndPoint="1,0">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FFF" Offset="0.0"/>
                    <GradientStop Color="#CCC" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="LightBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FFF" Offset="0.0"/>
                    <GradientStop Color="#EEE" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="HorizontalLightBrush" StartPoint="0,0" EndPoint="1,0">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FFF" Offset="0.0"/>
                    <GradientStop Color="#EEE" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="DarkBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FFF" Offset="0.0"/>
                    <GradientStop Color="#AAA" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="PressedBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#BBB" Offset="0.0"/>
                    <GradientStop Color="#EEE" Offset="0.1"/>
                    <GradientStop Color="#EEE" Offset="0.9"/>
                    <GradientStop Color="#FFF" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
    
        <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
    
        <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
    
        <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
    
        <!-- Border Brushes -->
    
        <LinearGradientBrush x:Key="NormalBorderBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#CCC" Offset="0.0"/>
                    <GradientStop Color="#444" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="HorizontalNormalBorderBrush" StartPoint="0,0" EndPoint="1,0">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#CCC" Offset="0.0"/>
                    <GradientStop Color="#444" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="DefaultedBorderBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#777" Offset="0.0"/>
                    <GradientStop Color="#000" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="PressedBorderBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#444" Offset="0.0"/>
                    <GradientStop Color="#888" Offset="1.0"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" />
    
        <SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />
    
        <SolidColorBrush x:Key="LightBorderBrush" Color="#AAA" />
    
        <!-- Miscellaneous Brushes -->
        <SolidColorBrush x:Key="GlyphBrush" Color="#444" />
    
        <SolidColorBrush x:Key="LightColorBrush" Color="#DDD" />
        <Style TargetType="{x:Type CheckBox}">
            <Setter Property="SnapsToDevicePixels" Value="true"/>
            <Setter Property="OverridesDefaultStyle" Value="true"/>
            <Setter Property="FocusVisualStyle" Value="{DynamicResource CheckBoxFocusVisualStyle}" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="CheckBox">
                        <BulletDecorator Background="Transparent">
                            <BulletDecorator.Bullet>
                                <Border x:Name="Border"  
                                  Width="17" 
                                  Height="17" 
                                  CornerRadius="2" 
                                  Background="{StaticResource NormalBrush}"
                                  BorderThickness="1"
                                  BorderBrush="{StaticResource NormalBorderBrush}">
                                    <Path 
                                    Width="11" Height="11" 
                                    x:Name="CheckMark"
                                    SnapsToDevicePixels="False" 
                                    Stroke="{StaticResource GlyphBrush}"
                                    StrokeThickness="2"
                                    Data="M 2,4 C 2,4 3,5 5,13 C 5,13 5,3 12,0" />
                                </Border>
                            </BulletDecorator.Bullet>
                            <ContentPresenter Margin="4,0,0,0"
                                VerticalAlignment="Center"
                                HorizontalAlignment="Left"
                                RecognizesAccessKey="True"/>
                        </BulletDecorator>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="false">
                                <Setter TargetName="CheckMark" Property="Visibility" Value="Collapsed"/>
                            </Trigger>
                            <Trigger Property="IsChecked" Value="{x:Null}">
                                <Setter TargetName="CheckMark" Property="Data" Value="M 0 7 L 7 0" />
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource DarkBrush}" />
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource PressedBrush}" />
                                <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource PressedBorderBrush}" />
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />
                                <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
                                <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
    
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <StackPanel>
        <CheckBox>Hello</CheckBox>
            <CheckBox IsThreeState="True">asdfsdaf</CheckBox>
            </StackPanel>
    </Grid>
    

    The best software to modify the existing look and feel of the controls is Expression Blend. If you want to change the existing look and feel and you have to modify the Control Template of the control.

    0 讨论(0)
  • 2021-02-04 07:39

    Try this (modified from the article that publicgk linked to)

    <Window x:Class="WpfApplication1.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>
        <Style x:Key="CheckRadioFocusVisual">
          <Setter Property="Control.Template">
            <Setter.Value>
              <ControlTemplate>
                <Rectangle Margin="14,0,0,0"
                           StrokeThickness="1"
                           Stroke="Black"
                           StrokeDashArray="1 2"
                           SnapsToDevicePixels="true"/>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
    
        <Style x:Key="EmptyCheckBoxFocusVisual">
          <Setter Property="Control.Template">
            <Setter.Value>
              <ControlTemplate>
                <Rectangle Margin="1"
                           StrokeThickness="1"
                           Stroke="Black"
                           StrokeDashArray="1 2"
                           SnapsToDevicePixels="true"/>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
    
        <SolidColorBrush x:Key="CheckBoxFillNormal"
                         Color="#F4F4F4"/>
        <SolidColorBrush x:Key="CheckBoxStroke"
                         Color="#8E8F8F"/>
        <Style x:Key="{x:Type CheckBox}"
             TargetType="{x:Type CheckBox}">
          <Setter Property="Foreground"
                Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
          <Setter Property="Background"
                Value="{StaticResource CheckBoxFillNormal}"/>
          <Setter Property="BorderBrush"
                Value="{StaticResource CheckBoxStroke}"/>
          <Setter Property="BorderThickness"
                Value="1"/>
          <Setter Property="FocusVisualStyle"
                Value="{StaticResource EmptyCheckBoxFocusVisual}"/>
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type CheckBox}">
                <BulletDecorator Background="Transparent" 
                                 SnapsToDevicePixels="true">
                  <BulletDecorator.Bullet>
                    <theme:BulletChrome Background="{TemplateBinding Background}"
                                        BorderBrush="{TemplateBinding BorderBrush}"
                                        RenderMouseOver="{TemplateBinding IsMouseOver}"
                                        RenderPressed="{TemplateBinding IsPressed}"
                                        IsChecked="{TemplateBinding IsChecked}"/>
                  </BulletDecorator.Bullet>
                  <ContentPresenter Margin="{TemplateBinding Padding}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    RecognizesAccessKey="True"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </BulletDecorator>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsChecked" 
                           Value="{x:Null}">
                    <!-- TODO: Do Stuff Here -->
                  </Trigger>
                  <Trigger Property="HasContent"
                           Value="true">
                    <Setter Property="FocusVisualStyle"
                            Value="{StaticResource CheckRadioFocusVisual}"/>
                    <Setter Property="Padding"
                            Value="4,0,0,0"/>
                  </Trigger>
                  <Trigger Property="IsEnabled"
                           Value="false">
                    <Setter Property="Foreground"
                            Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                  </Trigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </Window.Resources>
      <StackPanel>
        <CheckBox IsChecked="True" Content="Checked"/>
        <CheckBox IsChecked="{x:Null}" Content="Unknown"/>
        <CheckBox IsChecked="False" Content="Not Checked"/>
      </StackPanel>
    </Window>
    
    0 讨论(0)
  • 2021-02-04 07:39

    Another option may be to style a toggle button as it has multiple states as well. In past projects I have created custom toggle buttons with multiple states that look and function as chekcboxes. I did use blend to make the changes but in using a tggle button as the base I was able to create a more customized look and feel for the various states of the button/chekcbox. Using a toggle button can bypass a lot of the chrome related issues that are tightly boud to a standard chekcbox control.

    0 讨论(0)
  • 2021-02-04 07:46

    You can set the checkbox's IsThreeState property to true.

    This, however, allows toggling the checkbox's value to null.
    If that is undesired, you can instead add to your CheckBox's Template a trigger for the null value, just like Greg Bacchus shows in his answer:

    <ControlTemplate.Triggers>
        <Trigger Property="IsChecked" Value="{x:Null}">
            <!-- TODO: Do Stuff Here -->
        </Trigger>
    </ControlTemplate.Triggers>
    
    0 讨论(0)
  • 2021-02-04 07:49

    You can use CheckBox styling from the classic theme located at:

    • C:\Program Files (x86)\Microsoft Expression\Blend 4\SystemThemes\Wpf\classic.xaml

    This implementation has a Path representing the checkbox mark called CheckMarkPath. I simply replaced this Path with a filled Rectangle to get these results:

    Checkboxes

    0 讨论(0)
  • 2021-02-04 07:51

    Have you thought about using SimpleStyles as the base for control?

    ExpressionSimpleStyles

    By selecting this control from the Assets panel, Expression Blend will place a new resource dictonary in your project that you can use to modify the style as you please. Might be a better starting point than trying to hack into the Chrome for the standard checkbox.

    0 讨论(0)
提交回复
热议问题