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>
Related
I have a style for Buttons and now I want to apply it to RadioButtons, except that where a normal Button has a CornerRadius that is a single number (each corner is the same) I want to render the RadioButtons with different corner radii, like this:
I use a custom ControlTemplate for Button as well as a style:
<ControlTemplate TargetType="{x:Type ButtonBase}" x:Key="ButtonTemplate">
<Border Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
CornerRadius="22.5"
BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding Foreground}">
<TextBlock FontSize="14" FontWeight="Bold"
TextWrapping="Wrap" TextAlignment="Center"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="30 0"
Foreground="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"
Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
</ControlTemplate>
<Style TargetType="{x:Type ButtonBase}" x:Key="MainButton">
<Setter Property="Foreground" Value="{StaticResource IntBlue2}"/>
<Setter Property="TextBlock.Foreground" Value="{StaticResource IntBlue2}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="MinWidth" Value="132"/>
<Setter Property="Template" Value="{StaticResource ButtonTemplate}"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="LightSlateGray"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#66CDFF"/>
</Trigger>
</Style.Triggers>
</Style>
And I have a style for RadioButton that uses the Button template
<Style TargetType="RadioButton">
<Setter Property="Template" Value="{StaticResource ButtonTemplate}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource ForegroundPureWhite}"/>
<Setter Property="BorderThickness" Value="2"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Foreground" Value="{StaticResource DisabledGrey}"/>
</Trigger>
</Style.Triggers>
</Style>
Everything above works, until I want the custom CornerRadius for each RadioButton.
I've tried CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}}" inside the Border in the ControlTemplate, and <Setter Property="Border.CornerRadius" Value="22.5"/> inside the MainButton style, but it doesn't work (it doesn't apply the radius).
Binding CornerRadius="{TemplateBinding CornerRadius}" to the border in the template doesn't even compile, and setting CornerRadius on a Button or RadioButton, through the control tag or through a setter in the style, also doesn't compile.
How do I use one template, but different CornerRadius in each style or instance?
A ButtonBase has no CornerRadius property that you can bind to but you could use the Tag property:
<ControlTemplate TargetType="{x:Type ButtonBase}" x:Key="ButtonTemplate">
<Border Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
CornerRadius="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}"
...
<Style TargetType="RadioButton">
<Setter Property="Tag" Value="22.5" />
...
</Style>
<RadioButton ... Tag="0" />
I've created a WPF Style for a TextBox with an InputBindings (KeyBinding for Enter) inside the ControlTemplate.
Style and InputBindings is working fine for my TextBoxes, but if I use this Style for my TextBoxes the TabOrder/TabStop is not working any more.
This is the style:
<Style x:Key="TextBoxTemplate" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="FontSize" Value="16"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="5,0,5,5"/>
<Setter Property="Width" Value="150"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<TextBox Text="{TemplateBinding Text}">
<TextBox.InputBindings>
<KeyBinding Command="{Binding EnterKeyCommand}" Key="Enter"/>
</TextBox.InputBindings>
</TextBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How I add it to my TextBoxes:
<TextBox Text={Binding FirstName} Style="{StaticResource TextBoxTemplate}">
<TextBox Text={Binding LastName} Style="{StaticResource TextBoxTemplate}">
I think the problem is that I use a TextBox inside of the ControlTemplate.
But I don't know how to get running the InputBindings without the TextBox inside of the Template
Do you have any idea?
Thanks Phil
Modify your template to look like the original one plus your KeyBinding:
<Style x:Key="TextBoxTemplate" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="FontSize" Value="16"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="5,0,5,5"/>
<Setter Property="Width" Value="150"/>
<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">
<ScrollViewer.InputBindings>
<KeyBinding Command="{Binding EnterKeyCommand}" Key="Enter"/>
</ScrollViewer.InputBindings>
</ScrollViewer>
</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>
XAML:
<RadioButton Margin="15" Grid.Row="0" Grid.Column="3" Style=" {StaticResource SpeedButtonStyle}" Content="TEST"/>
Style:
<!-- Speed Button Style -->
<Style x:Key="SpeedButtonStyle" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="FontSize" Value="18px"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Background" Value="{StaticResource SidePanelButtonBgInactive}"/>
<Setter Property="Foreground" Value="White"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource SidePanelButtonBgActive}"/>
<Setter Property="Foreground" Value="{StaticResource SidePanelButtonFgActive}"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="BorderThickness" Value="30"/>
<Setter Property="BorderBrush" Value="White" />
<Setter Property="Background" Value="{StaticResource SidePanelButtonBgActive}"/>
<Setter Property="Foreground" Value="{StaticResource SidePanelButtonFgActive}"/>
</Trigger>
</Style.Triggers>
</Style>
I am trying to change the size of the border on my radio button which is styled like a toggle button. I can change the colour of the border but not the size. it seems to be using the default size which is realy thin.
I'm using my templated ToggleRadioButton and you can achieve it by binding BorderThickness to its templated parent.
<Style TargetType="RadioButton" x:Key="SpeedButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ControlTemplate.Resources>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ControlTemplate.Resources>
<ToggleButton IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}">
</ToggleButton>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="18px"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="White"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="DarkRed"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="BorderThickness" Value="5"/>
<Setter Property="BorderBrush" Value="White" />
<Setter Property="Background" Value="Green"/>
<Setter Property="Foreground" Value="LightSeaGreen"/>
</Trigger>
</Style.Triggers>
</Style>
EDIT:
I think you had completely different problem. Trigger on IsMouseOver or IsChecked doesn't get rid of default Windows hover colours. So you have to get rid of that, which is achieved but templating ToggleButton with a Border on top of templating your RadioButton with that styled ToggleButton. Note that if you would want to modify it more, you have to bind it's properties in the Border as well in ToggleButton. Difference between TemplateBinding and Binding on TemplatedParent is here and furthermore TemplateBinding is only One Way, so IsChecked should be on TemplatedParent.
This should work now (at least for me it did in new project), just replace the colours.
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>
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>