Help Creating a Style for a ListBoxItem - wpf

I am new to styles and need help to create a style for a ListBoxItem that will give the item a transparent background then have the Font turn Gold when hovered over. It should not change the color when clicked and return to normal when the mouse moves off. It must still pass the selected object to the PreviewMouseRightButtonDown event for the ListBox
I currently use a default dictionary from REUXABLES THEMES, but it is way to much coloring for this portion of the display on the application.
Thanks,
<DataTemplate x:Key="ItemsTemplate">
<StackPanel Orientation="Vertical"
Margin="0,5,0,5"
Width="{Binding
Path=ActualWidth,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ScrollContentPresenter}}}" MaxWidth="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ScrollViewer}}, Path=ViewportWidth}" >
<TextBlock VerticalAlignment="Top" TextWrapping="Wrap" FontSize="14" Text="{Binding Path=CID}" />
<StackPanel Orientation="Horizontal" Margin="0,5,0,0" >
<TextBlock>
<Label Foreground="{DynamicResource DisabledForegroundBrush}" >Posted by</Label>
<Label Foreground="{DynamicResource DisabledForegroundBrush}" VerticalContentAlignment="Top" Content="{Binding Path=ACID}" />
</TextBlock>
<TextBlock>
<Label Foreground="{DynamicResource DisabledForegroundBrush}" Margin="3,0,0,0">at</Label>
<Label Foreground="{DynamicResource DisabledForegroundBrush}" Margin="3,0,3,0" VerticalContentAlignment="Top" Content="{Binding Path=Type}" />
</TextBlock>
<TextBlock>
<Label Foreground="{DynamicResource DisabledForegroundBrush}">(</Label>
<Label Foreground="{DynamicResource DisabledForegroundBrush}" VerticalContentAlignment="Top" Content="{Binding Path=Route}" />
<Label Foreground="{DynamicResource DisabledForegroundBrush}">)</Label>
</TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
<Style x:Key="ItemsListBox" TargetType="{x:Type ListBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Background" Value="{DynamicResource Transparent}"/>
<Setter Property="BorderBrush" Value="{DynamicResource Transparent}"/>
<Setter Property="BorderBrush" Value="{DynamicResource Transparent}"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
</Style>
<ListBox x:Name="ListViewFlightPlans" Grid.Column="0" ItemTemplate="{DynamicResource ItemsTemplate}"
MaxWidth="800" ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderBrush="Black" BorderThickness="2,0,0,1">
</ListBox>
Dave

Unfortunately changing BorderBrush for the ListBoxItem won't have your desired effect, since the Border with the selection highlight is internal to the ControlTemplate of the ListBoxItem.
Instead, you can add a new Brush resource with the key of SystemColors.HighlightBrushKey, this is the key that the ListBoxItem uses for setting the selection highlight color.
The inactive selection brush uses the key of SystemColors.ControlBrushKey, so if you override both of these with a transparent Brush you're guaranteed not to have any selection color. You can read more about it in this article.
Here's an example with everything but your DataTemplate:
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid.Resources>
<x:Array x:Key="data" Type="{x:Type sys:String}">
<sys:String>a </sys:String>
<sys:String>bb</sys:String>
<sys:String>ccc</sys:String>
<sys:String>dddd</sys:String>
</x:Array>
</Grid.Resources>
<ListBox ItemsSource="{StaticResource data}">
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Gold"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
</ListBox>
</Grid>

Related

Changing background color for a ComboBox, it's not changing color at all

I going crazy that I just can't change the color of the ComboBox. Have tried to use the background property right on the ComboBox but nothing happens.
Have also tried to use a Style block and set the background color, but that does also not work.
Code
<ComboBox Padding="7" Height="34" Background="#ffffff">
<ComboBox.Resources>
<Style x:Key="{x:Type ComboBox}" TargetType="ComboBox">
<Setter Property="Background" Value="red" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="black" />
</Style>
</ComboBox.Resources>
<ComboBoxItem IsSelected="True">1 - Room</ComboBoxItem>
<ComboBoxItem>2 - Rooms</ComboBoxItem>
<ComboBoxItem>3 - Rooms</ComboBoxItem>
<ComboBoxItem>4 - Rooms</ComboBoxItem>
<ComboBoxItem>5+ - Rooms</ComboBoxItem>
</ComboBox>
Even though that I have set the background color to white, It still only the standard grey color.
Here you can see how it looks:
Hope someone can tell me what I'm doing wrong?
here are several thing which in my opinion can help you:
Remove the Background definition from the ComboBox declaration(Background="#ffffff").
Move the combo items declaration to the combo holding Grid because of the fact that ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container.
Implement the data template selector to support data templates of combo (one for selected item, second for the items to select).
Here is the XAML code
<Grid>
<Grid.Resources>
<x:Array Type="{x:Type system:String}" x:Key="MyRoomsArray">
<system:String>1 - Room</system:String>
<system:String>2 - Rooms</system:String>
<system:String>3 - Rooms</system:String>
<system:String>4 - Rooms</system:String>
<system:String>5+ - Rooms</system:String>
</x:Array>
</Grid.Resources>
<ComboBox Padding="7" Height="34" SelectedIndex="0" ItemsSource="{StaticResource MyRoomsArray}">
<ComboBox.Resources>
<DataTemplate x:Key="ItemToSelect">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="Red"
BorderBrush="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=BorderBrush, UpdateSourceTrigger=PropertyChanged}"
BorderThickness ="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=BorderThickness, UpdateSourceTrigger=PropertyChanged}">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding }" />
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="SelectedItem">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=Background, UpdateSourceTrigger=PropertyChanged}"
BorderBrush="Transparent"
BorderThickness ="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=BorderThickness, UpdateSourceTrigger=PropertyChanged}">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding }" />
</Border>
</Grid>
</DataTemplate>
<wpfComboBAckground:ComboDataTemplateSelector x:Key="ComboDataTemplateSelector" Selected="{StaticResource SelectedItem}" ItemToSelect="{StaticResource ItemToSelect}"/>
<Style TargetType="ComboBox">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Background" Value="Red" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="ItemTemplateSelector" Value="{StaticResource ComboDataTemplateSelector}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Resources>
</ComboBox>
</Grid>
Here is the data template selector
public class ComboDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var selected = false;
// container is the ContentPresenter
FrameworkElement fe = container as FrameworkElement;
if (fe == null) return ItemToSelect;
var cbo = fe.TemplatedParent as ComboBox;
if (cbo != null)
selected = true;
return selected ? Selected : ItemToSelect;
}
public DataTemplate Selected { get; set; }
public DataTemplate ItemToSelect { get; set; }
}
How it looks like:
Regards.

set Foreground color of element inside Selected Row of DataGrid

I have a DataGridTemplateColumn defined as below. I need to change the Foreground property of both textblocks to White if the row is selected
<DataGrid.Columns>
<DataGridTemplateColumn Header="User" Width="240" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Margin="10,3,0,0" Foreground="#1c72c7" >
<Run Text="{Binding FullName, Mode=OneWay}" />
</TextBlock>
<Label Padding="0,0,0,0" Margin="0,0,0,3">
<TextBlock Foreground="#1c72c7" Margin="10,0,0,0" TextDecorations="Underline" Text="{Binding DisplayName}" />
</Label>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I already have a RowStyle defined to change the background color of the row as follows
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="{x:Static SystemColors.HighlightColor}" />
</Style.Resources>
</Style>
You should modify the Style for each individual TextBlock, and add the behavior as you'd like, as so:
<Style x:Key="FirstTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected,
RelativeSource= {RelativeSource
AncestorType={x:Type DataGridRow}}}"
Value="True">
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>

Merge Style.Triggers with property Template in WPF

I want to set a style for my DataGrid, but I do not know where is the problem
the backgroud property does not work with its value in the presence of the Template property.
my code:
<Style x:Key="DataGridStyle1" TargetType="{x:Type DataGrid}">
<Setter Property="CellStyle" Value="{DynamicResource GridStyle1}"/>
</Style>
<Style x:Key="GridStyle1" TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True" >
<Setter Property="Background" Value="SeaGreen"/>
</Trigger>
</Style.Triggers>
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Name="DataGridCellBorder">
<ContentControl Content="{TemplateBinding Content}">
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBlock Background="Transparent" TextWrapping="WrapWithOverflow" TextTrimming="CharacterEllipsis"
Height="auto" Width="auto" Text="{Binding Text}"/>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
Help me please.
You have explicitly set TextBlock background to Transparent, so it won't pick value from DataGridCell. You should bind with background of DataGridCell using RelativeSource like this:
<TextBlock Background="{Binding Background, RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType=DataGridCell}}"
TextWrapping="WrapWithOverflow" TextTrimming="CharacterEllipsis"
Height="auto" Width="auto" Text="{Binding Text}"/>

Styling WPF Tree At All Levels

I have a tree in WPF that has no root node, but has defined TreeViewItems for separate categories. Each of these TreeViewItems have their ItemsSource bound to the display object. The data displays fine. Now I'm trying to make the tree appear like the Windows7 Explorer trees.
I've used some of the styling from this post: WPF TreeView: How to style selected items with rounded corners like in Explorer
Anyhow here is the TreeViewItem:
<TreeViewItem ItemsSource="{Binding Path=Configuration.CognosServers}"
IsExpanded="True"
Visibility="{Binding ItemsSource.Count, Converter={StaticResource ResourceKey=TreeViewItemVisibility1}, RelativeSource={RelativeSource Self}}">
<TreeViewItem.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</TreeViewItem.ItemContainerStyle>
<TreeViewItem.HeaderTemplate>
<DataTemplate>
<Border Margin="0,5,0,0">
<Border.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove" Click="TreeItemMenu_RemoveClick" />
<MenuItem Header="Add Client..." Click="TreeItemMenu_AddNewClient" />
</ContextMenu>
</Border.ContextMenu>
<StackPanel Orientation="Horizontal">
<Image Source="/WPF;component/Images/server_chart.png"
Margin="0,0,5,0"/>
<TextBlock Text="Cognos Servers" />
</StackPanel>
</Border>
</DataTemplate>
</TreeViewItem.HeaderTemplate>
<TreeViewItem.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Namespaces}">
<Border>
<TextBlock Text="{Binding DisplayName}" PreviewMouseRightButtonDown="OnPreviewMouseRightButtonDown" />
</Border>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource ResourceKey=TreeViewItemStyle1}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Clients}">
<Border>
<TextBlock Text="{Binding DisplayName}" PreviewMouseRightButtonDown="OnPreviewMouseRightButtonDown" />
</Border>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource ResourceKey=TreeViewItemStyle1}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<Border>
<TextBlock Text="{Binding DisplayName}"
ContextMenu="{StaticResource ResourceKey=ContextMenuTreeItem}"
PreviewMouseRightButtonDown="OnPreviewMouseRightButtonDown" />
</Border>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
The style I'm apply to the TreeView appears like this:
<TreeView x:Name="TreeViewLoadedItems"
Grid.Row="1"
VerticalAlignment="Stretch"
ItemContainerStyle="{DynamicResource TreeViewItemStyle1}"
MouseDoubleClick="TreeViewItem_MouseDoubleClick"
SelectedItemChanged="TreeViewLoadedItems_SelectedItemChanged" >
Finally the style I'm applying is this:
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type TreeViewItem}">
<!-- Style for the selected item -->
<Setter Property="BorderThickness" Value="1"/>
<Style.Triggers>
<!-- Selected and has focus -->
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="#7DA2CE"/>
</Trigger>
<!-- Mouse over -->
<!--<Trigger Property="helpers:TreeView_IsMouseDirectlyOverItem.IsMouseDirectlyOverItem" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFFAFBFD" Offset="0"/>
<GradientStop Color="#FFEBF3FD" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" Value="#B8D6FB"/>
</Trigger>-->
<!-- Selected but does not have the focus -->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="IsSelectionActive" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" Value="#D9D9D9"/>
</MultiTrigger>
</Style.Triggers>
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="2"/>
</Style>
</Style.Resources>
</Style>
</Setter.Value>
</Setter>
</Style>
No Matter what I've done I can't seem to get each item to look the same when selected. Only the leaf nodes seem to be picking up the style. I always have trouble when there are HierarchialDataTemplates and I need to style things. What gives?!
In your style you set the ItemContainerStyle, why? That way the immediate TreeViewItem the style is applied to will not have the style, maybe that somehow even propagates down to the leaf; you should not need to set that property. Just place a style for TreeViewItems in the Resources of the TreeView and it will automatially apply to each item, move everything in the ItemContainerStyle up to the actual main style.

WPF ContentPresenter only showing first item in list

I am trying to create a WPF application where I have a StackPanel that shows a list of accounts. There is an Account object in the code behind for each account, stored in a List structure. I want to databind this to my WPF, but I don't want a listbox.
Instead, I defined a template for how each account summary should appear. I then want to stack these in a StackPanel and call it a day.
The problem is that the Data Binding only takes the first item from the list and that's it. How to I bind it so that this effectively creates a little stacked list of nicely formatted chunks of data?
Here is the relevant WPF code:
<StackPanel Name="sp_AccountList" Margin="0,0,0,0" VerticalAlignment="Top">
<StackPanel.Resources>
<svc:AccountBalanceColorConverter x:Key="accountColorConverter" />
<Style x:Key="AccountSummaryBackgroundGradient" TargetType="{x:Type StackPanel}">
<!-- nice formatting code here -->
</Style>
<Style x:Key="AccountSummaryNameStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Padding" Value="10,0,0,0" />
<Setter Property="FontSize" Value="18" />
<Setter Property="Height" Value="20" />
<Setter Property="FontFamily" Value="Cambria" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="Transparent" />
</Style>
<Style x:Key="AccountSummaryBalanceStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Padding" Value="10,0,0,0" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Height" Value="20" />
<Setter Property="FontFamily" Value="Cambria" />
<Setter Property="Background" Value="Transparent" />
</Style>
<ObjectDataProvider x:Key="accounts"
ObjectType="{x:Type svc:AccountService}"
MethodName="ListAccounts" />
<DataTemplate x:Key="AccountSummaryLayout">
<StackPanel Orientation="Vertical" Style="{StaticResource AccountSummaryBackgroundGradient}">
<TextBlock Text="{Binding Path=Name}" Style="{StaticResource AccountSummaryNameStyle}" />
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="{Binding Path=TotalAccountBalance, Converter={StaticResource accountColorConverter} }" Text="{Binding Path=TotalAccountBalance, Mode=OneWay}" Style="{StaticResource AccountSummaryBalanceStyle}" />
<TextBlock Foreground="{Binding Path=AvailableAccountBalance, Converter={StaticResource accountColorConverter} }" Text="{Binding Path=AvailableAccountBalance, Mode=OneWay}" Style="{StaticResource AccountSummaryBalanceStyle}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</StackPanel.Resources>
<StackPanel Orientation="Vertical">
<ContentPresenter x:Name="AccountSummaryPresenter" ContentTemplate="{StaticResource AccountSummaryLayout}" Content="{DynamicResource accounts}" />
</StackPanel>
</StackPanel>
StackPanel does not have an ItemsSource property, its children controls are not databindable.
What you can do is create an ItemsControl which uses a StackPanel as its Itemshost.
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Source={StaticResource accounts}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True" Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
...
</ItemsControl.ItemTemplate>
</ItemsControl>
<ScrollViewer>

Resources