【问题标题】:How do I make a CheckBox look like a RadioButton如何使 CheckBox 看起来像 RadioButton
【发布时间】:2011-04-27 21:10:06
【问题描述】:

我想使用 CheckBox,但我希望它具有 RadioButton chrome。

最简单的方法是什么?

【问题讨论】:

  • 您的用户会因此而爱上您。
  • 有什么理由不能使用一组像复选框一样的 RadioButtons?
  • 我想使用 DataGridCheckBoxColumn,我基本上想使用跨行 RadioButton,我知道我可以使用 DataGridTemplateColumn 设置 CellTemplate 和 CellEditingTemplate 但我认为 DataGridCheckBoxColumn 不那么冗长。
  • 你的意思是复选框应该是圆形的像 RaidoButton..?
  • 这听起来是个坏主意,因为用户会对控件的行为有一定的期望,而您正在改变它。

标签: wpf checkbox radio-button styles


【解决方案1】:
public partial class RadioCheckBox : CheckBox
{...}

RadioCheckBox.xaml:

<CheckBox
x:Class="WpfApplication1.RadioCheckBox"
...
xmlns:m="clr-namespace:WpfApplication1"
>
<CheckBox.Style>
    <Style TargetType="{x:Type m:RadioCheckBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type m:RadioCheckBox}">
                    <Grid>
                        <RadioButton
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, 
Path=IsChecked, Mode=TwoWay}"
IsHitTestVisible="False" />
                        <CheckBox
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, 
Path=IsChecked, Mode=TwoWay}" Opacity="0"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</CheckBox.Style>

【讨论】:

  • 其实是个好主意,但我认为从 CheckBox 继承是不必要的,只需将 CheckBox 模板如您所说,绑定到 CheckBox 类型的 FindAncestor 并相应地设置其 IsChecked 值。
  • 谢谢你!我将 .net (3.5) 的 m:RadioCheckBox 更改为 CheckBox
  • 可能是 .NET 4.5 的工作方式不同,但 VS 告诉我样式无效,因为“TargetType 与元素 'CheckBox' 的类型不匹配”。
  • 那么,这里发生了什么?为什么这行得通?我们是否只是覆盖了一个不可见的复选框(所以我们与复选框的交互仍然会产生复选框行为)并在其后面显示一个单选按钮(所以我们看到一个单选按钮,但得到了不可见复选框的行为?)
【解决方案2】:

这实际上就像我想要的那样工作:

<Style TargetType="{x:Type CheckBox}" x:Key="CheckBox_RadioButtonStyle">
  <Setter Property="Foreground" 
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
  <Setter Property="Background" Value="#F4F4F4"/>
  <Setter Property="BorderBrush" Value="#8E8F8F"/>
  <Setter Property="BorderThickness" Value="1"/>
  <Setter Property="FocusVisualStyle">
    <Setter.Value>
      <Style>
        <Setter Property="Control.Template">
          <Setter.Value>
            <ControlTemplate>
              <Rectangle Margin="1" SnapsToDevicePixels="True" 
Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" 
StrokeThickness="1" StrokeDashArray="1 2"/>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </Setter.Value>
  </Setter>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type CheckBox}">
        <BulletDecorator Background="Transparent" SnapsToDevicePixels="true">
          <BulletDecorator.Bullet>
            <themes:BulletChrome BorderBrush="{TemplateBinding BorderBrush}" 
Background="{TemplateBinding Background}" 
IsChecked="{TemplateBinding IsChecked}" 
RenderMouseOver="{TemplateBinding IsMouseOver}" 
RenderPressed="{TemplateBinding IsPressed}" IsRound="True"/>
          </BulletDecorator.Bullet>
          <ContentPresenter 
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" 
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </BulletDecorator>
        <ControlTemplate.Triggers>
          <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>


<!-------------------------------------->

<DataGridCheckBoxColumn x:Name="colSelected" Header="Selected" 
    ElementStyle="{StaticResource CheckBox_RadioButtonStyle}"/>

【讨论】:

  • 是的,复制粘贴这行不通。您有两件事,主题 xmlns 和您未在任何地方定义的 CheckRadioFocusVisual 静态资源。如果您使用的是表达式混合,您应该真正努力包含这些缺失的内容,或者注意您的 xaml 中包含非标准 xmlns。
【解决方案3】:

XAML:

<DataGrid x:Name="dg">
    <DataGrid.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="Test"/>
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </DataGrid.GroupStyle>
    <DataGrid.Resources>
        <Style x:Key="myStyle" TargetType="CheckBox">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="CheckBox">
                        <RadioButton IsChecked="{Binding IsChecked, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=CheckBox}}"
                                Content="{TemplateBinding Content}"
                                GroupName="{Binding MyProperty}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridCheckBoxColumn ElementStyle="{StaticResource myStyle}"
                                EditingElementStyle="{StaticResource myStyle}"
                                IsReadOnly="False"
                                Binding="{Binding Flag, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                                Header="1"/>
    </DataGrid.Columns>
</DataGrid>

代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        object[] items = new object[] {
            new MyClass() { Flag = false, MyProperty = 1 },
            new MyClass() { Flag = false, MyProperty = 1 },
            new MyClass() { Flag = false, MyProperty = 1 },
            new MyClass() { Flag = false, MyProperty = 1 },
            new MyClass() { Flag = false, MyProperty = 1 },
            new MyClass() { Flag = false, MyProperty = 2 },
            new MyClass() { Flag = true, MyProperty = 2 },
            new MyClass() { Flag = false, MyProperty = 2 },
        };

        ICollectionView cv = CollectionViewSource.GetDefaultView(items);
        cv.GroupDescriptions.Add(new PropertyGroupDescription("MyProperty"));
        this.dg.ItemsSource = cv;
    }

    public class MyClass : INotifyPropertyChanged
    {
        public int MyProperty { get; set; }

        private bool flag;
        public bool Flag
        {
            get { return this.flag; }
            set
            {
                this.flag = value;
                this.OnPropertyChanged("Flag");
            }
        }
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        #endregion
    }
}

【讨论】:

  • 它的行为就像一个普通的 RadioButton,只能选择一行,这可能是正确的答案,问题是我如何设置 RadioButton 组,让我解释一下,我有 100 行,从每组行中我必须选择 1 行。
  • 另外,它不会改变绑定的属性,有时也会因为某些原因被渲染成 CheckBox。
  • 见上面更新的代码。希望这个例子有效。想一想,如果你只使用 DataGridTemplateColumn 可能会更容易。
【解决方案4】:

试试这个..

<SolidColorBrush x:Key="CheckBoxStroke" Color="#8E8F8F"/>
    <Style x:Key="CheckRadioFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Rectangle Stroke="Black" StrokeDashArray="1 2" StrokeThickness="1" Margin="14,0,0,0" SnapsToDevicePixels="true"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
        <Style x:Key="CheckBoxStyle1" 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 SnapsToDevicePixels="true" Background="Transparent">
                        <BulletDecorator.Bullet>
                            <Microsoft_Windows_Themes:BulletChrome Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" IsChecked="{TemplateBinding IsChecked}" RenderMouseOver="{TemplateBinding IsMouseOver}" IsRound="True" RenderPressed="{TemplateBinding IsPressed}"/>
                        </BulletDecorator.Bullet>
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
                    </BulletDecorator>
                    <ControlTemplate.Triggers>
                        <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>


        <CheckBox HorizontalAlignment="Left" Margin="186,31,0,0" Style="{DynamicResource CheckBoxStyle1}" VerticalAlignment="Top" Content="CheckBox"/>
    <CheckBox Margin="310,31,246.58,0" Style="{DynamicResource CheckBoxStyle1}" VerticalAlignment="Top" Content="CheckBox" d:LayoutOverrides="Width"/>
    <CheckBox HorizontalAlignment="Right" Margin="0,31,150.58,0" Style="{DynamicResource CheckBoxStyle1}" VerticalAlignment="Top" Content="CheckBox"/>

【讨论】:

    猜你喜欢
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 2016-11-11
    • 2011-11-15
    • 2018-08-31
    • 1970-01-01
    • 2015-06-23
    相关资源
    最近更新 更多