views:

73

answers:

4

I wanna use a CheckBox but I want it to have the RadioButton chrome.

What's the easiest way to do this?

A: 

just try this..

<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"/>
Kishore Kumar
Doesn't seem to be working.
Shimmy
+1  A: 
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>

Andy
Actually a great idea, but I think inheriting from CheckBox is unnecessary, just have the CheckBox template as you said, bound to FindAncestor of type CheckBox and set its IsChecked value accordingly.
Shimmy
A: 

This actually works just like I desired:

<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}"/>
Shimmy
+1  A: 

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>

Code-Behind:

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
    }
}
karmicpuppet
It behaves like a regular RadioButton and only one row can be selected, **probably this is the right answer**, the question is just how can I set RadioButton groups, let me explain, I have 100 rows, from each group of rows I have to select 1 row.
Shimmy
In addition, it doesn't change the bound property, and also sometimes is rendered like a CheckBox for some reason.
Shimmy
See updated code above. Hope the example works. Come to think of it, maybe it will be easier if you just used a DataGridTemplateColumn instead.
karmicpuppet