0

So with a lot of looking around I am hoping to make a GroupBox that acts like a Radio button. The header section would act as the bullet. I took some code from this question

Styling a GroupBox

that is how I want it to look. But I want to have it as a Radio button. So I put in this code (mind you I've only been doing WPF for a week or 2 now)

    <Style TargetType="{x:Type RadioButton}" >
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RadioButton}">
                    <BulletDecorator>
                        <BulletDecorator.Bullet>
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Border x:Name="SelectedBorder"
                                        Grid.Row="0"
                                        Margin="4"
                                        BorderBrush="Black"
                                        BorderThickness="1"
                                        Background="#25A0DA">
                                    <Label x:Name="SelectedLabel" Foreground="Wheat">
                                        <ContentPresenter Margin="4" />
                                    </Label>
                                </Border>
                                <Border>

                                </Border>
                            </Grid>
                        </BulletDecorator.Bullet>
                    </BulletDecorator>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="true">
                            <Setter TargetName="SelectedBorder" Property="Background" Value="PaleGreen"/>
                            <Setter TargetName="SelectedLabel"
                                    Property="Foreground"
                                    Value="Black" />
                        </Trigger>

                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

I have a feeling that I can add a label to the second row of my grid, but then I don't know how to access it. I have that template in a test project in the Window.Resources section (I plan on moving it to a resource dictionary in my main project) the xaml for my window is this

<Grid>
    <GroupBox Name="grpDoor" Margin ="8"  Grid.Row="0" Grid.Column="0">
        <GroupBox.Header>
            WPF RadioButton Template
        </GroupBox.Header>
        <StackPanel Margin ="8">
            <RadioButton   FontSize="15" Content="Dhaka" Margin="4" IsChecked="False"/>
            <RadioButton   FontSize="15" Content="Munshiganj" Margin="4" IsChecked="True" />
            <RadioButton   FontSize="15" Content="Gazipur" Margin="4" IsChecked="False" />
        </StackPanel>
    </GroupBox>
</Grid>

I then hoping for something like this (not sure how I'd do it yet though)

<Grid>
    <GroupBox Name="grpDoor" Margin ="8"  Grid.Row="0" Grid.Column="0">
        <GroupBox.Header>
            WPF RadioButton Template
        </GroupBox.Header>
        <StackPanel Margin ="8">
            <RadioButton   FontSize="15"
                           Content="Dhaka"
                           Margin="4"
                           IsChecked="False">
                <RadioButton.Description>
                    This is a description that would show under my Header
                </RadioButton.Description>
            </RadioButton>
            <RadioButton   FontSize="15"
                           Content="Munshiganj"
                           Margin="4"
                           IsChecked="True">
                <RadioButton.Description>
                    This is a description that would show under my Header
                </RadioButton.Description>
            </RadioButton>
            <RadioButton   FontSize="15"
                           Content="Gazipur"
                           Margin="4"
                           IsChecked="False">
                <RadioButton.Description>
                    This is a description that would show under my Header
                </RadioButton.Description>
            </RadioButton>
        </StackPanel>
    </GroupBox>
</Grid>
Community
  • 1
  • 1
Robert Snyder
  • 2,399
  • 4
  • 33
  • 65

2 Answers2

1

Based on your clarification, here is a very simple example with a RadioButton that looks like a GroupBox.

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:SimpleViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:SimpleOption}">
            <RadioButton GroupName="choice" IsChecked="{Binding Path=IsSelected, Mode=TwoWay}">
                <RadioButton.Template>
                    <ControlTemplate TargetType="{x:Type RadioButton}">
                        <GroupBox x:Name="OptionBox" Header="{Binding Path=DisplayName, Mode=OneWay}">
                            <TextBlock Text="{Binding Path=Description, Mode=OneWay}"/>
                        </GroupBox>
                        <ControlTemplate.Triggers>
                            <DataTrigger Binding="{Binding Path=IsSelected, Mode=OneWay}" Value="True">
                                <Setter TargetName="OptionBox" Property="Background" Value="Blue"/>
                            </DataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </RadioButton.Template>
            </RadioButton>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Path=Options, Mode=OneWay}"/>
    </Grid>
</Window>

public class SimpleViewModel
{

    public SimpleViewModel()
    {
        Options = new ObservableCollection<SimpleOption>();
        var _with1 = Options;
        _with1.Add(new SimpleOption {
            DisplayName = "Dhaka",
            Description = "This is a description for Dhaka."
        });
        _with1.Add(new SimpleOption {
            DisplayName = "Munshiganj",
            Description = "This is a description for Munshiganj.",
            IsSelected = true
        });
        _with1.Add(new SimpleOption {
            DisplayName = "Gazipur",
            Description = "This is a description for Gazipur."
        });
    }

    public ObservableCollection<SimpleOption> Options { get; set; }

}

public class SimpleOption : INotifyPropertyChanged
{

    public string DisplayName {
        get { return _displayName; }
        set {
            _displayName = value;
            NotifyPropertyChanged("DisplayName");
        }
    }

    private string _displayName;
    public string Description {
        get { return _description; }
        set {
            _description = value;
            NotifyPropertyChanged("Description");
        }
    }

    private string _description;
    public bool IsSelected {
        get { return _isSelected; }
        set {
            _isSelected = value;
            NotifyPropertyChanged("IsSelected");
        }
    }

    private bool _isSelected;
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
    public delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e);

}
Trevor Tubbs
  • 2,097
  • 16
  • 18
1

I'd do it with a custom attached property. That way, you can bind to it from a ViewModel, or apply it directly in XAML.

First, create a new class in your Style assembly:

public static class RadioButtonExtender
{
    public static readonly DependencyProperty DescriptionProperty = DependencyProperty.RegisterAttached(
        "Description", 
        typeof(string),
        typeof(RadioButtonExtender), 
        new FrameworkPropertyMetadata(null));

    [AttachedPropertyBrowsableForType(typeof(RadioButton))]
    public static string GetDescription(RadioButton obj)
    {
        return (string)obj.GetValue(DescriptionProperty);
    }

    public static void SetDescription(RadioButton obj, string value)
    {
        obj.SetValue(DescriptionProperty, value);
    }
}

And your style's Bullet would change so that the label is:

<Label x:Name="SelectedLabel" 
       Foreground="Wheat"
       Content="{Binding (prop:RadioButtonExtender.Description), RelativeSource={RelativeSource TemplatedParent}} />

You could then use it in your final XAML:

<RadioButton FontSize="15"
             Content="Dhaka"
             Margin="4"
             IsChecked="False">
    <prop:RadioButtonExtender.Description>
        This is a description that would show under my Header
    </prop:RadioButtonExtender.Description>
</RadioButton>

As an added bonus, since you're creating the Style in a separate assembly, you can create a custom XAML namespace to make using your property easier.

Abe Heidebrecht
  • 30,090
  • 7
  • 62
  • 66