WPF: How to implement Blend's Dark theme for context menu - wpf

I have added this xaml in my App.xaml:
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="Background" Value="{StaticResource ShadeBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource ShadeBrush}" />
<Setter Property="Foreground" Value="White" />
</Style>
This gets me most of the way towards a dark theme....
How do I fix this problem with the menu items:
I suspect I need to modify the style or template for the menuitem.
Thanks.
UPDATE: Using Snoop (mentioned by Andy, thanks), I find this when selecting the white rect:

For whoever comes here next, I solved this problem by setting the template like so:
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="Background" Value="{StaticResource ShadeBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource ShadeBrush}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<Border Uid="Border_93">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Tag"
Value="{DynamicResource
{x:Static SystemParameters.DropShadowKey}}"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding Tag,
RelativeSource={RelativeSource Self}}"
Value="True">
<Setter Property="Background"
Value="Transparent"/>
<Setter Property="Padding"
Value="0,0,5,5"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect
BlurRadius="4"
Opacity="0.8"
ShadowDepth="1"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Uid="Border_50">
<ScrollViewer CanContentScroll="True"
Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer,
TypeInTargetAssembly={x:Type FrameworkElement}}}"
Uid="ScrollViewer_9">
<ItemsPresenter
KeyboardNavigation.DirectionalNavigation="Cycle"
Margin="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Uid="ItemsPresenter_5"/>
</ScrollViewer>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

IntegerUpDown Style Up/down buttons

I am trying to style a integerupdown(Xceed framework) control and my wpf knowledge in lacking. So far I have gotten it styled for everything but the OnMouseOver which still looks like a "normal" button mouseover.
How can I set the style on mouseover? Remove the blue automatic background.
<UserControl.Resources>
<Style x:Key="{x:Static theme:ResourceKeys.SpinnerButtonStyleKey}" TargetType="RepeatButton">
<Setter Property="Foreground" Value="#fff" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="#555555"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"></Setter>
<Setter Property="Background" Value="Black"></Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type xctk:IntegerUpDown}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static theme:ResourceKeys.GlyphNormalForegroundKey}" Color="#e9e9ee"/>
</Style.Resources>
</Style>
</UserControl.Resources>
You should define a custom RepeatButton style for the themes:ResourceKeys.SpinnerButtonStyleKey resource:
<xctk:IntegerUpDown
xmlns:themes="clr-namespace:Xceed.Wpf.Toolkit.Themes;assembly=Xceed.Wpf.Toolkit"
xmlns:chrome="clr-namespace:Xceed.Wpf.Toolkit.Chromes;assembly=Xceed.Wpf.Toolkit">
<xctk:IntegerUpDown.Resources>
<Style x:Key="{x:Static themes:ResourceKeys.SpinnerButtonStyleKey}"
TargetType="RepeatButton">
<Setter Property="Background" Value="{DynamicResource {x:Static themes:ResourceKeys.ButtonNormalBackgroundKey}}" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static themes:ResourceKeys.ButtonNormalOuterBorderKey}}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="2,2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Grid>
<chrome:ButtonChrome x:Name="Chrome"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
CornerRadius="{DynamicResource {x:Static themes:ResourceKeys.SpinButtonCornerRadiusKey}}"
RenderEnabled="{TemplateBinding IsEnabled}"
RenderMouseOver="False"
RenderNormal="True"
RenderPressed="{TemplateBinding IsPressed}"
SnapsToDevicePixels="true" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</xctk:IntegerUpDown.Resources>
</xctk:IntegerUpDown>

TextBox focus border AND placeholder text

I want to create a textbox with placeholder text, that doesn't turn blue on mouse over/focus.
Through experimentation and scouring the internet I've found that the following code is the simplest solutions to the individual problems.
Placeholder Text
<Style x:Key="PlaceHolderTextBox" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<TextBox Text="{Binding Path=Text,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
x:Name="textSource"
Background="Transparent"
Panel.ZIndex="2" />
<TextBox Text="{TemplateBinding Tag}" Background="{TemplateBinding Background}" Panel.ZIndex="1">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="">
<Setter Property="Foreground" Value="Gray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Focus Border replacement
<Style x:Key="CustomBorderTextBox" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#000000"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="Yellow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, you can't just combine them. Putting both the grid and border in one ControlTemplate doesn't work, so how would you create a style that replaces the border and also displays placeholder text (preferably without code-behind)?
combine them by adding a panel (Grid) which can have more than one child.
I took "CustomBorderTextBox" as base and added placehold TextBlock which becomes visible when text is empty. Placeholder text is stored TextBox.Tag
<Style x:Key="CustomTextBox" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
<TextBlock Text="{TemplateBinding Tag}" IsHitTestVisible="False">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, RelativeSource={RelativeSource AncestorType=TextBox}}"
Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#000000"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="Yellow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF TabStop TextBoxes not working on Win10

I am struggling with testing of my wpf application, in which I have a window with TextBoxes, that contain a custom style from Application.Resources
The style implements a placeholder, and because it interfered with tabbing(it focused the placeholder instead of TB content) I had to add some IsTabStop code.
It's working perfectly fine when Im debugging and also the release exe on Win7, but the tabbing doesn't work on Win10, it simply ignores TextBoxes and just tabs trough other controls that don't have this style implemented.
Any help would be great!
Here is the style code:
<Style x:Key="placeHolderNoline" TargetType="{x:Type TextBox}" BasedOn="{StaticResource tb}">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<TextBox Text="{Binding Path=Text,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
x:Name="textSource"
Background="Transparent"
Panel.ZIndex="2"
BorderThickness="0,0,0,0"/>
<TextBox Text="{TemplateBinding Tag}" Background="{TemplateBinding Background}" Panel.ZIndex="1" BorderThickness="0" IsTabStop="False">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="">
<Setter Property="Foreground" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Edit: tb style:
<Style TargetType="TextBox" x:Key="tb">
<Setter Property="Foreground" Value="WhiteSmoke"/>
<Setter Property="Background" Value="#33FFFFFF"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
A ControlTemplate of a TextBox is not supposed to include another or two other TextBox elements.
Try this style:
<Style x:Key="placeHolderNoline" TargetType="TextBox" BasedOn="{StaticResource tb}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="#FFABAdB3"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<TextBlock Text="{TemplateBinding Tag}" Foreground="LightGray" Background="{TemplateBinding Background}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Style content via setters v ContentTemplate

The xaml for the first style works as I want, producing a button with a Wingding glyph using setters to lay out the content and it's properties. The second version of this style is trying to do the same thing but with a DataTemplate for the Content, but it just displays the type of a DataTemplate (ie, System.Windows.DataTemplate).
Why won't the 2nd version display the same content as the 1st?
Assuming the fix is trivial, would one version of the style be preferable over the other for any reason beyond personal preference?
NOTE: I am showing the bindings and triggers in case there is something in there that is affecting the content, but it's only the the first part of the style that varies
Cheers,
Berryl
Style 1
Displays:
<Style x:Key="EditCommandButtonStyle" TargetType="{x:Type Button}" >
<Setter Property="Content" Value="a" />
<Setter Property="Foreground" Value="Navy" />
<Setter Property="FontFamily" Value="Wingdings 3" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="18" />
<Setter Property="Width" Value="30" />
<Setter Property="Height" Value="Auto" />
<!--What makes it an Edit button-->
<Setter Property="Command" Value="{Binding ActivateThisSatelliteVmCommand}"/>
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock>
<TextBlock.Text>
<Binding Path="HeaderLabel" StringFormat="{resx:Resx ResxName=Smack.Core.Presentation.Resources.MasterDetail, Key=Item_Edit_Label}"/>
</TextBlock.Text>
</TextBlock>
</Setter.Value>
</Setter>
<!-- WHen its available -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="theBorder" CornerRadius="4">
<ContentPresenter x:Name="theContent" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter TargetName="theContent" Property="Visibility" Value="Hidden"/>
<Setter TargetName="theBorder" Property="Background" Value="Transparent"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
<Setter TargetName="theBorder" Property="Background" Value="Orange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Style 2
Displays "System.Windows.DataTemplate"
<Style x:Key="EditCommandButtonStyle" TargetType="{x:Type Button}" >
<Setter Property="Content">
<Setter.Value>
<DataTemplate>
<TextBlock Text="a" FontFamily="Wingdings 3" FontWeight="Bold" FontSize="18" Foreground="Navy" />
</DataTemplate>
</Setter.Value>
</Setter>
<!--What makes it an Edit button-->
<Setter Property="Command" Value="{Binding ActivateThisSatelliteVmCommand}"/>
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock>
<TextBlock.Text>
<Binding Path="HeaderLabel" StringFormat="{resx:Resx ResxName=Core.Presentation.Resources.MasterDetail, Key=Item_Edit_Label}"/>
</TextBlock.Text>
</TextBlock>
</Setter.Value>
</Setter>
<!-- When its available -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="theBorder" CornerRadius="4">
<ContentPresenter x:Name="theContent" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter TargetName="theContent" Property="Visibility" Value="Hidden"/>
<Setter TargetName="theBorder" Property="Background" Value="Transparent"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
<Setter TargetName="theBorder" Property="Background" Value="Orange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Your Content property is set to a DataTemplate
DataTemplates are meant to be used with Template properties, and not directly inserted into the VisualTree via the Content property
Change your Style Setter to set the ContentTemplate instead of Content and it should work fine
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="a" FontFamily="Wingdings 3" FontWeight="Bold" FontSize="18" Foreground="Navy" />
</DataTemplate>
</Setter.Value>
</Setter>
As for your second question, I prefer the first because its simpler, and I think it may contain fewer elements in the Visual Tree (I'd have to double-check that)
I found another way to resolve this issue:
<Style x:Key="DefaultButtonBaseStyle" TargetType="{x:Type ButtonBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Grid>
<Border x:Name="BackBorder" Margin="0" Padding="0"
BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding BorderBrush}"/>
<Border x:Name="FrontBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}"
Margin="0" Padding="{TemplateBinding Padding}"
CornerRadius="{Binding ElementName=BackBorder, Path=CornerRadius}">
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Set border image for Textbox on focus

I want to set an image as border when a text box has got focus. I know how to set the border color when the text box gets focus as follows
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderThickness" Value="2.20" />
<Setter Property="BorderBrush" Value="#f8cb1c" />
</Trigger>
</Style.Triggers>
</Style>
but how can I set an image for border or around a textbox.
<Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
<Grid>
<Image x:Name="imgctrl" Stretch="Fill"/>
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</Microsoft_Windows_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Source" TargetName="imgctrl" Value="5.jpg"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I would hide the default TextBox border, and place it on top of an Image containing the border image you want, and show the Image when the TextBox is selected
<Style x:Key="BorderImageStyle" TargetType="{x:Type Image}">
<Setter Property="IsVisible" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SomeTextBox, Path=IsKeyboardFocusWithin}" Value="True">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
</Style>
<Grid>
<Image x:Name="BorderImage" ... />
<TextBox x:Name="SomeTextBox" BorderThickness="0" Margin="20" ... />
</Grid>

Resources