Dynamic highlight color in ListView - wpf

How can I make background highlight color dependent on some property of ListViewItem?

This is an issue that people often ask for. Actually, for some reasons, when an item is selected in a ListView or ListBox, the Background color is not the one that is changed. It is a bit more tricky. In fact you need to override the value of the static color resources to which the item template is bound. So to change the higlighting colors of the items you have to do like this:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Orange"/>
</Style.Resources>
</Style>
</ListView.ItemContainerStyle>
</List>
Here is a more developed explanation: Trigger for ListBoxItem

EDIT:
For changing selected background, you will have to override the ListViewItem's Template.
See this... http://msdn.microsoft.com/en-us/library/ms788717(v=vs.90).aspx.
Replace the {StaticResource SelectedBackgroundBrush} with your preferred background brush in the template.
To change backgrounds based on ANY other property that the control template does not rely upon, You can use triggers ...
<ListView ...>
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="SomeListViewItemProperty" Value="Value1">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="SomeListViewItemProperty" Value="Value2">
<Setter Property="Background" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
<ListView.Resources>
</ListView>
I hope this answers your question.

Related

XAML separate binding of ContainerStyle and ContentTemplate in ListBox

I tried this for a while now and searched in the web without success... Now I dare to ask on stackoverflow myself.
So, the aim is to separate the definitions of the ItemContainerStyle and the ContentTemplate of a ListBoxItem. I have defined the ListBoxItemStyle in a ResourceDictionary and two different DataTemplates in the Window.Resources.
I now like to set the style of the ListBoxItem according to the one defined in the ResourceDictionary and change the DataTemplate with a trigger (IsMouseOver).
My (not working) Code so fare looks like this:
<ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="20,60,10,10"
Grid.Row="1" Grid.Column="0"
PreviewMouseMove="DragMove_PreviewMouseMove"
PreviewMouseLeftButtonDown="Drag_PreviewMouseLeftButtonDown"
ItemsSource="{Binding Persons}" VerticalContentAlignment="Center"
Style="{StaticResource DefaultListBoxStyle}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Style" Value="{StaticResource DefaultListBoxItemStyle}"/>
<Setter Property="ContentTemplate" Value="{StaticResource PersonsListBoxItemTemplate_default}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource PersonsListBoxItemTemplate_infoButtons}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
where DefaultListBoxStyle is the style defined in the ResourceDictionary and PersonsListBoxItemTemplate_default & PersonsListBoxItemTemplate_infoButtons are the DataTemplates defined in the Window.Resources.
Now I get an error, that the style-object must not have an impact on the style-property of the object it belongs to.
I tried different ways, but without success... I also tried to define the style first and then change the template, but it does not work either.
Thank you all for your help!
So you can't set Style Property in Style with Setter. For this you need to use BasedOn:
<Style TargetType="ListBoxItem" BasedOn="{StaticResource DefaultListBoxItemStyle}">
<Setter ... />
</Style>

Apply same style to multyple objects that match specific criteria wpf

In my application I have several menus with the same background color, corner radius,border color and border thickness. I save those properties as resources in my application resources so that if I change the background color for example it will change the color of all my menus. I was wondering if it is possible to create a style so that I can just bind that style to the menus instead of binding so many properties. Moreover I just want to apply that style to some borders because not all borders in my application are menus. How could I do that?
for example I am hoping to do something like:
here is my style in my application resources:
<Style x:Key="someStyle">
<Style.Resources>
<Color x:Key="MenuBackground2">#BB252525</Color>
<CornerRadius x:Key="CornerRadiusMenu2">7</CornerRadius>
<Border x:Key="MainBorder2" >
<Border.Background>
<SolidColorBrush Color="{DynamicResource MenuBackground}"/>
</Border.Background>
</Border>
</Style.Resources>
</Style>
and then on MainWindow.xaml place:
<Border Margin="498,90,25,0" Name="brdMain" Style="{DynamicResource someStyle}"></Border>
but when I do that, brdMain does not seem to bind to that style...
Your Style is not correctly defined. It should be a collection of Setters. For example, your given style should be:
<Style x:Key="someStyle">
<Setter Property="Background" Value="#BB252525"/>
<Setter Property="CornerRadius" Value="7"/>
etc ...
</Style>
A Style is little more than a bunch of property setters. You can only set properties of the object to which the Style has been applied.
<Style x:Key="someStyle" TargetType="{x:Type Border}">
<Setter Property="Control.Background" Value="#BB252525"/>
<Setter Property="Control.BorderThickness" Value=".5"/>
<Setter Property="Control.BorderBrush" Value="White"/>
<Setter Property="CornerRadius" Value="7"/>
</Style>

Selected item in listbox unreadable because of the color

I dynamically create a collection of stackpanels in my listbox. In this stackpanel are contained labels and checkbox horizontally aligned.
The problem is when I click on a stackpanel, the selection is unreadable because the line become dark-blue whereas the letters stay black so black on blue, you see nothing.
How can I dynamically change the forecolor of the selected elements in the stackpanel? I say dynamically and not in the xml file, because all those elements are dynamically created from a database.
I have code similar to this:
foreach (var utilis in item.user)
{
StackPanelWithID ligne = new StackPanelWithID();
ligne.Orientation = Orientation.Horizontal;
ligne.ID = utilis.TRIGRAMME;
ligne.Height = 21;
Label l = new Label();
l.Width = 120;
Label l2 = new Label();
l2.Width = 145;
CheckBox cbEntretien = new CheckBox();
}
contentpresenter won't work... I tried several way to position it...
So, I found a way to circle the problem ...
in the app.xaml :
<Application.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightBlue"/>
</Style.Resources>
</Style>
</Application.Resources>
Thus the background of selected items is clearer so that the user can still read text of the selected listboxitems.
and every listboxitem is concerned.
and yet... I would love to know how on earth it's possible to change the selected item's text color in list box.. if I manage to get the answer I'll keep you in touch...
I did this...
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background"
Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ContentPresenter>
</ControlTemplate>
but stll not working, it says the trigger property can't be found in ControlTemplate...
I tried to add it after the trigger property, but not working either...
I tried something like this in the App.xaml :
"
<Style x:Key="SimpleListBoxItem" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" <!--can't find the text property so try to act on the Background color to set it to a different color than dark blue-->
Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>"
and in the particular xaml file where my listbox is :
<ListBox Margin="9,64,8,313" Loaded="lstUtilisateurs_Loaded" Name="lstUtilisateurs" ItemContainerStyle="{StaticResource SimpleListBoxItem}"/>
but when executing, nothing appears anymore in the listbox, nothing... I don't get it...
Dunno if it still matters (last answer was on Mar 25 2010), but for the people who are still wondering how to accomplish this I did it this way:
In the Style part:
<Style x:Key="myLBStyle" TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/> <!-- makes the background color transparent, removes backcolor border-->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Red"/> <!-- Sets the textcolor of the selected text to red -->
</Style.Resources>
</Style>
In the Listbox I use then the ItemContainerStyle property like this:
ItemContainerStyle="{StaticResource myLBStyle}
Took me a while to find, but here it is. Hope that someone can use it!
Also handy:
http://msdn.microsoft.com/en-us/library/ms603164.aspx
Best Regards,
Sam

Apply default WPF style

I have a global style that sets all my TextBox styles, but in some cases I want to revert just the Foreground color to the original non-custom-style color. I tried using {TemplateBinding Foreground} inside the specific TextBoxes that I wanted to revert. It didn't end up being valid XAML and I'm not sure that's the right way anyhow.
Any ideas? Thanks.
There's a few ways this could be done. If you look at the Precedence List on the MSDN
then you can see that the Forground set in ways 1-8 will override the Foreground from a default style. The easiest way being just to set the local value in the TextBox.
<TextBox Foreground="Red" />
Another thing that you can do is use the 'BasedOn' property of styles to override the other versions. This does require giving a key value to your default style, but that can then be used to also apply the default like in this example:
<Style TargetType="{x:Type TextBox}"
x:Key="myTextBoxStyle">
<Setter Property="Foreground"
Value="Red" />
<Setter Property="FontWeight"
Value="Bold" />
</Style>
<!-- Style applies to all TextBoxes -->
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource myTextBoxStyle}" />
<TextBox Text="Hello">
<TextBox.Style>
<Style BasedOn="{StaticResource myTextBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground"
Value="Blue" />
</Style>
</TextBox.Style>
</TextBox>
Edit:
In the case that the default style is applying a value and you want to revert it to the base value there are a few ways I can think of, off hand, to get this behavior. You can't, that I know of, bind back to the default theme value in a generic manner.
We can however do some other things. If we need the style to not apply some properties, we can set the style to {x:Null}, thus stopping the default style from applying. Or we can give the element it's own style that does not inherit from the base style and then re-apply only the setters that we need:
<TextBox Text="Hello" Style="{x:Null}" />
<TextBox Text="Hello">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontWeight"
Value="Bold" />
</Style>
</TextBox.Style>
</TextBox>
We could modify the default style so that the Foreground will only be set on certain conditions, such as the Tag being a certain value.
<Style TargetType="{x:Type TextBox}"
x:Key="myTextBoxStyle">
<Setter Property="FontWeight"
Value="Bold" />
<Style.Triggers>
<Trigger Property="Tag"
Value="ApplyForeground">
<Setter Property="Foreground"
Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
<TextBox Text="Hello" />
<TextBox Text="Hello" Tag="ApplyForeground" />

Can you define multiple TargetTypes for one XAML style?

In HTML/CSS you can define a style which can be applied to many types of elements, e.g.:
.highlight {
color:red;
}
can be applied to both P and DIV, e.g.:
<p class="highlight">this will be highlighted</p>
<div class="highlight">this will also be highlighted</div>
but in XAML you seem to have to define the TargetType for styles, otherwise you get an error:
<Style x:Key="formRowLabel" TargetType="TextBlock">
is there a way to allow a XAML style to be applied to multiple elements or even to leave it open as in CSS?
The setters in WPF styles are checked during compile time; CSS styles are applied dynamically.
You have to specify a type so that WPF can resolve the properties in the setters to the dependency properties of that type.
You can set the target type to base classes that contain the properties you want and then apply that style to derived classes. For example, you could create a style for Control objects and then apply it to multiple types of controls (Button, TextBox, CheckBox, etc)
<Style x:Key="Highlight" TargetType="{x:Type Control}">
<Setter Property="Foreground" Value="Red"/>
</Style>
...
<Button Style="{StaticResource Highlight}" Content="Test"/>
<TextBox Style="{StaticResource Highlight}" Text="Test"/>
<CheckBox Style="{StaticResource Highlight}" Content="Test"/>
<!-- Header text style -->
<Style x:Key="headerTextStyle">
<Setter Property="Label.VerticalAlignment" Value="Center"></Setter>
<Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter>
<Setter Property="Label.FontWeight" Value="Bold"></Setter>
<Setter Property="Label.FontSize" Value="18"></Setter>
<Setter Property="Label.Foreground" Value="#0066cc"></Setter>
</Style>
<!-- Label style -->
<Style x:Key="labelStyle" TargetType="{x:Type Label}">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Margin" Value="0,0,0,5" />
</Style>
I think both of these methods of declaring a style might answer your question.
In the first one, there is no TargetType specified, but the property names are prefixed with 'Label'. In the second one, the style is created for Label objects.
Another method to do it is:
<UserControl.Resources>
<Style x:Key="commonStyle" TargetType="Control">
<Setter Property="FontSize" Value="24"/>
</Style>
<Style BasedOn="{StaticResource commonStyle}" TargetType="ListBox"/>
<Style BasedOn="{StaticResource commonStyle}" TargetType="ComboBox"/>
</UserControl.Resources>
I wanted to apply a style to a Textblock and a TextBox but the selected answer didn't work for me because Textblock doesn't inherit from Control, in my case I wanted to affect the Visibility property, so I used FrameworkElement
<Style x:Key="ShowIfRequiredStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShowIfRequiredStyle, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBlock Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
<TextBox Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
This works for the Visibility property because both items inherit from Frameworkelement and the property is defined there. Of course this will not work for properties defined only in Control, you can search the hierarchy tree and try to find a base class, anyway I thought this could help someone since this is a top search result and the selected answer is a little incomplete.
There is an alternative answer to the question. You CAN leave the TargetType parameter off the style altogether which will allow it to apply to various different controls, but only if you prefix the property name with "Control."
<Style x:Key="Highlight">
<Setter Property="Control.Foreground" Value="Red"/>
</Style>
Obviously, this only works for properties of the base control class. If you tried to set ItemsSource say, it would fail because there is no Control.ItemsSource
I got this working
<Style x:Key="HeaderStyleThin" TargetType="{x:Type Border}">
<Setter Property="Background" Value="Black" />
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background=" Value="Red" />
</Style>
</Style.Resources>
</Style>

Resources