Preventing a WPF Expander from expanding when header is clicked - wpf

How can I prevent a WPF Expander from expanding when its header is clicked? I would like my Expander to expand or collapse only when the expand button itself is clicked.
I imagine the answer has something to do with canceling a bubbled event. If possible I would like to implement the solution in XAML while avoiding retemplating the entire Expander.

There is actually a much simpler XAML solution than modifying templates. Simply DON'T use the Expander's header property in this case. Instead, cover the expander with your own styled TextBlock.
<Application.Resources>
<Style x:Key="ExpanderHeader" TargetType="{x:Type TextBlock}">
<Setter Property="Height" Value="22" />
<Setter Property="Margin" Value="21,0,0,0" />
<Setter Property="Padding" Value="9,3,0,0" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
</Application.Resources>
<Grid>
<Expander>
<TextBlock Text="I am some content. I have disowned my default header." Margin="10,5" />
</Expander>
<TextBlock Text="I'm filling in for the default header. You'll like me better anyway."
Style="{StaticResource ResourceKey=ExpanderHeader}"/>
</Grid>

The header is the button that creates the event, so you need to change the template for your Expander to just have the expander icon as the button.
Here is a post of how to change the expander.

I modified the default template for the Expander control as suggested by Simeon.
The following ControlTemplate defines an expander, which only reacts (expands/collapses) when the user clicks on the header icon.
This is quick and dirty so expect it to break.
<ControlTemplate x:Key="LazyExpanderTemplate" TargetType="Expander">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" CornerRadius="3,3,3,3" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" SnapsToDevicePixels="True">
<DockPanel>
<DockPanel DockPanel.Dock="Top" Name="HeaderSite">
<ToggleButton
DockPanel.Dock="Left"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}"
Foreground="{TemplateBinding TextElement.Foreground}"
FontFamily="{TemplateBinding TextElement.FontFamily}"
FontSize="{TemplateBinding TextElement.FontSize}"
FontStretch="{TemplateBinding TextElement.FontStretch}"
FontStyle="{TemplateBinding TextElement.FontStyle}"
FontWeight="{TemplateBinding TextElement.FontWeight}"
HorizontalContentAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding Control.VerticalContentAlignment}"
Padding="{TemplateBinding Control.Padding}"
MinWidth="0"
MinHeight="0"
Margin="1,1,1,1"
>
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Padding="{TemplateBinding Control.Padding}">
<Grid Background="#00FFFFFF" SnapsToDevicePixels="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="19" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Ellipse Stroke="#FFA9A9A9" Name="circle" Width="19" Height="19" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Ellipse Name="shadow" Width="17" Height="17" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" />
<Path Data="M1,1.5L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" Name="arrow" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="False" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked" Value="True" >
<Setter Property="Path.Data" TargetName="arrow">
<Setter.Value>
<StreamGeometry>M1,4.5L4.5,1 8,4.5</StreamGeometry>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<Setter Property="Shape.Stroke" TargetName="circle">
<Setter.Value>
<SolidColorBrush>#FF666666</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Shape.Stroke" TargetName="arrow">
<Setter.Value>
<SolidColorBrush>#FF222222</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="UIElement.Visibility" TargetName="shadow">
<Setter.Value>
<x:Static Member="Visibility.Visible" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
<ToggleButton.FocusVisualStyle>
<Style TargetType="IFrameworkInputElement">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Stroke="#FF000000" StrokeThickness="1" StrokeDashArray="1 2" Margin="0,0,0,0" SnapsToDevicePixels="True" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.FocusVisualStyle>
</ToggleButton>
<ContentPresenter
RecognizesAccessKey="True"
Content="{TemplateBinding HeaderedContentControl.Header}"
ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
ContentStringFormat="{TemplateBinding HeaderedContentControl.HeaderStringFormat}"
Margin="4,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
SnapsToDevicePixels="True"
/>
</DockPanel>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Name="ExpandSite" Margin="{TemplateBinding Control.Padding}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" Visibility="Collapsed" Focusable="False" DockPanel.Dock="Bottom" />
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Expander.IsExpanded">
<Setter Property="UIElement.Visibility" TargetName="ExpandSite">
<Setter.Value>
<x:Static Member="Visibility.Visible" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="Expander.ExpandDirection" Value="Right">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
<Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/>
<Setter Property="FrameworkElement.Style" TargetName="HeaderSite">
<Setter.Value>
<Style TargetType="ToggleButton">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Padding="{TemplateBinding Control.Padding}">
<Grid Background="#00FFFFFF" SnapsToDevicePixels="False">
<Grid.RowDefinitions>
<RowDefinition Height="19" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid>
<Grid.LayoutTransform>
<TransformGroup>
<TransformGroup.Children>
<RotateTransform Angle="-90" />
</TransformGroup.Children>
</TransformGroup>
</Grid.LayoutTransform>
<Ellipse Stroke="#FFA9A9A9" Name="circle" Width="19" Height="19" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Ellipse Name="shadow" Width="17" Height="17" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" />
<Path Data="M1,1.5L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" Name="arrow" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="False" />
</Grid>
<ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Margin="0,4,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" SnapsToDevicePixels="True" Grid.Row="1" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked">
<Setter Property="Path.Data" TargetName="arrow">
<Setter.Value>
<StreamGeometry>M1,4.5L4.5,1 8,4.5</StreamGeometry>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="UIElement.IsMouseOver">
<Setter Property="Shape.Stroke" TargetName="circle">
<Setter.Value>
<SolidColorBrush>#FF666666</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Shape.Stroke" TargetName="arrow">
<Setter.Value>
<SolidColorBrush>#FF222222</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="UIElement.Visibility" TargetName="shadow">
<Setter.Value>
<x:Static Member="Visibility.Visible" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="Expander.ExpandDirection">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
<Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/>
<Setter Property="FrameworkElement.Style" TargetName="HeaderSite">
<Setter.Value>
<Style TargetType="ToggleButton">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Padding="{TemplateBinding Control.Padding}">
<Grid Background="#00FFFFFF" SnapsToDevicePixels="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="19" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.LayoutTransform>
<TransformGroup>
<TransformGroup.Children>
<RotateTransform Angle="180" />
</TransformGroup.Children>
</TransformGroup>
</Grid.LayoutTransform>
<Ellipse Stroke="#FFA9A9A9" Name="circle" Width="19" Height="19" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Ellipse Name="shadow" Width="17" Height="17" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" />
<Path Data="M1,1.5L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" Name="arrow" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="False" />
</Grid>
<ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Margin="4,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" SnapsToDevicePixels="True" Grid.Column="1" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked">
<Setter Property="Path.Data" TargetName="arrow">
<Setter.Value>
<StreamGeometry>M1,4.5L4.5,1 8,4.5</StreamGeometry>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="UIElement.IsMouseOver">
<Setter Property="Shape.Stroke" TargetName="circle">
<Setter.Value>
<SolidColorBrush>#FF666666</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Shape.Stroke" TargetName="arrow">
<Setter.Value>
<SolidColorBrush>#FF222222</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="UIElement.Visibility" TargetName="shadow">
<Setter.Value>
<x:Static Member="Visibility.Visible" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Trigger.Value>
<x:Static Member="ExpandDirection.Up" />
</Trigger.Value>
</Trigger>
<Trigger Property="Expander.ExpandDirection">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite">
<Setter.Value>
<x:Static Member="Dock.Left" />
</Setter.Value>
</Setter>
<Setter Property="DockPanel.Dock" TargetName="HeaderSite">
<Setter.Value>
<x:Static Member="Dock.Right" />
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Style" TargetName="HeaderSite">
<Setter.Value>
<Style TargetType="ToggleButton">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Padding="{TemplateBinding Control.Padding}">
<Grid Background="#00FFFFFF" SnapsToDevicePixels="False">
<Grid.RowDefinitions>
<RowDefinition Height="19" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid>
<Grid.LayoutTransform>
<TransformGroup>
<TransformGroup.Children>
<RotateTransform Angle="90" />
</TransformGroup.Children>
</TransformGroup>
</Grid.LayoutTransform>
<Ellipse Stroke="#FFA9A9A9" Name="circle" Width="19" Height="19" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Ellipse Name="shadow" Width="17" Height="17" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" />
<Path Data="M1,1.5L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" Name="arrow" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="False" />
</Grid>
<ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Margin="0,4,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" SnapsToDevicePixels="True" Grid.Row="1" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked">
<Setter Property="Path.Data" TargetName="arrow">
<Setter.Value>
<StreamGeometry>M1,4.5L4.5,1 8,4.5</StreamGeometry>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="UIElement.IsMouseOver">
<Setter Property="Shape.Stroke" TargetName="circle">
<Setter.Value>
<SolidColorBrush>#FF666666</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Shape.Stroke" TargetName="arrow">
<Setter.Value>
<SolidColorBrush>#FF222222</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="UIElement.Visibility" TargetName="shadow">
<Setter.Value>
<x:Static Member="Visibility.Visible" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Trigger.Value>
<x:Static Member="ExpandDirection.Left" />
</Trigger.Value>
</Trigger>
<Trigger Property="UIElement.IsEnabled">
<Setter Property="TextElement.Foreground">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

My solution was to leave the header blank and just tag on a control that acts as the header (using a canvas for absolute positioning), that way only the icon expands the control:
<Grid Height="{Binding ElementName=exp, Path=ActualHeight}">
<Canvas>
<Expander Name="exp">
...
</Expander>
<Control Style="{StaticResource ExpanderHeaderStyle}" Margin="20,0,0,0" />
</Canvas>
</Grid>

A rather simple solution is to modify the toggle button templates that the Expander control tempate uses in the following way.
Set the background of the grid and border to {x:Null}
Set the content presenter IsHitTestVisible to False
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}" Background="{x:Null}">
<Grid Background="{x:Null}" SnapsToDevicePixels="False">
<Grid.RowDefinitions>
<RowDefinition Height="19"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid>
<Grid.LayoutTransform>
<TransformGroup>
<TransformGroup.Children>
<TransformCollection>
<RotateTransform Angle="-90"/>
</TransformCollection>
</TransformGroup.Children>
</TransformGroup>
</Grid.LayoutTransform>
<Ellipse x:Name="circle" HorizontalAlignment="Center" Height="19" Stroke="DarkGray" VerticalAlignment="Center" Width="19"/>
<Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="#666" StrokeThickness="2" VerticalAlignment="Center"/>
</Grid>
<ContentPresenter HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"IsHitTestVisible="False"/>
</Grid>
</Border>
</ControlTemplate>

You could just set IsEnabled to false but in case you need to determine if you can expand or collapse when the header is clicked:
public class MyExpander : Expander
{
private bool CanExpand() => true;
private bool CanCollapse() => true;
private bool rollback;
protected override void OnExpanded()
{
if (rollback) return;
if (CanExpand())
{
base.OnExpanded();
}
else
{
rollback = true;
SetCurrentValue(IsExpandedProperty, false);
rollback = false;
}
}
protected override void OnCollapsed()
{
if (rollback) return;
if (CanCollapse())
{
base.OnCollapsed();
}
else
{
rollback = true;
SetCurrentValue(IsExpandedProperty, true);
rollback = false;
}
}
}

As I've just checked, the header is named "HeaderSite". You can use method like the one described in this post in order to find child by name. When you have the child you can just change visibility of it. Also make sure the expander is loaded, otherwise you wont see the child.
expander.Loaded += (s, e) => {
var hv = expander.findChildByName("HeaderSite");
if (hv == null) return;
hv.Visibility = Visibility.Collapsed;
};
I guess it's not guaranteed the name won't change and for me it's just cosmetic problem.

Related

Insert an icon in menu item that uses an user defined Template

I want to have a dropdown menu with custom background color of the menu item. I was able to achieve this with the help of this answer. The root menu item in my GUI has only an icon with no Header. The code I used to define the menu item icon is as follows:
<Style x:Key="MenuIcon" TargetType="{x:Type MenuItem}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Menu Background="Orange">
<MenuItem ToolTip="Menu" BorderBrush="White">
<MenuItem.Header>
<StackPanel
Width="60"
Height="50"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Orange"
Orientation="Horizontal">
<Viewbox
Margin="9"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Fill">
<Grid Margin="-8,0,0,0">
<Path
x:Name="MenuIconFillStyle"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M6 36v-3h36v3Zm0-10.5v-3h36v3ZM615v-3h36v3Z"
Fill="White" />
</Grid>
</Viewbox>
</StackPanel>
</MenuItem.Header>
</MenuItem>
</Menu>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="MenuIconFillStyle" Property="Fill" Value="Yellow" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I added the following in the <ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}"> taken from here:
<ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Height="16" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>
and the following in the ControlTemplate.Triggers:
<Trigger Property="Icon" Value="True">
<Setter Property="Visibility" TargetName="Icon" Value="Visible"/>
</Trigger>
The Template="{DynamicResource MenuItemControlTemplate1}" is as follows:
<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot"
BorderBrush="#535353"
CornerRadius="3"
BorderThickness="1"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Width="26" Height="16" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" />
<ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="1" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom" HorizontalOffset="-2">
<Border x:Name="SubMenuBorder" BorderBrush="#595959" BorderThickness="1" Background="#3A3A3A" Padding="2">
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=SubMenuBorder}" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="True">
<Setter Property="Visibility" TargetName="Icon" Value="Visible"/>
</Trigger>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource DarkBrush}"/>
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#2C2C2C"/>
<Setter Property="BorderThickness" TargetName="templateRoot" Value="1"></Setter>
</Trigger>
<Trigger Property="CanContentScroll" SourceName="SubMenuScrollViewer" Value="False">
<Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}"/>
<Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="{StaticResource Clicked}" />
<Setter Property="Header" Value="Test" />
<Setter Property="BorderBrush" Value="#2C2C2C"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
The custom background and the icon for the MenuItem is specified as in the following code snippet:
<Grid Background="#535353">
<Menu Width="100" Height="22" Margin="10, 10, 5, 5" HorizontalAlignment="Left" Background="White" VerticalAlignment="Top">
<MenuItem Style="{StaticResource MenuIcon}" Template="{DynamicResource MenuItemControlTemplate1}">
</Menu>
</Grid>
The icon defined in Style is not rendering in the MenuItem along with the Template (Template="{DynamicResource MenuItemControlTemplate1}") used for setting the background color. How can this be achieved?
Edit
Based on the suggestion of #mm8, I tried to combine the Styles that are responsible for changing the background color (The Style with x:Key="TopLevelHeaderStyle" which is borrowed from here) and inserting a menu item icon in the root menu and came up with the following:
<Style x:Key="TopLevelHeaderStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Background" Value="#000d18"/>
<Setter Property="Foreground" Value="#d8d8d8"/>
<Setter Property="Width" Value="72"/>
<Setter Property="Height" Value="42"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="MenuItemBorder" Width="72" Height="42" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding Header}" ContentSource="Header" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<Popup AllowsTransparency="True" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PlacementTarget="{Binding ElementName=MenuItemBorder}"
HorizontalOffset="1" VerticalOffset="-1">
<Border BorderBrush="#414141" Background="#414141">
<ScrollViewer Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" Value="#1271C8"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--MenuIcon-->
<Style x:Key="MenuIcon" TargetType="{x:Type MenuItem}" BasedOn="{StaticResource TopLevelHeaderStyle}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Menu>
<MenuItem>
<MenuItem.Header>
<StackPanel
Width="60"
Height="50"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Orange"
Orientation="Horizontal">
<Viewbox
Margin="9"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Fill">
<Grid Margin="-8,0,0,0">
<Path x:Name="MenuIconFillStyle"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="White"
Data="M6 36v-3h36v3Zm0-10.5v-3h36v3ZM6 15v-3h36v3Z"
/>
</Grid>
</Viewbox>
</StackPanel>
</MenuItem.Header>
</MenuItem>
</Menu>
And used it as follows:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Menu Grid.Column="0" FontSize="24" HorizontalAlignment="Left" VerticalAlignment="Top">
<MenuItem Header="File" Style="{StaticResource TopLevelHeaderStyle}">
<MenuItem Header="New"/>
<MenuItem Header="Open"/>
<MenuItem Header="Close"/>
</MenuItem>
</Menu>
<Menu Grid.Column="1" FontSize="24" HorizontalAlignment="Left" VerticalAlignment="Top">
<MenuItem Margin="-11, 0,0,0" Width="50" Header="File" Style="{StaticResource MenuIcon}">
<MenuItem Header="New1"/>
<MenuItem Header="Open1"/>
<MenuItem Header="Close1"/>
</MenuItem>
</Menu>
</Grid>
Now the drop down menu having an icon in the root menu item is not showing the other menu item contents New1, Open1 and Close1 What mistake am I making?
The MenuItem control has a DependencyProperty of type Object named 'Icon'. This property is reserved for your exact purpose.
First you need to bind the Data in the Path within your MenuItem ControlTemplate to the Icon property of the parent MenuItem. Like this:
<Path x:Name="MenuIconFillStyle"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="{TemplateBinding Icon}"
Fill="White" />
Now you may specify a PathGeometry in XAML like this. Its contents will be your SVG data:
<PathGeometry x:Key="MySpecialPath">M2 0C0.89687</PathGeometry>
Finally, apply this path using its Key to any MenuItem as a StaticResource:
<Menu Width="100" Height="22" Margin="10, 10, 5, 5" HorizontalAlignment="Left" Background="White" VerticalAlignment="Top">
<MenuItem Template="{DynamicResource MenuItemControlTemplate1}"
Icon="{StaticResource MySpecialPath}">
</Menu>
If you want a bit more control out of your icons (multiple colors, different size, margin, etc..) It is a bit more involved. Just remember that the 'Path' property on MenuItem is an Object so you can hypothetically use any 'Presenting' element (Does not need to be Path) in your MenuItem ControlTemplate and TemplateBind it to MenuItem.Path - then pass any type of 'Presented' object to the MenuItem (does not need to be PathGeometry). You can look into using a
<ContentPresenter Content="{TemplateBinding Icon}" />
instead of the Path control in the MenuItem ControlTemplate - and then giving literally any "Icon" control to your MenuItem.Path property in your XAML.

XAML code without resources and templates possible?

I found an example (the first one) for a slider,
which defines also a track with thumb.
Is it possible to recode it without resources and templates?
Thank you for your comments.
Erhy
I have done it.
Here the XAML code without template and style references
for the slider with track and thumb
<Slider x:Name="slidExample"
VerticalAlignment="Center" TickFrequency="37.5"
Minimum="0" Maximum="600" Value="500" Width="300" Margin="50,0,50,0"
SnapsToDevicePixels="true"
OverridesDefaultStyle="true"
IsTabStop="false"
Focusable="false"
>
<Slider.Style>
<Style TargetType="Slider">
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="MinHeight" Value="21" />
<Setter Property="MinWidth" Value="104" />
</Trigger>
</Style.Triggers>
</Style>
</Slider.Style>
<Slider.Template>
<ControlTemplate>
<Grid x:Name="GridOfslidExample">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TickBar x:Name="TopTickOfslidExample" Fill="LightGray" VerticalAlignment="Top"
SnapsToDevicePixels="True" Grid.Row="0" Placement="Top" Height="5"
Visibility="Visible">
</TickBar>
<Border BorderBrush="LightGray" BorderThickness="0,0,0,1" ></Border>
<Border x:Name="TrackBackground" VerticalAlignment="Center" Margin="0,-10,0,0" BorderBrush="Red" Background="Red" Height="3" Grid.Row="1" BorderThickness="1"/>
<Track Grid.Row="1" x:Name="PART_Track" Margin="0,-10,0,0" >
<Track.DecreaseRepeatButton>
<RepeatButton Command="Slider.DecreaseLarge" >
<RepeatButton.Style>
<Style TargetType="RepeatButton">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Border SnapsToDevicePixels="True" Background="YellowGreen" BorderThickness="1" BorderBrush="YellowGreen" Height="3"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RepeatButton.Style>
</RepeatButton>
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb x:Name="ThumbOfslidExample">
<Thumb.Style>
<Style TargetType="Thumb">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<StackPanel Orientation="Vertical">
<Path Data="M 0 0 L 8 0 L 4 6 Z" Stroke="YellowGreen" Margin="-2,0,0,0" StrokeThickness="2" Fill="YellowGreen"></Path>
<Line X1="0" Y1="0" X2="0" Y2="7" Stroke="Gray" StrokeThickness="1" Margin="2,0,0,0" StrokeDashArray="1.5,1.5"></Line>
<TextBlock Foreground="Black" Margin="-2,30,0,0" Text="{Binding Value, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Slider}}}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Command="Slider.IncreaseLarge" >
<RepeatButton.Style>
<Style TargetType="RepeatButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Border Background="Transparent"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RepeatButton.Style>
</RepeatButton>
</Track.IncreaseRepeatButton>
</Track>
<TextBlock Text="0" Grid.Row="1" Margin="0,15,0,0"></TextBlock>
<TickBar x:Name="BottomTickOfslidExample" Fill="LightGray" SnapsToDevicePixels="True" Grid.Row="2" Placement="Bottom" Height="4" Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Slider.TickPlacement" Value="TopLeft">
<Setter TargetName="TopTickOfslidExample" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="Slider.TickPlacement" Value="BottomRight">
<Setter TargetName="BottomTickOfslidExample" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="Slider.TickPlacement" Value="Both">
<Setter TargetName="TopTickOfslidExample" Property="Visibility" Value="Visible" />
<Setter TargetName="BottomTickOfslidExample" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Slider.Template>
</Slider>
I think I have fixed it.
The reason of missings commands of RepeatButton was the textfield in thumb.
Its name in the new source is "DisplaysValueInThumb".
I had to add a converter, because the value of the slider produce many decimal places, which hide the touch area of the repeat button.
Because I was unable to format the source correctly
you find the source here.
Erhy

How to create a WPF-tab control as chevron list?

I have a WPF tab control. but I would like to change the tab item style. The default style is square. I need to make it like a chevron list. Each block in that as hexagon.
EDIT:
Here's a quick example made with Kaxaml:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="chevronTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30">
<Path Data="M0,0 10,0 10,30 0,30 10,15"
Fill="{TemplateBinding Background}"/>
<Grid>
<Rectangle Fill="{TemplateBinding Background}" />
<TextBlock Text="{TemplateBinding Header}" Margin="10,5" VerticalAlignment="Center" />
</Grid>
<Path Data="M0,0 10,15 0,30"
Fill="{TemplateBinding Background}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<TabControl ItemContainerStyle="{StaticResource chevronTabItemStyle}">
<TabItem Header="Design" Background="DarkSlateBlue" />
<TabItem Header="Plan" Background="DarkCyan" />
<TabItem Header="Build" Background="LightSkyBlue" />
<TabItem Header="Test" Background="SandyBrown" />
<TabItem Header="Evaluate" Background="SteelBlue" />
</TabControl>
</Grid>
</Page>
You will probably need to adjust a few properties, but it's roughly what you described...
Thomas Levesque your answer is beautiful!
There is a little problem with foreground color, move property into TextBlock prevent all tab to be colored White
In this way we can change the color of the header if properties IsEnable or Selected are valued.
<Style x:Key="TestNewTabStyle" TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30">
<Path Data="M0,0 10,0 10,30 0,30 10,15" Fill="{TemplateBinding Background}"/>
<Grid >
<Rectangle Fill="{TemplateBinding Background}" />
<TextBlock Name="HeaderArrow" Text="{TemplateBinding Header}" Margin="15,5" VerticalAlignment="Center" Foreground="White"**/>
</Grid>
<Path Data="M0,0 10,15 0,30" Fill="{TemplateBinding Background}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="HeaderArrow" Property="FontWeight" Value="Bold" />
<Setter TargetName="HeaderArrow" Property="Foreground" Value="Yellow" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="HeaderArrow" Property="Foreground" Value="DarkGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Default combobox template. Popup width

I want add some buttons to default combobox template, so I override its template.
I use this:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="l:RefreshableComboBox">
<Grid Name="MainGrid" SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="0" MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" />
</Grid.ColumnDefinitions>
<Popup IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" AllowsTransparency="True" Name="PART_Popup" Margin="1,1,1,1" Grid.ColumnSpan="2" >
<mwt:SystemDropShadowChrome Color="#00FFFFFF" Name="Shdw" MinWidth="0" MaxHeight="{TemplateBinding ComboBox.MaxDropDownHeight}">
<Border BorderThickness="1,1,1,1" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" Name="DropDownBorder">
<ScrollViewer Name="DropDownScrollViewer">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas Width="0" Height="0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Fill="{x:Null}" Name="OpaqueRect" Width="Auto" Height="Auto" />
</Canvas>
<ItemsPresenter Name="ItemsPresenter" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Contained" />
</Grid>
</ScrollViewer>
</Border>
</mwt:SystemDropShadowChrome>
</Popup>
<ToggleButton x:Name="ToggleButton" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Grid.ColumnSpan="2">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Resources>
<ResourceDictionary />
</Style.Resources>
<Setter Property="FrameworkElement.OverridesDefaultStyle">
<Setter.Value>
<s:Boolean>True</s:Boolean>
</Setter.Value>
</Setter>
<Setter Property="KeyboardNavigation.IsTabStop">
<Setter.Value>
<s:Boolean>False</s:Boolean>
</Setter.Value>
</Setter>
<Setter Property="UIElement.Focusable">
<Setter.Value>
<s:Boolean>False</s:Boolean>
</Setter.Value>
</Setter>
<Setter Property="ButtonBase.ClickMode">
<Setter.Value>
<x:Static Member="ClickMode.Press" />
</Setter.Value>
</Setter>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<mwt:ButtonChrome Background="{TemplateBinding Panel.Background}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}"
RenderPressed="{TemplateBinding ButtonBase.IsPressed}"
Name="Chrome" SnapsToDevicePixels="True">
<Grid Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" HorizontalAlignment="Right">
<Path Data="M0,0L3.5,4 7,0z" Fill="#FF000000" Name="Arrow" Margin="3,1,0,0"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</mwt:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked">
<Setter Property="mwt:ButtonChrome.RenderPressed" TargetName="Chrome">
<Setter.Value>
<s:Boolean>True</s:Boolean>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="UIElement.IsEnabled">
<Setter Property="Shape.Fill" TargetName="Arrow">
<Setter.Value>
<SolidColorBrush>#FFAFAFAF</SolidColorBrush>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
<ContentPresenter Content="{TemplateBinding ComboBox.SelectionBoxItem}" ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}" ContentStringFormat="{TemplateBinding ComboBox.SelectionBoxItemStringFormat}" Margin="{TemplateBinding Control.Padding}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" IsHitTestVisible="False" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Popup.HasDropShadow" SourceName="PART_Popup">
<Setter Property="FrameworkElement.Margin" TargetName="Shdw">
<Setter.Value>
<Thickness>0,0,5,5</Thickness>
</Setter.Value>
</Setter>
<Setter Property="mwt:SystemDropShadowChrome.Color" TargetName="Shdw">
<Setter.Value>
<Color>#71000000</Color>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="ItemsControl.HasItems">
<Setter Property="FrameworkElement.Height" TargetName="DropDownBorder">
<Setter.Value>
<s:Double>95</s:Double>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="UIElement.IsEnabled">
<Setter Property="TextElement.Foreground">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="Panel.Background">
<Setter.Value>
<SolidColorBrush>#FFF4F4F4</SolidColorBrush>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="ItemsControl.IsGrouping">
<Setter Property="ScrollViewer.CanContentScroll">
<Setter.Value>
<s:Boolean>False</s:Boolean>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer">
<Setter Property="Canvas.Top" TargetName="OpaqueRect">
<Setter.Value>
<Binding Path="VerticalOffset" ElementName="DropDownScrollViewer" />
</Setter.Value>
</Setter>
<Setter Property="Canvas.Left" TargetName="OpaqueRect">
<Setter.Value>
<Binding Path="HorizontalOffset" ElementName="DropDownScrollViewer" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
By some reason my popup(PART_Popup) isn't the same width as toggleButton. It has width enough for displaying item. If I don't override template popup is the same width as toggleButton. So I can't understand why I can't get the same situation with standart template
Change the MinWidth of mwt:SystemDropShadowChrome from 0 to:
MinWidth="{Binding ElementName=MainGrid,Path=ActualWidth}"

Applying a style to a gridview

I have been tearing my hair out all afternoon on this, hopefully someone can help me. Bear with me on this one.
I have a number of styles in my App.xaml which transforms a gridview, the code looks like this.
<Application.Resources>
<Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}"
TargetType="{x:Type ScrollViewer}">
<Setter Property="Focusable"
Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Margin="{TemplateBinding Padding}">
<ScrollViewer DockPanel.Dock="Left"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Focusable="false">
<GridViewHeaderRowPresenter Margin="2,0,2,0"
Columns="{Binding Path=TemplatedParent.View.Columns,RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderContainerStyle="{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle,RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderTemplate="{Binding Path=TemplatedParent.View.ColumnHeaderTemplate,RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderTemplateSelector="{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector,RelativeSource={RelativeSource TemplatedParent}}"
AllowsColumnReorder="{Binding Path=TemplatedParent.View.AllowsColumnReorder,RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderContextMenu="{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu,RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderToolTip="{Binding Path=TemplatedParent.View.ColumnHeaderToolTip,RelativeSource={RelativeSource TemplatedParent}}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter"
KeyboardNavigation.DirectionalNavigation="Local"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
CanContentScroll="{TemplateBinding CanContentScroll}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</DockPanel>
<DockPanel Grid.Column="1"
Grid.Row="1"
Background="{Binding Path=Background,ElementName=PART_VerticalScrollBar}"
LastChildFill="false">
<Rectangle DockPanel.Dock="Left"
Width="1"
Fill="White"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<Rectangle DockPanel.Dock="Top"
Height="1"
Fill="White"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type GridViewHeaderRowPresenter}">
<Setter Property="Height" Value="80" />
<Setter Property="LayoutTransform">
<Setter.Value>
<TransformGroup>
<RotateTransform Angle="-90" />
<ScaleTransform ScaleY="-1" />
</TransformGroup>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type GridViewRowPresenter}">
<Setter Property="LayoutTransform">
<Setter.Value>
<TransformGroup>
<RotateTransform Angle="-90" />
<ScaleTransform ScaleY="-1" />
</TransformGroup>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<Border Name="Border" BorderThickness="1" BorderBrush="Black" Background="White">
<ScrollViewer Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}">
<ItemsPresenter />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Background" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="2,0,2,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="HeaderBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,1,0,1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="7"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Rectangle Fill="#FFE3F7FF" x:Name="UpperHighlight" Visibility="Collapsed"/>
<Border Grid.RowSpan="2" Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0,0,0,1" x:Name="HeaderContent" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True">
<ContentPresenter.LayoutTransform>
<TransformGroup>
<ScaleTransform ScaleY="-1" />
<RotateTransform Angle="90" />
</TransformGroup>
</ContentPresenter.LayoutTransform>
</ContentPresenter>
</Border>
</Grid>
</Border>
<Border Margin="1,1,0,0" x:Name="HeaderHoverBorder" BorderThickness="1,0,1,1"/>
<Border Margin="1,0,0,1" x:Name="HeaderPressBorder" BorderThickness="1,1,1,0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Height" Value="Auto">
<Setter Property="MinHeight" Value="20"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Now, this is applying to ALL gridviews on my page, how would i make these styles apply to certain gridviews and not others? I have tried a million different ways and i'm sure i'm missing something obvious!, please help :-)
You have to make your Key a string, like <Style x:Key="myGridStyle" TargetType="{x:Type ScrollViewer}">, then call that style for the grids you want to use it on. Also, if you only set a TargetType and not a Key, then it will be the default for that Type everywhere, unless you override it.

Resources