I have a custom stye applied to textboxes in my WPF page, however I have now changed TextBoxes to editable ComboBoxes and need to apply the style to fit the new editable ComboBoxes. This is the current code:
<Style TargetType="ComboBox">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="BorderBrush" Value="Silver"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border Name="Border" Padding="1" Background="#FFFFFF" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" >
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="#EEEEEE"/>
<Setter TargetName="Border" Property="BorderBrush" Value="#EEEEEE"/>
<Setter Property="Foreground" Value="#888888"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The above is what I have managed to change, however I am unsure of what else needs to be changed. The editable ComboBox is essentially a textbox with a drop down, so I assumed that it would remain pretty much the same. The TextBoxBase seems to be the biggest issue.
After creating a new sample project, the problem seems to be a bug with Windows 8.
Related
for some reason in my code behind (WPF), the "setter" section makes the text box not function anymore. I can't type in it or add any functionality to it. When I remove the setter section, the text box works. I've seen other people online do it this exact way and it works for them but I'm not sure what I'm doing wrong.
Here's what I have in the main window.
<TextBox Style="{DynamicResource inputBox}" Margin="0,50,125,0"/>
And here's what I have in the code behind
<Style x:Key="inputBox" TargetType="TextBox">
<Setter Property="Padding" Value="3"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="65"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Text" Value=""/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<!--This setter somehow breaks the text box-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="Transparent" CornerRadius="5" BorderThickness="1" BorderBrush="Black">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks
Your template only shows the border. Not the content. It needs a PART_ContentHost Do yourself a favor and copy the existing template and edit that. You can do this on the XAML designer. For example, here is what it looks like when I copy it on mine:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 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="{StaticResource TextBox.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
I have a simple window with a Grid that has a TextBox. I set IsEnabled on the Grid to False.
<Grid IsEnabled="False">
<TextBox Text="Foo"/>
<TextBlock Text = "Bar"/>
<TextBox Text="Bazz" Foreground ="Orange"/>
</Grid>
XAML Designer shows all three elements are now grayed in response to IsEnabled = false, and if I debug, the text in all three are grayed out in the app. I want to control the value of the grayed foreground state to something darker.
Since the three inner controls retain their color when disabled, it appears WPF conveys "disabled" via an opacity change. Where/how can I override this? It would be great if XAML Designer shows the desired darker text.
Indeed, the deafult style for a TextBox just sets a lower opacity.
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
In order to change this, you have to create your own TextBox style or copy the default style and its control template e.g. using Visual Studio or Blend. From there, customize the disabled state by addding setters to the trigger shown above.
<SolidColorBrush x:Key="TextBox.Static.Border" Color="#FFABAdB3"/>
<SolidColorBrush x:Key="TextBox.MouseOver.Border" Color="#FF7EB4EA"/>
<SolidColorBrush x:Key="TextBox.Focus.Border" Color="#FF569DE5"/>
<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<!-- ...add or change setters here. -->
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
<Condition Property="IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
</MultiTrigger>
</Style.Triggers>
</Style>
As an example, this trigger sets the foreground color to red with half opacity.
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.5"/>
<Setter Property="Foreground" Value="Red"/>
</Trigger>
Then, reference the style in the TextBoxes where you want to apply it.
<Grid IsEnabled="False">
<TextBox Style="{StaticResource TextBoxStyle}" Text="Foo"/>
<TextBlock Style="{StaticResource TextBlockStyle}" Text = "Bar"/>
<TextBox Style="{StaticResource TextBoxStyle}" Text="Bazz" Foreground ="Orange"/>
</Grid>
If you want to automatically apply the style to all TextBoxes within the scope of the resources where you created the style, remove its x:Key to make it implicit and do not set or reference a style.
<Style TargetType="{x:Type TextBox}">
<Grid IsEnabled="False">
<TextBox Text="Foo"/>
<TextBlock Text = "Bar"/>
<TextBox Text="Bazz" Foreground ="Orange"/>
</Grid>
The default TextBlock style does not have a special appearance for the disabled state. You can adapt it similarly to the TextBox style. Here is an example.
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="TextTrimming" Value="None"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
I'm relatively new to WPF and XAML, and I'm trying to override the style of the TabItems in my TabControl. At the top of my xaml file I have this:
<Window.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" Margin="0,5,0,0" Background="Transparent"
BorderBrush="LightGray" BorderThickness="1,1,1,1">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header" Margin="12,2,12,2"
RecognizesAccessKey="True">
</ContentPresenter>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="100"/>
<Setter TargetName="Border" Property="Background" Value="#EEE9ED"/>
<Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,1"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="IsEnabled" Value="False"/>
<Setter TargetName="Border" Property="Background" Value="LightGray"/>
<Setter TargetName="Border" Property="BorderBrush" Value="Black"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</Window.Resources>
It applies the style to all TabItems, and that works. It all looks how I want it to. The problem is that now I can't click on any of them. It doesn't look like any of the style guides online have encountered this problem, so it's probably just something really stupid that I'm doing, but I really can't figure it out.
The problem is <Setter Property="IsEnabled" Value="False"/>. A TabItem with IsEnabled set to False cannot be selected. Since all non-selected TabItems are disabled by your Style, this prevents any of them from being selected.
I've the following styles for my datagrid rows and cells :
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Margin" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Foreground" Value="{StaticResource ResourceKey=CouleurTexte}" />
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Cursor" Value="Arrow"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource ResourceKey=CouleurDataGridRowSelected}"/>
<Setter Property="Foreground" Value="{StaticResource ResourceKey=CouleurTexteBouton}" />
<Setter Property="BorderBrush" Value="{StaticResource ResourceKey=CouleurDataGridBorderSelected}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource ResourceKey=CouleurDataGridRowHover}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Padding" Value="5" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Cursor" Value="Arrow"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock Background="Transparent" Name="texte" TextTrimming="CharacterEllipsis"
Height="auto" Width="auto" VerticalAlignment="Center" Text="{Binding Text}"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource ResourceKey=CouleurDataGridRowSelected}"/>
</Trigger>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" Value="True">
</DataTrigger>
</Style.Triggers>
</Style>
with my datagrid defined with stars in the width of my columns (so they can take all the space of the window).
I want to set a border around a full row when its selected. My styles work fine until I set BorderThickness to 1 in the datagrid row.
When I do the datagrid show the horizontal scrollbar to scroll only one (maybe 2) pixel (the one from the border added).
When I don't have all my columns with "" as width it works fine but I need to find a way to make it work with "". How can I avoid this behavior ? It seems the border come on the outside of the row ?
Thank you
I remember having this issue and spending a good lot of time to fix it, lastly had to fix it by having a -ve margin on you control, You can set a -ve margin equal to your border width and see the unwanted scrollbar going away.
I've found a trick to do it thanks to Muds' answer.
With his solution I had troubles with alternate row background, So I've checked using Snoop and tried to change different values and it appears that we can "solve" this issue by setting a new template for the datagridRow with margin="-1,0,-1,0" (my border thickness is 1) on the DataGridCellsPresenter.
I have requirement to show the toolbar button border on mouse Hovering and otherwise hide it. I tried to do the following:
<Style x:Key="{x:Static ToolBar.ButtonStyleKey}" TargetType="Button" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="Control.Background" Value="Transparent" />
<Setter Property="Control.BorderBrush" Value="Transparent" />
<Setter Property="Control.BorderThickness" Value="1" />
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Control.BorderBrush" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
but it doesn't work as expected. What I expect to happen is that on mouse over the border will turn into red color otherwise will be transparent. Actual result was that it act like in the default behavior with the default colors.
Surely I'm doing something wrong.
Does anyone knows what is it?
Try the following to override button style identified by the ToolBar.ButtonStyleKey when used inside a ToolBar.
<ToolBar.Resources>
<Style x:Key="{x:Static ToolBar.ButtonStyleKey}" TargetType="{x:Type Button}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="BorderThickness" Value="4"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Bd"
SnapsToDevicePixels="true"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="Bd" Value="Orange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToolBar.Resources>