I have a ListBox which I need to gray out when it's disabled. Per user request it's not enough to disable it, but it also has to appear differently. shrugs I've looked in several other places and followed the examples, and it seems as if it should work, but it does not. Here are some examples I looked at: Example1, Example2.
Here is my code:
<Style x:Key="ListBoxStyle" TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="BorderBrush" Value="Black"></Setter>
<Setter Property="Foreground" Value="LightGray"></Setter>
<Setter Property="Background" Value="LightGray"></Setter>
<Setter Property="BorderBrush" Value="LightGray"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It seems fairly straightforward. I did the same basic process on ComboBox and TextBox with success. Can anyone help me see where my code is wrong? An example of how to do it correctly would be great. The first example listed above seemed to be exactly what I needed, but the correct answer was "The only way to do this is by overriding the template" which doesn't help me.
I've already tried several simple solutions. It's possible some other style may be affecting this because we're working with a couple different Resource Dictionaries. Does anybody know what may be a good way to track this down?
Edit:
I did a search on the entire solution and the only place ListBox is being used is my portion and the only place it's being styled is the styles I've set. According to MSDN there are no "parts" of a ListBox, so it's not possible I inadvertently styled part of the ListBox in the process of styling for some other control. With no styling, when I disable the ListBox, it is frozen but visible with no text, and has a default background. When I try to apply the Property="Background" Value="LightGray" it seems to be hidden (i.e. nothing is visible). If anybody knows why it may be doing this or how to accomplish my task, I'd appreciate the help.
sa_ddam213's answer didn't work for me so i thought i'd add what i found i had to do. In my case, i had set transparent background, but when i disabled the box it would turn gray. I wanted to be able to control the background of the listbox when the control was disabled and here's what i found to work.
note: For your case, you'd want to change the Transparent color to whatever shade of Gray you want.
note2: This will likely only work if you haven't changed the template for the listbox. (changing the datatemplate is ok).
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
</Style.Resources>
</Style>
</ListBox.Style>
Both answers didn't really work for me so I found a solution that overwrites the ControlTemplate which works for me:
<Style TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Grid Width="Auto" Height="Auto">
<Border x:Name="Border"
BorderThickness="1"/>
<ScrollViewer Focusable="false" IsTabStop="False" HorizontalScrollBarVisibility="Disabled">
<StackPanel IsItemsHost="true"/>
</ScrollViewer>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Border.Background" Value="{StaticResource DisabledBackgroundBrush}"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="{StaticResource DefaultBackground}"/>
</Style>
This helped me: https://social.msdn.microsoft.com/Forums/vstudio/en-US/4b033268-864e-488c-b371-80818daf7f71/can-i-override-the-disabled-background-color-for-a-listbox?forum=wpf
I don't think you need to override the ControlTemplate, just adding a Style.Trigger worked fine for me.
Example:
<ListBox>
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="LightGray" />
<Setter Property="Background" Value="LightGray" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
Related
I have a TextBox in WPF and I'm trying to make the border color change when the mouse hovers over the TextBox. Based on my experience with other elements in WPF, I need to insert a ControlTemplate value with TemplateBinding to the values I am trying to dynamically change. However, when I apply this, the box becomes uneditable (and the text disappears). If I remove the Template setter, the box becomes editable again, but the custom BorderBrush triggers do not work.
Here is the Style:
<Style x:Key="TextBoxBase" TargetType="TextBox">
<Setter Property="FontSize" Value="30"/>
<Setter Property="Background" Value="{StaticResource BrushLightGrey}"/>
<Setter Property="Foreground" Value="{StaticResource BrushNormalText}"/>
<Setter Property="IsReadOnly" Value="False"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border BorderBrush="{TemplateBinding BorderBrush}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource BrushBlue}"/>
</Trigger>
</Style.Triggers>
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="5"/>
</Style>
</Style.Resources>
</Style>
Any suggestions or help is appreciated. Thanks.
You missed out the critical part:
<ScrollViewer Margin="0"
x:Name="PART_ContentHost" />
This is what hosts the text.
See
https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/textbox-styles-and-templates
TextBox Parts
The following table lists the named parts for the TextBox control.
TEXTBOX PARTS
Part Type Description
PART_ContentHost FrameworkElement A visual element that can contain a FrameworkElement. The text of the TextBox is displayed in this element.
I have seen a few similar questions but not of the solutions seem to work.
I would prefer to have the solution through XAML but wouldn't mind it through code (VB.net) either.
I have this code currently, not sure how much of it is correct:
<Style TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Foreground" Value="DarkSlateGray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="White">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="DodgerBlue"/>
</Trigger>
</Style.Triggers>
</Style>
Thanks in advance.
It is generally correct. But do note that your ContentPresenter in your template has no Content property defined. Of course, if you need more complicated triggers, you can also combine with other things like IsEnabled into a MultiTrigger.
I just started getting used to WPF using Blend for Visual Studio. I created previous programs with the standart Windows Forms and now want to get to something more modern.
But I already encountered a main problem after like 5 Minutes.
I added a button with an background image with a transperancy. That worked like a charm, but the problem is that, when I run the application, the button always gets blue when the Mouse hovers it. I do not want this blue effect but can't find the option to disable it in Blend.
Hope someone can help me with this stupid question, Windows Forms was a little
What you're describing is the default state behavior for the button. You would have to create a custom template or style to change it. Example:
<Button Content="Button">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I am demonstrating two properties changes here: Background & Foreground. You may have as many as you want and change them to whatever value you wish. If you don't want any changes, simply remove Style.Triggers or a particular property within it.
Here's a demo for you, since you're new:
Here's the Resource Dictionary way:
Create a Resource Dictionary and add a style to it:
<Style x:Key="CustomButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
Place this in your App.xaml or wherever you merge your resource dictionaries:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ButtonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Then simply specify the style for your button:
Style="{StaticResource CustomButtonStyle}"
I have a style for button as follow:
<Style TargetType="Button" x:Key="BlackButton">
<Setter Property="Background" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="red" />
</Trigger>
</ControlTemplate.Triggers>
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and a button on which is defined as follow:
<Button Canvas.Left="19" Canvas.Top="520" Height="34" Width="107"
Style="{StaticResource BlackButton}" />
But when I run application, I can not see the button. Its background set to none.
If I change the style as follow:
<Style TargetType="Button" x:Key="BlackButton">
<Setter Property="Background" Value="Black"/>
</Style>
(Removing the template) then the button is shown but its background is not changing.
What is wrong with this xaml code?
You've overridden the template of your control in order to set the MouseOver trigger. That means your control template is otherwise empty - and so nothing is drawn for your button.
You can fix that by moving your triggers to the style itself, like this:
<Style TargetType="Button" x:Key="BlackButton">
<Setter Property="Background" Value="Black"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="red" />
</Trigger>
</Style.Triggers>
</Style>
However, what you're likely to run into now is that the button's built-in MouseOver animation will override your red background. You'll see a flash of red, followed by a transition to the default Windows colour. One way to fix that thoroughly is to take a full copy of the default Button template (using Expression Blend is the easiest way to do this) and remove the animations from it.
Well your ControlTemplate is simply empty, although you have a ControlPresenter in it. But since its Content property is not set, it's also empty. To have a Background you will have to add a Border.
<Style TargetType="Button" x:Key="BlackButton">
<Setter Property="Background" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="red" />
</Trigger>
</ControlTemplate.Triggers>
<Border Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This should show you something.
It almost gets me mad in recent days. I have a textbox and the style in xaml file.
But the style without a control template cannot take effect on textbox. Whereas, a control template works, but control template seems to overwrite the textbox totally, the default behaviors loses of textbox such as editing, inputing or selecting...
Here is content of xaml with the control template:
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Name="tbBorder" Background="White" BorderThickness="0.6" BorderBrush="#B9B9B9">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="#4D90FE" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="#4D90FE" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here is the simple style which does not work at all,
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="#4D90FE" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="#4D90FE" />
</Trigger>
</Style.Triggers>
</Style>
Thanks!
update: the entire textbox's code snipt:
<TextBox Height="23" HorizontalAlignment="Left" Margin="114,53,0,0" Name="textBox1" VerticalAlignment="Top" Width="150" Text="{Binding Path=TraderAccount, Mode=OneWayToSource, NotifyOnValidationError=True}" BorderBrush="#FFB9B9B9" BorderThickness="1" >
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="Red" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
The style setter is working for me but the issue I see is that the controls animations are animating away the style that's just been set.
You may want to extract the original control template and redefine that rather than completely redefining it. As far as I know The textbox control is more complex than just a border with a content presenter (I've never extracted the control template for it though!) and its likely to have a couple of borders that work to give it all it's states etc
You can use Blend to do this - in the absence of Blend there is the MSDN resource for control templates and styles:
http://msdn.microsoft.com/en-us/library/aa970773.aspx
Edit:
For starters it looks to me like you are missing the content 'PART' in your redefined template
<ScrollViewer Margin="0" x:Name="PART_ContentHost" />
Edit 2:
You are saying it doesn't work... this works for me on WPF using .NET Framework 4.0 - I changed the border colour to 'Red' instead to make sure I could see the effect and it definitely works, aside from the red fading immediately because the controls visual state is changed by the Visual State Manager (which is why you need to edit the control template and change the visual states)
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="Red" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
When you hover over the box, you get a red border which immediately fades
Does this XAML not work for you at all??
You did not post TextBox code but I assume (it happened to me too) that you simply forgot to set BorderThickness of your textbox:
<TextBox BorderThickness="4">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="#4D90FE" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="#4D90FE" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Your style does work, set a property like Background in your style without the template and you will see that it does get applied. However, like someone else mentioned, the reason you do not see any changes is because of animation in the default WPF control template for TextBox (Animation values always take precedence over local values, setters and triggers). When you redefine the control template, those animations are no longer there and so your example works. What you could do is take the default TextBox template and modify it to suit your purposes (can be found here: http://msdn.microsoft.com/en-us/library/cc645061%28VS.95%29.aspx).