I have a custom template for an expander that is close to the code below. I had to change some of the code to take out custom classes, brushes, etc..
<Style TargetType="{x:Type Expander}">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="VerticalContentAlignment"
Value="Top" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="FontFamily"
Value="Tahoma" />
<Setter Property="FontSize"
Value="12" />
<Setter Property="Foreground"
Value="Black" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Margin"
Value="2,0,0,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border x:Name="Border"
SnapsToDevicePixels="true"
Background="White"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Margin="0,0,0,10"
Padding="0"
CornerRadius="8">
<DockPanel>
<Border x:Name="HeaderSite"
Background="Blue"
CornerRadius="8"
Height="32"
DockPanel.Dock="Top">
<DockPanel>
<ToggleButton Foreground="White"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="0"
MinHeight="0"
MinWidth="0"
Padding="6,2,6,2"
IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
DockPanel.Dock="Left">
</ToggleButton>
<ContentPresenter SnapsToDevicePixels="True"
HorizontalAlignment="Left"
Margin="4,0,0,0"
ContentSource="Header"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</DockPanel>
</Border>
<Border x:Name="InnerBorder"
Margin="0" >
<ContentPresenter Focusable="false"
Visibility="Collapsed"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
x:Name="ExpandSite"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
DockPanel.Dock="Bottom" />
</Border>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded"
Value="true">
<Setter Property="Margin"
TargetName="InnerBorder"
Value="5" />
<Setter Property="Visibility"
TargetName="ExpandSite"
Value="Visible" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see there are two ContentPresenters. I would like the first one to use Tahoma Bold as the font instead of the default Tahoma. How can I do this?
You need to use the FontWeight property to specify a bold font. However, you've probably noticed that ContentPresenter doesn't have that property. So you'll need to use the TextBlock.FontWeight attached property to tell the ContentPresenter that any text inside it should be bold.
Try this:
<ContentPresenter TextBlock.FontFamily="Tahoma"
TextBlock.FontWeight="Bold"
SnapsToDevicePixels="True"
HorizontalAlignment="Left"
Margin="4,0,0,0"
ContentSource="Header"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
I can't help about Silverlight, but in the new WPF 4 it is TextElement rather than TextBlock
Related
I want to change the background color of MenuItem when IsMouseOver is triggered but without using a Template.
Could it happen?
Or should I use a Template to change background color of MenuItem when IsMouseOver is triggered?
Edit:
I try to add ControlTemplate using dhilmathy's advice, now I can change the background of the header when IsMouseOver is triggered, but how can I change the background of MenuItem? MenuItems now disappeared.
XAML below as:
<Menu Grid.Column="0" Background="#000d18" BorderBrush="#000d18" Cursor="Hand" Margin="28,0,0,0">
<MenuItem Header="Test1" Width="72" Height="42" Foreground="#d8d8d8" FontSize="16">
<MenuItem Header="Content1" Style="{StaticResource MenuItemStyle}"/>
<MenuItem Header="Content2" Style="{StaticResource MenuItemStyle}"/>
<MenuItem Header="Content3" Style="{StaticResource MenuItemStyle}"/>
<MenuItem Header="Content4" Style="{StaticResource MenuItemStyle}"/>
<MenuItem Header="Content5" Style="{StaticResource MenuItemStyle}"/>
<MenuItem Header="Content6" Style="{StaticResource MenuItemStyle}"/>
</MenuItem>
<MenuItem Header="Test2" Width="72" Height="42" Foreground="#d8d8d8" FontSize="16">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border Width="72" Height="42" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Header}" ContentSource="Header" Margin="{TemplateBinding Padding}" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1271C8"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</MenuItem.Style>
<MenuItem Header="Content1" Style="{StaticResource MenuItemStyle}"/>
<MenuItem Header="Content2" Style="{StaticResource MenuItemStyle}"/>
<MenuItem Header="Content3" Style="{StaticResource MenuItemStyle}"/>
</MenuItem>
<MenuItem Header="Test3" Width="72" Height="42" Foreground="#d8d8d8" FontSize="16"></MenuItem>
</Menu>
MenuItem Styles:
<Style x:Key="MenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Foreground" Value="#d8d8d8"/>
<Setter Property="Background" Value="#414141"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="#414141"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontFamily" Value="Arial"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#011627"/>
<!--<Setter Property="Background" Value="#1271C8"/>-->
</Trigger>
</Style.Triggers>
</Style>
You need to modify the default ControlTemplate of MenuItem to achieve this. You can create a copy of the existing Template from Visual Studio,
Default template:
<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid Margin="-1">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="22" SharedSizeGroup="MenuItemIconColumnGroup" Width="Auto"/>
<ColumnDefinition Width="13"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Height="16" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>
<Border x:Name="GlyphPanel" BorderBrush="#FF26A0DA" BorderThickness="1" Background="#3D26A0DA" ClipToBounds="False" HorizontalAlignment="Center" Height="22" Margin="-1,0,0,0" Visibility="Hidden" VerticalAlignment="Center" Width="22">
<Path x:Name="Glyph" Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z" Fill="#FF212121" FlowDirection="LeftToRight" Height="11" Width="10"/>
</Border>
<ContentPresenter x:Name="menuHeaderContainer" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="2" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
<TextBlock x:Name="menuGestureText" Grid.Column="4" Margin="{TemplateBinding Padding}" Opacity="0.7" Text="{TemplateBinding InputGestureText}" VerticalAlignment="Center"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" TargetName="templateRoot" Value="#3D26A0DA"/>
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF26A0DA"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="#FF707070"/>
<Setter Property="Fill" TargetName="Glyph" Value="#FF707070"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted" Value="True"/>
<Condition Property="IsEnabled" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="templateRoot" Value="#0A000000"/>
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#21000000"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
You need to edit IsHighlighted Trigger to match your requirements.
I have already solved my question.
In order to change MenuItem's background, it must use Template.
Here is MenuItem style:
<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>
Set Template to revise original template, and use ContentPresenter to show content and Popup to show SubMenuItem whose ItemsPresenter can show subMenuItem content. Adjust Popup's style can meet expectaion.
Besides, Trigger IsHighlighted can change MenuItem's background until clicking other position.
SubMenuItem's style can use another customized style to change.
New Style:
I have the following style for a CustomControl in WPF:
<Style TargetType="{x:Type local:BooleanIndicator}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BooleanIndicator}">
<Border Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2">
<StackPanel Orientation="Horizontal"
Margin="3">
<Label Name="symbol"
FontFamily="Segoe MDL2 Assets"
FontSize="{TemplateBinding FontSize}"
Foreground="{TemplateBinding Foreground}"
VerticalAlignment="Center"
Content="{TemplateBinding Symbol}"/>
<ContentPresenter Margin="3,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsActive"
Value="True">
<Setter Property="Foreground"
Value="{Binding ActiveForeground, RelativeSource={RelativeSource TemplatedParent}}" />
</Trigger>
<Trigger Property="IsActive"
Value="False">
<Setter Property="Foreground"
Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
With a dependency property "ActiveForeground":
public Brush ActiveForeground
{
get { return (Brush)GetValue(ActiveForegroundProperty); }
set { SetValue(ActiveForegroundProperty, value); }
}
public static readonly DependencyProperty ActiveForegroundProperty =
DependencyProperty.Register("ActiveForeground",
typeof(Brush),
typeof(BooleanIndicator),
new UIPropertyMetadata(Brushes.DarkGreen));
However it does not work - the Foreground colour is not updated. If I change the colour in the trigger directly, e.g. <Setter Property="Foreground" Value="DarkGreen" /> it works... What is going on?
You must set the TargetName of a Setter in a ControlTemplate:
<Setter Property="Foreground" TargetName="symbol" Value="{Binding ActiveForeground, RelativeSource={RelativeSource TemplatedParent}}" />
If you want to set the Foreground property of the control itself, you should use a Style trigger:
<Style TargetType="{x:Type local:BooleanIndicator}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BooleanIndicator}">
<Border Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2">
<StackPanel Orientation="Horizontal"
Margin="3">
<Label Name="symbol"
FontFamily="Segoe MDL2 Assets"
FontSize="{TemplateBinding FontSize}"
Foreground="{TemplateBinding Foreground}"
VerticalAlignment="Center"
Content="{TemplateBinding Symbol}"/>
<ContentPresenter Margin="3,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Gray" />
<Style.Triggers>
<Trigger Property="IsActive" Value="True">
<Setter Property="Foreground"
Value="{Binding ActiveForeground, RelativeSource={RelativeSource Self}}" />
</Trigger>
</Style.Triggers>
</Style>
I'm in the process of creating a dark ui for my application, and came across something interesting while using Visual Studio as a point of reference. I noticed they render their MenuItems almost as if they're Tabs in a Tabcontrol. Here's a picture:
And here's what mine looks like:
I know it's probably hard to see because everything is sort of the same color, so I went ahead and made another modified image to better highlight the area.
As you can hopefully see, Visual studio draws a border around the MenuItem, and then doesnt draw a border directly below it, for the drop down children. How does Visual Studio do it, though? How could I achieve it? Here's my template:
<Style x:Key="{x:Type Menu}" TargetType="Menu">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="#f1f1f1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Menu">
<Border x:Name="MainMenu" Background="#2d2d30">
<StackPanel
ClipToBounds="True"
IsItemsHost="True"
Orientation="Horizontal" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
<Border
x:Name="templateRoot"
Height="16"
Background="{TemplateBinding Background}"
BorderBrush="#535353"
SnapsToDevicePixels="True">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter
Grid.Column="1"
Margin="{TemplateBinding Padding}"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Popup
x:Name="PART_Popup"
AllowsTransparency="True"
Focusable="False"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
Placement="Bottom"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
<Border
x:Name="SubMenuBorder"
Padding="2"
Background="#1b1b1c"
BorderBrush="#595959"
BorderThickness="1">
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas
Width="0"
Height="0"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Rectangle
x:Name="OpaqueRect"
Width="{Binding ActualWidth, ElementName=SubMenuBorder}"
Height="{Binding ActualHeight, ElementName=SubMenuBorder}"
Fill="{Binding Background, ElementName=SubMenuBorder}" />
</Canvas>
<ItemsPresenter
x:Name="ItemsPresenter"
Grid.IsSharedSizeScope="True"
KeyboardNavigation.DirectionalNavigation="Cycle"
KeyboardNavigation.TabNavigation="Cycle"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter TargetName="PART_Popup" Property="PopupAnimation" Value="None" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="#3e3e40" />
<Setter TargetName="templateRoot" Property="BorderBrush" Value="#2C2C2C" />
</Trigger>
<Trigger SourceName="SubMenuScrollViewer" Property="CanContentScroll" Value="False">
<Setter TargetName="OpaqueRect" Property="Canvas.Top" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}" />
<Setter TargetName="OpaqueRect" Property="Canvas.Left" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="#1b1b1c" />
<Setter Property="Header" Value="Test" />
<Setter Property="BorderBrush" Value="#2C2C2C" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="MenuItemControlTemplate2" TargetType="{x:Type MenuItem}">
<Border
x:Name="templateRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<Grid Margin="-1">
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="Auto"
MinWidth="22"
SharedSizeGroup="MenuItemIconColumnGroup" />
<ColumnDefinition Width="13" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<ContentPresenter
x:Name="Icon"
Width="16"
Height="16"
Margin="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Icon}"
ContentSource="Icon"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Border
x:Name="GlyphPanel"
Width="22"
Height="22"
Margin="-1,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="#3D26A0DA"
BorderBrush="#FF26A0DA"
BorderThickness="1"
ClipToBounds="False"
Visibility="Hidden">
<Path
x:Name="Glyph"
Width="10"
Height="11"
Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z"
Fill="#FF212121"
FlowDirection="LeftToRight" />
</Border>
<ContentPresenter
x:Name="menuHeaderContainer"
Grid.Column="2"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<TextBlock
x:Name="menuGestureText"
Grid.Column="4"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
Opacity="0.7"
Text="{TemplateBinding InputGestureText}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="GlyphPanel" Property="Visibility" Value="Visible" />
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="templateRoot" Property="BorderBrush" Value="Orange" />
<Setter TargetName="templateRoot" Property="Background" Value="Yellow" />
<Setter TargetName="menuHeaderContainer" Property="TextBlock.Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="#FF707070" />
<Setter TargetName="Glyph" Property="Fill" Value="#FF707070" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted" Value="True" />
<Condition Property="IsEnabled" Value="False" />
</MultiTrigger.Conditions>
<Setter TargetName="templateRoot" Property="Background" Value="#0A000000" />
<Setter TargetName="templateRoot" Property="BorderBrush" Value="#21000000" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
In order to figure out what's going on inside Visual Studio, I started two instances of Visual Studio 2017 and attached one to the other's process which allowed me to use the Live Visual Tree tool to inspect the controls (presumably you could use Snoop for this as well).
It turns out that the menu popup in Visual Studio appears to be offset so that it overlays the menu bar and a small box of some sort is drawn to achieve the continuous tab look. This is especially noticeable if you use the Properties window to tweak the VerticalOffset property of the popup so that it is separated from the main menu.
Finding the Popup in the Visual Tree:
Changing the VerticalOffset from its original -2 to a positive number:
And the resulting popup:
If you look at the top left of the now separated menu popup you should be able to see a small extension of the popup that, when the VerticalOffset was -2 originally, overlapped the parent MenuItem border creating the illusion of a single tab-like control.
Knowing this, creating a rudimentary version of Visual Studio's solution is fairly straightforward:
<Window x:Class="MenuItemTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MenuItemTest"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="525"
Height="350"
mc:Ignorable="d">
<Window.Resources>
<local:SubtractingConverter x:Key="SubtractingConverter" />
<Style x:Key="{x:Type Menu}" TargetType="Menu">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="#f1f1f1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Menu">
<Border x:Name="MainMenu" Background="#2d2d30">
<StackPanel ClipToBounds="True"
IsItemsHost="True"
Orientation="Horizontal" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot"
Height="16"
Background="{TemplateBinding Background}"
BorderBrush="#535353"
SnapsToDevicePixels="True">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="1"
Margin="{TemplateBinding Padding}"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Popup x:Name="PART_Popup"
AllowsTransparency="True"
Focusable="False"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
Placement="Bottom"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
<Grid>
<Border x:Name="SubMenuBorder"
Padding="2"
Background="#1b1b1c"
BorderBrush="#595959"
BorderThickness="1">
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas Width="0"
Height="0"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Rectangle x:Name="OpaqueRect"
Width="{Binding ActualWidth, ElementName=SubMenuBorder}"
Height="{Binding ActualHeight, ElementName=SubMenuBorder}"
Fill="{Binding Background, ElementName=SubMenuBorder}" />
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter"
Grid.IsSharedSizeScope="True"
KeyboardNavigation.DirectionalNavigation="Cycle"
KeyboardNavigation.TabNavigation="Cycle"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</ScrollViewer>
</Border>
<Rectangle Width="{TemplateBinding ActualWidth,
Converter={StaticResource SubtractingConverter},
ConverterParameter=1}"
Height="2"
Margin="1,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Fill="{Binding Background, ElementName=SubMenuBorder}" />
</Grid>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter TargetName="PART_Popup" Property="PopupAnimation" Value="None" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="#3e3e40" />
<Setter TargetName="templateRoot" Property="BorderBrush" Value="#2C2C2C" />
</Trigger>
<Trigger SourceName="SubMenuScrollViewer" Property="CanContentScroll" Value="False">
<Setter TargetName="OpaqueRect" Property="Canvas.Top" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}" />
<Setter TargetName="OpaqueRect" Property="Canvas.Left" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="#1b1b1c" />
<Setter Property="Header" Value="Test" />
<Setter Property="BorderBrush" Value="#2C2C2C" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="MenuItemControlTemplate2" TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<Grid Margin="-1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
MinWidth="22"
SharedSizeGroup="MenuItemIconColumnGroup" />
<ColumnDefinition Width="13" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Icon"
Width="16"
Height="16"
Margin="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Icon}"
ContentSource="Icon"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Border x:Name="GlyphPanel"
Width="22"
Height="22"
Margin="-1,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="#3D26A0DA"
BorderBrush="#FF26A0DA"
BorderThickness="1"
ClipToBounds="False"
Visibility="Hidden">
<Path x:Name="Glyph"
Width="10"
Height="11"
Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z"
Fill="#FF212121"
FlowDirection="LeftToRight" />
</Border>
<ContentPresenter x:Name="menuHeaderContainer"
Grid.Column="2"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<TextBlock x:Name="menuGestureText"
Grid.Column="4"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
Opacity="0.7"
Text="{TemplateBinding InputGestureText}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="GlyphPanel" Property="Visibility" Value="Visible" />
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="templateRoot" Property="BorderBrush" Value="Orange" />
<Setter TargetName="templateRoot" Property="Background" Value="Yellow" />
<Setter TargetName="menuHeaderContainer" Property="TextBlock.Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="#FF707070" />
<Setter TargetName="Glyph" Property="Fill" Value="#FF707070" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted" Value="True" />
<Condition Property="IsEnabled" Value="False" />
</MultiTrigger.Conditions>
<Setter TargetName="templateRoot" Property="Background" Value="#0A000000" />
<Setter TargetName="templateRoot" Property="BorderBrush" Value="#21000000" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Menu Background="#2d2d30">
<MenuItem Header="Tools" Template="{StaticResource MenuItemControlTemplate1}">
<MenuItem Padding="0"
Background="#2d2d30"
Header="Test"
Template="{StaticResource MenuItemControlTemplate2}" />
</MenuItem>
<MenuItem Header="Whatever" Template="{StaticResource MenuItemControlTemplate1}">
<MenuItem Padding="0"
Background="#2d2d30"
Header="Test"
Template="{StaticResource MenuItemControlTemplate2}" />
</MenuItem>
</Menu>
</Grid>
</Window>
This is basically the same style and templates that you gave above with the addition of a Rectangle within the MenuItemControlTemplate1 ControlTemplate and a Grid so that both it and the existing Border can be contained within the popup. The SubtractingConverter is just a simple IValueConverter that subtracts the ConverterParameter from the Value... nothing fancy. I've also gone ahead and thrown it in a window for testing. When I run this test program I now get this:
Since I don't have all of your styles obviously not all of the colors are going to be correct, but you'll notice that the menu you were concerned about now appears to be one continuous tab like in Visual Studio.
Now this is not a full solution. There are obvious minor details such as a missing border around the parent "Tools" and "Whatever" menus, but more critically you still need to account for the Popup changing its position due to overlap with the monitor edges when placing the Rectangle.
If you move the application window to the bottom of the screen, the Popup class will open the menu instance above the "Tools" menu rather than below, which will obviously result in the Rectangle being misplaced. Similarly, opening the menu when the window is again the right edge of the screen will once again cause the Rectangle to be misplaced due to the change in popup position. Even Visual Studio 2017 doesn't properly account for this case as you can see below:
Now, maybe handling the basic use case is enough for you in which case, great! If you want to go further and handle repositioning, resizing, and/or hiding/showing the rectangle so that it looks perfect no matter what weird position the user opens a menu in, then I really see no way to do this cleanly without some actual C# code. I suspect this is at least one of the things that the VSMenuItem class in the Live Visual Tree of Visual Studio shown previously does over and above the bog standard MenuItem class. Implementing that functionality is really outside the scope of the original question, but hopefully this at least made clear how they pulled it off.
Set the background colour of that menu item to the colour that you want, and the foreground colour to white.
Hello I have developed a UI in WPF and I am using that UI into PowerShell, I want to change the Titlebar color for that I have implemented a Custome Templete and it's working but I don't know how to handle click event of Minimize maximiz and close button of windows,
below is my code.
[xml]$xaml = #"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Style="{DynamicResource MetroWindowStyle}">
<Window.Resources>
<Style x:Key="MetroWindowStyle" TargetType="{x:Type Window}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="WindowStyle" Value="None" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<Border x:Name="MainBorder" BorderThickness="0" Background="#FFEEE1E1" >
<DockPanel LastChildFill="True">
<Border x:Name="PART_TITLEBAR" BorderThickness="1" BorderBrush="Black" Margin="0,0,0,0" Height="40" DockPanel.Dock="Top" Background="Transparent">
<DockPanel LastChildFill="False">
<TextBlock Margin="4,0,0,4" VerticalAlignment="Center"
Foreground="Red" TextWrapping="NoWrap"
Text="{TemplateBinding Title}" FontSize="16" />
<Button Name="PART_CLOSE" DockPanel.Dock="Right"
VerticalAlignment="Center" Margin="5"
Height="20" Width="20"
Style="{DynamicResource MetroWindowButtonStyle}"
>
<Path Data="F1M54.0573,47.8776L38.1771,31.9974 54.0547,16.1198C55.7604,14.4141 55.7604,11.6511 54.0573,9.94531 52.3516,8.23962 49.5859,8.23962 47.8802,9.94531L32.0026,25.8229 16.1224,9.94531C14.4167,8.23962 11.6511,8.23962 9.94794,9.94531 8.24219,11.6511 8.24219,14.4141 9.94794,16.1198L25.8255,32 9.94794,47.8776C8.24219,49.5834 8.24219,52.3477 9.94794,54.0534 11.6511,55.7572 14.4167,55.7585 16.1224,54.0534L32.0026,38.1745 47.8802,54.0534C49.5859,55.7585 52.3516,55.7572 54.0573,54.0534 55.7604,52.3477 55.763,49.5834 54.0573,47.8776z"
Stretch="Uniform" Fill="#FFAAAAAA" Width="10" Margin="0,0,0,0" ></Path>
</Button>
<Button x:Name="PART_MAXIMIZE_RESTORE"
DockPanel.Dock="Right" Margin="5"
HorizontalAlignment="Center" VerticalAlignment="Center"
Height="20" Width="20" Style="{DynamicResource MetroWindowButtonStyle}">
<Path Data="M4.3685131,23.127279L4.3685131,47.283243 47.117023,47.283243 47.117023,23.127279z M0,10.684L53.755001,10.684 53.755001,51.668001 0,51.668001z M8.5679998,0L58.668022,0 64,0 64,5.6864691 64,45.317999 58.668022,45.317999 58.668022,5.6864691 8.5679998,5.6864691z"
Stretch="Uniform" Fill="#FFAAAAAA" Width="10" Margin="0,0,0,0" ></Path>
</Button>
<Button x:Name="PART_MINIMIZE"
HorizontalAlignment="Center"
VerticalAlignment="Center" Margin="5"
DockPanel.Dock="Right"
Height="20" Width="20" Style="{DynamicResource MetroWindowButtonStyle}"
VerticalContentAlignment="Bottom">
<Button.Content>
<Path Data="M0,20L53.333,20 53.333,8.888 0,8.888z"
Stretch="Uniform" Fill="#FFAAAAAA" Width="10" Margin="0,0,0,5"></Path>
</Button.Content>
</Button>
</DockPanel>
</Border>
<AdornerDecorator DockPanel.Dock="Bottom">
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}"/>
</AdornerDecorator>
</DockPanel>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ResizeMode" Value="CanResizeWithGrip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid>
<AdornerDecorator>
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}"/>
</AdornerDecorator>
<ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" IsTabStop="False" Visibility="Collapsed" VerticalAlignment="Bottom"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode" Value="CanResizeWithGrip"/>
<Condition Property="WindowState" Value="Normal"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="MetroWindowButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle">
<Setter.Value>
<Style>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="#FF707070"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsDefaulted" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFBEE6FD"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35*"/>
<RowDefinition Height="55*"/>
<RowDefinition Height="57*"/>
<RowDefinition Height="172*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock Text="Select" FontSize="15"></TextBlock>
<ComboBox x:Name="FC" Margin="10,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" Width="78" >
</ComboBox>
<TextBlock Text="" Name="SelectedValueText" VerticalAlignment="Top" Margin="10,0,0,0"></TextBlock>
</StackPanel>
<StackPanel Grid.Row="1">
<TextBlock Text="This is Visible from A selection" Name="First" Visibility="Collapsed"></TextBlock>
</StackPanel>
<StackPanel Grid.Row="2">
<TextBlock Text="This is Visible from B selection" Name="Second" Visibility="Collapsed"></TextBlock>
</StackPanel>
</Grid>
</Window>
"#
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load( $reader )
$combobox=$Window.FindName('FC')
$combobox.Items.Add('A')
$combobox.Items.Add('B')
$SValue=$Window.FindName('SelectedValueText')
$First=$Window.FindName('First')
$Second=$Window.FindName('Second')
$combobox.Add_SelectionChanged({
$SValue.Text=$combobox.SelectedItem.ToString()
if ($SValue.Text -eq 'A')
{
$First.Visibility='Visible'
$Second.Visibility='Hidden'
[System.Windows.Forms.MessageBox]::Show("you select A")
}
else
{
$First.Visibility='Hidden'
$Second.Visibility='Visible'
[System.Windows.Forms.MessageBox]::Show("you Select B")
}
})
$Window.ShowDialog()
below is op window
currently my Close, Maximize and Minimize button not workin can any one please help me how I can write that events in Powershell?
You need to use the $Window.WindowState property to say whether the form should be minimized, maximized or restored to normal. The code below shows how it can be done.
#Minimize the Window
$MinimizeButton.Add_Click({
$Window.WindowState = 'Minimized'
})
$MaxRestoreButton.Add_Click({
If ($Window.WindowState -eq 'Normal') {
#Maximize the window
$Window.WindowState = 'Maximized'
} Else {
#Put window back to its normal size if maximized already
$Window.WindowState = 'Normal'
}
})
I would like to apply a TextTrimming option on a TextBox (Not a TextBlock).
The compiler tells me that the TextTrimming options is not a valid property of the Textbox.
I could do a fancy control that is a Textblock and once it's clicked will become a Textbox and conversely go back to being a Textblock once the focus is lost.
Before going this way I would like to know if a built-in function already exists (or is there a smarter way) to allow you to do that?
EDIT: What I want to have in the end is a TextBox which is trim (the full content will be display in a tooltip) but when the user select the TextBox (enter in "edit mode") the full content will be display (without trim) therefore the user will be able to modify the full text. when the TextBox lost the focus (go back to "view mode") the content will be trim again.
Thanks
Try a style like this (I've added background colours to make the change obvious):
<Style TargetType="TextBox">
<Setter Property="Background" Value="Yellow" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<TextBlock Text="{TemplateBinding Text}" TextTrimming="CharacterEllipsis" Background="Red" />
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Dan Puzey has a great answer, but I wanted to add more so that the style of the TextBlock appeared like a TextBox.
Here is the XAML style I came up with:
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border BorderThickness="1" CornerRadius="1">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFABADB3" Offset="0"/>
<GradientStop Color="#FFABADB3" Offset="0.044"/>
<GradientStop Color="#FFE2E3EA" Offset="0.060"/>
<GradientStop Color="#FFE3E9EF" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<TextBlock Padding="4,2,0,0" Text="{TemplateBinding Text}" TextTrimming="CharacterEllipsis"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
This is what the control looks like when it has no keyboard focus:
This is what the control looks like after gaining keyboard focus:
I think wat you are looking for is this
<TextBox Text="{Binding Path=String, Converter={StaticResource StringConverter}, ConverterParameter=Trim:Argument:AnotherArgument}" />
I hope it helps :)
It will call the trim function and pass any arguments, if you want.
You can also use split and pass the delimiters as arguments.
You can find more on Binding.Converter here
I would use different control template: template with trimming when text box is not focused, whereas text box is focused I would use the regular template to allow text selection.
Needs to replace TextBox control template.
<ControlTemplate TargetType="{x:Type TextBox}"
x:Key="ControlTemplateTextBoxNormal">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Border x:Name="ErrorElement"
Visibility="Collapsed"
BorderThickness="1.25"
BorderBrush="{StaticResource BrushError}">
<Grid>
<Polygon x:Name="toolTipCorner"
Panel.ZIndex="2"
Margin="-1"
Points="9,9 9,0 0,0"
Fill="{StaticResource BrushError}"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Polygon.ToolTip>
<ToolTip Style="{StaticResource ToolTipStyleError}"
Content="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" />
</Polygon.ToolTip>
</Polygon>
</Grid>
</Border>
<ScrollViewer x:Name="PART_ContentHost"
Padding="{TemplateBinding Padding}"
BorderThickness="0"
IsTabStop="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}" />
<TextBlock Text="{Binding Path=(behaviors:TextBoxBehaviors.WatermarkText), RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
IsHitTestVisible="False"
Visibility="Collapsed"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
Foreground="Gray"
x:Name="watermark" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused"
Value="False">
<Setter Property="Visibility"
TargetName="watermark"
Value="Visible" />
</Trigger>
<Trigger Property="Validation.HasError"
Value="True">
<Setter Property="Visibility"
TargetName="ErrorElement"
Value="Visible" />
</Trigger>
<!--<Trigger Property="behaviors:TextBoxBehaviors.WatermarkText"
Value="True">
<Setter Property="Visibility"
TargetName="ErrorElement"
Value="Visible" />
</Trigger>-->
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource {x:Type TextBox}}"
x:Key="TextBoxStyleTrimming">
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Validation.ErrorTemplate"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Border x:Name="ErrorElement"
Visibility="Collapsed"
BorderThickness="1.25"
BorderBrush="{StaticResource BrushError}">
<Grid>
<Polygon x:Name="toolTipCorner"
Panel.ZIndex="2"
Margin="-1"
Points="9,9 9,0 0,0"
Fill="{StaticResource BrushError}"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Polygon.ToolTip>
<ToolTip Style="{StaticResource ToolTipStyleError}"
Content="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" />
</Polygon.ToolTip>
</Polygon>
</Grid>
</Border>
<TextBlock Padding="{TemplateBinding Padding}"
Text="{TemplateBinding Text}"
TextTrimming="CharacterEllipsis"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}" />
<TextBlock Text="{Binding Path=(behaviors:TextBoxBehaviors.WatermarkText), RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
IsHitTestVisible="False"
Visibility="Collapsed"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
Foreground="Gray"
x:Name="watermark" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused"
Value="False">
<Setter Property="Visibility"
TargetName="watermark"
Value="Visible" />
</Trigger>
<Trigger Property="Validation.HasError"
Value="True">
<Setter Property="Visibility"
TargetName="ErrorElement"
Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsKeyboardFocused"
Value="True">
<Setter Property="Template"
Value="{StaticResource ControlTemplateTextBoxNormal}" />
</Trigger>
</Style.Triggers>
</Style>
You may create a control template for your TextBox that display the usual editor when focused, and a TextBlock with trimming when it's not.