Dotted border on ListBoxItem in WPF - wpf

How can I make the default border on my ListBoxItems a dotted border? See following way of styling it:
<Grid.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Height" Value="30" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
<Setter Property="BorderBrush" Value="Silver" />
<Setter Property="Content" Value="" />
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="3">
<Setter Property="BorderBrush" Value="Black"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
Here I make the AlternationIndex 0, 1 and 2 to a dotted border instead of a solid line. How can this be done?

Try this:
<Window.Resources>
<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
<!-- SimpleStyles: ListBoxItem -->
<Style TargetType="ListBoxItem" x:Key="ListBoxItemTemplate">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Rectangle x:Name="Rectangle" Fill="Transparent" Stroke="Black"
StrokeDashCap="Square" StrokeThickness="0" SnapsToDevicePixels="True">
<Rectangle.StrokeDashArray>
<sys:Double>5</sys:Double>
</Rectangle.StrokeDashArray>
</Rectangle>
<Border
Name="Border"
Padding="2"
BorderThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness}"
BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush}">
<ContentPresenter />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Rectangle" Property="StrokeThickness" Value="1" />
<Setter TargetName="Border" Property="BorderThickness" Value="0" />
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Rectangle" Property="Fill" Value="{StaticResource SelectedBackgroundBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource ListBoxItemTemplate}">
<Setter Property="Height" Value="30" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
<Setter Property="BorderBrush" Value="Silver" />
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="3">
<Setter Property="BorderBrush" Value="Black"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<ListBox>
<ListBoxItem Content="Item 1" />
<ListBoxItem Content="Item 2" />
<ListBoxItem Content="Item 3" />
<ListBoxItem Content="Item 4" />
</ListBox>
</StackPanel>
So I put a rectangle bellow the actual border in the control template. The rectangle can have its border be dotted, or dashed or w/e (to make the dash smaller just change the part to 2, 1 is not noticeable). So the default value of the rectangle's border thickness is 0, but when selected I set the thickness to 1 so it's visible. I made some border properties to be binded to its templated parent too, so it can look like what you set on your style (brush silver, thickness 0,0,0,1).

Related

Changing the button label foreground on focus with label inside content

I have a button that I need to change the background and foreground color of when the button is in focus. I have the background color change working, but cannot get the foreground color change (on the label) to work.
I want to do this in XAML only.
My Button:
<Button Style="{StaticResource ModButtonWhite}"
Name="btnConnect"
Height="30"
Click="btnConnect_Click"
Width="75"
Margin="0,0,15,0">
<Label Name ="btnConnectLabel" Content="Re-_Connect" />
</Button>
My Style:
<Style TargetType="Button"
x:Key="ModButtonWhite">
<Setter Property="Foreground"
Value="White" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="5"
BorderThickness="1"
BorderBrush="White">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsFocused"
Value="True">
<Setter Property="Background"
Value="White" />
<Setter Property="Foreground"
Value="DeepSkyBlue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Resources>
<Style TargetType="Label">
<Setter Property="Foreground"
Value="White" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Foreground"
Value="DeepSkyBlue" />
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="White" />
<Setter Property="Opacity"
Value=".4" />
<Setter Property="Foreground"
Value="DeepSkyBlue" />
</Trigger>
</Style.Triggers>
All you need to do is to bind the Label.Foreground to the Button.Foreground. No need of any additional styles defined in the Style.Resources dictionary. Just the plain style to override the Button.Template:
<Window>
<Window.Resources>
<Style TargetType="Button"
x:Key="ModButtonWhite">
<Setter Property="Foreground"
Value="White" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="5"
BorderThickness="1"
BorderBrush="White">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsFocused"
Value="True">
<Setter Property="Background"
Value="White" />
<Setter Property="Foreground"
Value="DeepSkyBlue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Button Style="{StaticResource ModButtonWhite}">
<Label Content="Click me!"
Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}" />
</Button>
</Window>

WPF TabItem format date

I am trying to create a style for a TabControl to achieve 2 goals:
Display the selected TabItem with a different background color and in bold.
Format the tab header text, bound to a date in the view model, to hours and minutes like "15:45".
I almost succeeded but the header text is also displaying the date part.
Besides it is displaying 03:45 instead of 15:45.
see screenshot here
Here is the XAML code I am using:
<TabControl ItemsSource="{Binding MC}" >
<TabControl.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Background" Value="#01535F" />
<Setter Property="Foreground" Value="Azure" />
<Setter Property="FontSize" Value="16" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" BorderThickness="1,1,1,0" BorderBrush="Black" Margin="1,1">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
/>
<!--<HeaderedContentControl Header="{Binding Path=MarketStartTime, StringFormat={}{0:HH:mm}}" />-->
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
<Setter TargetName="Panel" Property="Background" Value="#003F44" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="#01535F" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<HeaderedContentControl Header="{Binding Path=MarketStartTime, StringFormat={}{0:HH:mm}}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
</TabControl>
Thanks in advance for any help.
I think this is what you're looking for:
<TabControl ItemsSource="{Binding MC}">
<TabControl.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Background" Value="#01535F" />
<Setter Property="Foreground" Value="Azure" />
<Setter Property="FontSize" Value="16" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" BorderThickness="1,1,1,0" BorderBrush="Black" Margin="1,1">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
<Setter TargetName="Panel" Property="Background" Value="#003F44" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="#01535F" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=MarketStartTime, StringFormat={}{0:HH:mm}}"></TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
The ItemTemplate is for the header area, the ContentTemplate is for what is showing in the content area. That ContentPresenter in the ContentTemplate will instantiate the controls from the ItemTemplate.

WPF Tab Styling

I am trying to style my WPF TabControl. I basically want to get the tab control to have a transparent background, with a white border and text. I want the selected tab to have a White Background and Transparent Text (or any colour text!). Essentially a 2 colour tab.
However, I cannot override the selected tab appearance - this shows as white. And my child textboxes are taking the style of the TabItem font. Note, in the screen shot my labels have their own style set so do not take the TabItem font.
I have the following XAML in place to do this. Ideally I want to create the styles so that I can reuse across the application.
Resource Dictionary
<ResourceDictionary 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">
<Style x:Key="Tabs" TargetType="TabControl">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="White"/>
</Style>
<Style x:Key="TabItemStyle" TargetType="TabItem">
<Setter Property="Foreground" Value="White" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="FontSize" Value="16" />
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="False">
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Then the XAML MarkUp
<TabControl Style="{StaticResource Tabs}">
<TabItem Header="General" Style="{StaticResource TabItemStyle}">...</TabItem>
<TabItem Header="Details" Style="{StaticResource TabItemStyle}">...</TabItem>
<TabItem Header="Info" Style="{StaticResource TabItemStyle}">...</TabItem>
<TabItem Header="More Stuff..." Style="{StaticResource TabItemStyle}">...</TabItem>
</TabControl>
How can I style my tabs to be and prevent the children from sizing?
Your DataTriggers don't work. To fix it change RelatveSource to Self
Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}"
However I would suggest to change them to Triggers like so:
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="White"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
You should create control template for TabItem.
This sample change TabItem background to Transparent and Text color to White.
You can use own color schema.
<Window.Resources>
<Style TargetType="TabControl">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderBrush"
Value="White" />
</Style>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border"
Margin="0,0,-4,0"
Background="{x:Static Brushes.White}"
BorderBrush="{x:Static Brushes.White}"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0">
<ContentPresenter x:Name="ContentSite"
Margin="12,2,12,2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Panel.ZIndex"
Value="100" />
<Setter TargetName="Border"
Property="Background"
Value="{x:Static Brushes.Transparent}" />
<Setter TargetName="Border"
Property="BorderThickness"
Value="1,1,1,0" />
<Setter Property="TextBlock.Foreground"
Value="White" />
<!--<Setter Property="TextBlock.Foreground"
Value="Transparent" />-->
</Trigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter TargetName="Border"
Property="Background"
Value="{x:Static Brushes.White}" />
<Setter TargetName="Border"
Property="BorderBrush"
Value="{x:Static Brushes.White}" />
<Setter Property="Foreground"
Value="{x:Static Brushes.White}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="SkyBlue">
<TabControl Margin="20">
<TabItem Header="TabItem #1">
<TextBox>Tab Item #1 content</TextBox>
</TabItem>
<TabItem Header="TabItem #2">
<TextBox>Tab Item #1 content</TextBox>
</TabItem>
<TabItem Header="TabItem #3">
<TextBox>Tab Item #1 content</TextBox>
</TabItem>
</TabControl>
</Grid>

How can I bind to tag from style in wpf?

I'm implementing a search textbox; could you please help me with binding to TextBox.Tag?
Style
<Style x:Key="SearchTextBox" TargetType="{x:Type TextBox}">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}" Foreground="{StaticResource SearchTextBox.Foreground}" FontSize="{StaticResource SearchTextBox.FontSize}"/>
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Setter Property="FontSize" Value="{StaticResource SearchTextBox.FontSize}" />
<Setter Property="Foreground" Value="{StaticResource SearchTextBox.TextForeground}" />
<Setter Property="MinWidth" Value="200" />
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
Usage
<TextBox Style="{StaticResource SearchTextBox}" Tag="Search templates" />
How can I get the binding to work?
This article here is extremely similar to yours: WPF Bind to parent property from within nested element using style
Though, it doesn't really give a code sample, so here's some xaml you can use as an alternative to your current approach.
<Style x:Key="SearchTextBox" BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Style.Setters>
<Setter Property="Tag" Value=""/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<TextBlock x:Name="textBlock" Opacity="0.345" Text="{TemplateBinding Tag}" TextWrapping="Wrap" Visibility="Hidden" />
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="False" />
<Condition Property="Text" Value="" />
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="textBlock" Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
And you'll still write your textbox code the same way you already had it:
<TextBox Style="{StaticResource SearchTextBox}" Tag="Search templates" />

WPF buttons (image & label) shadowing

I want to create buttons which have a image and a text included and get a nice shadowing. Particularly, I want the image and label have a light grey shadowing, but when moving the mouse over the button I'd like a kind of blue shadowing. Moving away sets it back to light grey. I would need some help as I just can't figure out how to achive it (I'm new to WPF).
The Buttons looks like ...
<Button>
<Button.Content>
<StackPanel Orientation="Vertical">
<Image Source="Images/preferences-system.png" />
<Label HorizontalAlignment="Center">Settings</Label>
</StackPanel>
</Button.Content>
</Button>
The Canvas goes ...
<Canvas DockPanel.Dock="Left" Background="#FF349EBC">
<Canvas.Resources>
<DropShadowEffect x:Key="dropMouseOverShadow" Color="#FFD9EDF3" Opacity="80" Direction="270" />
<DropShadowEffect x:Key="dropLightShadow" Color="LightGrey" Opacity="10" Direction="270" BlurRadius="20" />
<Style TargetType="{x:Type Button}">
<Style.Setters>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Foreground" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" CornerRadius="2">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" Value="{StaticResource dropMouseOverShadow}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
<Style TargetType="{x:Type Image}">
<Style.Setters>
<Setter Property="Effect" Value="{StaticResource dropLightShadow}" />
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type Label}">
<Style.Setters>
<Setter Property="FontSize" Value="18" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontFamily" Value="Gill Sans MT" />
<Setter Property="Effect" Value="{StaticResource dropLightShadow}" />
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</Canvas.Resources>
What I get is a light grey shadowing on image and labels on begin. Moving the mouse over the button the grey and light blue get mixed. When moving further on the image it gets the light blue only. The same goes for the label.
How can I achive switching the shadowning to light blue when I mouse over the button and not the image and label itself? Anyone an idea or an completly other approach?
Apply the LightGray Effect to the ContentPresenter. Then on the IsMouseOver Trigger, set the Effect property of the ContentPresenter to the blue Effect.
NOTE: Accomplish this by setting the x:Name attribute of the ContentPresenter, then accessing the ContentPresenter by name via the Setter using TargetName.
NOTE: Remove the various other Effect settings in the styles of the child elements. Applying the Effect to the ContentPresenter causes the child elements to inherit the Effect.
<Canvas DockPanel.Dock="Left" Background="#FF349EBC">
<Canvas.Resources>
<DropShadowEffect x:Key="dropMouseOverShadow" Color="#FFD9EDF3" Opacity="80" Direction="270" />
<DropShadowEffect x:Key="dropLightShadow" Color="LightGrey" Opacity="10" Direction="270" BlurRadius="20" />
<Style TargetType="{x:Type Button}">
<Style.Setters>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Foreground" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" CornerRadius="2">
<ContentPresenter x:Name="cp" Effect="{StaticResource dropLightShadow}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="cp" Property="Effect" Value="{StaticResource dropMouseOverShadow}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
<Style TargetType="{x:Type Label}">
<Style.Setters>
<Setter Property="FontSize" Value="18" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontFamily" Value="Gill Sans MT" />
</Style.Setters>
</Style>

Resources