I've tried:
<UniformGrid DockPanel.Dock="Top" Columns="2" Rows="1">
<UniformGrid.Resources>
<Style TargetType="RadioButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<TabItem IsSelected="{TemplateBinding IsChecked}">
<TabItem.Header>
<ContentPresenter Margin="5" />
</TabItem.Header>
</TabItem>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UniformGrid.Resources>
<RadioButton Content="By company name" />
<RadioButton Content="By contact name" Grid.Column="1"/>
</UniformGrid>
It actually works except it doesn't select/unselect the appropriate tab.
I would prefer RadioButtons of course, but my customer insist it should be Tabs.
I think the problem is that the TabItem is "eating" the mouseclick so the RadioButton never gets checked/unchecked. You could wrap the TabItem in a Border and set IsHitTestVisible="False"
. Doing this you'll lose the IsMouseOver trigger etc, so you'll have to re-add them from the Default template
Try something like this
<LinearGradientBrush x:Key="TabItemHotBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#EAF6FD" Offset="0.15"/>
<GradientStop Color="#D9F0FC" Offset=".5"/>
<GradientStop Color="#BEE6FD" Offset=".5"/>
<GradientStop Color="#A7D9F5" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="TabItemSelectedBackground" Color="#F9F9F9"/>
<SolidColorBrush x:Key="TabItemHotBorderBrush" Color="#3C7FB1"/>
<Style x:Key="RadioButtonStyle1" TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Border BorderBrush="Transparent" BorderThickness="0" Background="Transparent" CornerRadius="0">
<TabItem x:Name="tabItem" IsSelected="{TemplateBinding IsChecked}" IsHitTestVisible="False">
<TabItem.Header>
<ContentPresenter Margin="5"/>
</TabItem.Header>
</TabItem>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="tabItem" Value="{StaticResource TabItemHotBackground}"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Panel.ZIndex" Value="1"/>
<Setter Property="Background" TargetName="tabItem" Value="{StaticResource TabItemSelectedBackground}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="false"/>
<Condition Property="IsMouseOver" Value="true"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="tabItem" Value="{StaticResource TabItemHotBorderBrush}"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Update
<ControlTemplate TargetType="RadioButton">
<Border BorderBrush="Transparent" BorderThickness="0" Background="Transparent" CornerRadius="0">
<TabItem x:Name="tabItem" IsSelected="{TemplateBinding IsChecked}" IsHitTestVisible="False">
<TabItem.Header>
<ContentPresenter Margin="5"/>
</TabItem.Header>
</TabItem>
</Border>
</ControlTemplate>
Update 2
You could use an Attached Behavior to raise the MouseDown event on the RadioButton when the TabItem gets clicked. Alternatively you could just set IsChecked="True" instead of raising the click-event
<ControlTemplate TargetType="RadioButton">
<TabItem x:Name="tabItem" IsSelected="{TemplateBinding IsChecked}"
local:LinkWithRadioButtonBehavior.LinkWithRadioButton="True">
<TabItem.Header>
<ContentPresenter Margin="5"/>
</TabItem.Header>
</TabItem>
</ControlTemplate>
LinkWithRadioButtonBehavior
public static class LinkWithRadioButtonBehavior
{
public static readonly DependencyProperty LinkWithRadioButtonProperty =
DependencyProperty.RegisterAttached
(
"LinkWithRadioButton",
typeof(bool),
typeof(LinkWithRadioButtonBehavior),
new UIPropertyMetadata(false, OnLinkWithRadioButtonPropertyChanged)
);
public static bool GetLinkWithRadioButton(DependencyObject obj)
{
return (bool)obj.GetValue(LinkWithRadioButtonProperty);
}
public static void SetLinkWithRadioButton(DependencyObject obj, bool value)
{
obj.SetValue(LinkWithRadioButtonProperty, value);
}
private static void OnLinkWithRadioButtonPropertyChanged(DependencyObject dpo,
DependencyPropertyChangedEventArgs e)
{
Control control = dpo as Control;
if (control != null)
{
if ((bool)e.NewValue == true)
{
control.PreviewMouseDown += OnMouseDown;
}
else
{
control.PreviewMouseDown -= OnMouseDown;
}
}
}
static void OnMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Control control = sender as Control;
MouseButtonEventArgs routedEventArgs = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left);
routedEventArgs.RoutedEvent = RadioButton.MouseDownEvent;
routedEventArgs.Source = control;
RadioButton clickedRadioButton = GetVisualParent<RadioButton>(control);
clickedRadioButton.RaiseEvent(routedEventArgs);
}
public static T GetVisualParent<T>(object childObject) where T : Visual
{
DependencyObject child = childObject as DependencyObject;
while ((child != null) && !(child is T))
{
child = VisualTreeHelper.GetParent(child);
}
return child as T;
}
}