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>
Related
No matter what I try I can't set get the trigger IsMouseOver and IsPressed to change the Foreground.
I have been trying to alter it in the Button itself.
<Button (STUFF HERE)>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="#FF373737"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Foreground" Value="#FF4D4D4E"/>
</Trigger>
</Button>
I have been trying to look it up, but I am pretty amateur with XAML.
here the general layout for styling controls:
<Button Content="OK">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers >
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="#FF373737"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Foreground" Value="#FF4D4D4E"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
If you want to reuse the style, then save it to a resourcedictionary as a named style and you can refer to it on your controls
You have to create a style where you put the Triggers. Add this style to any resource dictionary in scope, e.g. the Window.Resources or the application resources if you want to reuse it across the application. If you omit the x:Key, you make it implicit and therefore apply to all Buttons in scope.
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#FF373737"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="#FF4D4D4E"/>
</Trigger>
</Style.Triggers>
</Style>
Then reference that style in the Button.
<Button Style="{StaticResource MyButtonStyle}" .../>
Alternatively, you could also directly assign the style to the Button if it is the only one.
<Button Content="Styled">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#FF373737"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="#FF4D4D4E"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Note that while this works for the Foreground property, it does not for properties like Background as they are defined in the ControlTemplate triggers which take precedence over a style. In order change those, you have to copy and adapt the Button ControlTemplate.
Update for your comment. Maybe you understand the Foreground property wrong. It is used for the text color of the content, not the color of the button itself. The "blue-ish" tint is determined by the Background property and as stated above, you have to edit the ControlTemplate for that.
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" StrokeDashArray="1 2" SnapsToDevicePixels="true" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FF373737"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FF4D4D4E"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<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" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="contentPresenter" 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="{StaticResource Button.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</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'm trying to recreate a material design look & feel for a button. For the focused (hovered) state the guidelines say to make a 12 % #000000 shade over the button. I was wondering how this could be achieved in WPF.
I've been looking around a good option would be to add a non-hittable rectangle over the button with a 12 % opacity and a color of #000000. I want to implement this as a style, but I have no idea how to do that.
My style looks like this at moment:
<Style x:Key="MaterialRaisedButton" TargetType="ToggleButton">
<Setter Property="Padding" Value="8 0"/>
<Setter Property="Margin" Value="8 6 8 6"/>
<Setter Property="Height" Value="36"/>
<Setter Property="MinWidth" Value="64"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="{StaticResource MaterialSecondaryColorBrush}"/>
<Setter Property="Effect" Value="{StaticResource z-depth2}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Rectangle RadiusX="4" RadiusY="4" Fill="#000000" Opacity="0.12"/>
<Border CornerRadius="4" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource Material12Black}"/>
</Trigger>
</Style.Triggers>
</Style>
If there are any other methods of doing this, I'm all ear as well :)
In the fill of the rectangle you can specify opacity in the hex color like #00000000, the first two values are the opacity. So 12% would be #1e000000. The following will show .5 opacity rectangle when mouse is over other wise opacity is 0.
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Opacity" Value="0"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value=".5"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="false">
<Setter Property="Opacity" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
Update:
If anybody wants to reuse the code for a material-like button, the code is below. I used the ripple effect from this stackoverflower along with the shadows from this source. Hopefully this can help others recreating Material design without the toolkit :)
<Style x:Key="MaterialRaisedButton2" TargetType="Button">
<Setter Property="Padding" Value="8 0"/>
<Setter Property="Margin" Value="8 6 8 6"/>
<Setter Property="Height" Value="36"/>
<Setter Property="MinWidth" Value="64"/>
<Setter Property="Foreground" Value="{StaticResource NormalTextBrush}"/>
<Setter Property="Background" Value="{StaticResource MaterialSecondaryColorBrush}"/>
<Setter Property="Effect" Value="{StaticResource z-depth2}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<cons:RippleEffectDecorator Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" Background="{TemplateBinding Background}" HighlightBackground="#1e000000" Grid.Row="0" Grid.Column="0" Panel.ZIndex="0">
<Grid>
<Rectangle RadiusX="4" RadiusY="4" Fill="#1e000000" Panel.ZIndex="1">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Opacity" Value="0"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.12"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="false">
<Setter Property="Opacity" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</cons:RippleEffectDecorator>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" Value="#1FFFFFFF"/>
<Setter Property="Foreground" Value="#42FFFFFF"/>
</Trigger>
</Style.Triggers>
</Style>
I've declared a style as follows.
<Style x:Key="RightButtonStyle"
TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="BlueViolet"></Setter>
</Trigger>
<Trigger Property="IsMouseOver"
Value="False">
<Setter Property="Background"
Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
My button using the style does obey only the yellow part. For some reason it still gets bluish (default hover-over color) and not blue-violetish on hover. What am I missing? There are no other setters or styles that I'm aware of.
It's still using the default button template. You need to override it.
<Style Key="RightButtonStyle" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="BlueViolet"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
I have a button that can be at one of three modes:
Normal - No mouse hover and not selected
Hover - Mouse hover and not selected
Selected - A property at the view model (DataContext) called IsSelected equals true
This is my current code:
<Style x:Key="FlatButtonStyle" TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Orange"/>
</Trigger>
<DataTrigger Binding="{Binding IsSelected}">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="Background" Value="Gray" />
<Setter Property="Foreground" Value="White"/>
<Setter Property="Width" Value="125"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border BorderThickness="0"
Background="{TemplateBinding Background}"
CornerRadius="12">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, only the Hover and normal states work.
I tried data triggers, visual state manager but I'm new to WPF and couldn't make it work.
Your IsSelected Trigger Value is missing. If you want to stick with a button use
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
I will recommend to use ToggleButton and Trigger on IsChecked Property
<ToggleButton IsChecked="{Binding IsSelected}" Style="{StaticResource FlatButtonStyle}"/>
<Style x:Key="FlatButtonStyle" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Orange"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
<Setter Property="Background" Value="Gray" />
<Setter Property="Foreground" Value="White"/>
<Setter Property="Width" Value="125"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border BorderThickness="0"
Background="{TemplateBinding Background}"
CornerRadius="12">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Try useing Toggle Button instead of Button control. it has by default IsChecked state. Here is an exaple of how to use toggle button
http://miteshsureja.blogspot.ae/2011/12/wpf-toggle-button.html