Ok I started to post a question but in the midst of posting I had an idea that turned out to fix it... I'm posting with an answer in case it saves someone else some frustration.
I'm trying to make a custom style for ListViewItem and within a ListView that has a GridView. Here is my style:
<Style x:Key="StListViewItemBase" TargetType="{x:Type ListViewItem}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Padding" Value="4,1"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd"
Value="{StaticResource BrSelectableItemHover}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd"
Value="{StaticResource BrSelectableItemHover}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then I have a ListView like this:
<ListView ItemsSource="{Binding Tabs}" ItemContainerStyle="{StaticResource StListViewItemBase}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="test">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:SampleObject}">
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="test 2">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:SampleObject}">
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
however, when I run it I get the columns, but in the items list it just gives 'TestApp.SampleObject' readout for each item, and not even in each column, just once for each. If I remove the item container style it works as it should.
So I generated this style by going into Blend, creating a ListViewItem, and editing a copy of the template. However it turns out the template is different if it's inside a GridView than if it isn't... I had to create a ListView with a GridView, THEN a ListViewItem inside it and then edit that style. Here is the revised style that works:
<Style x:Key="StListViewItemBase" TargetType="{x:Type ListViewItem}">
<Setter Property="TextElement.FontFamily" Value="Resources/#Artifakt Element Light" />
<Setter Property="FontSize" Value="11pt" />
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="5,2,5,2"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Foreground" Value="{StaticResource BrDarkText}" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<Border x:Name="InnerBorder" BorderThickness="1" CornerRadius="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="11"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Rectangle x:Name="UpperHighlight" Fill="#75FFFFFF" Visibility="Collapsed"/>
<GridViewRowPresenter Grid.RowSpan="2"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="{StaticResource BrSelectableItemHover}"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="{StaticResource BrSelectableItemHover}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Hopefully that saves someone else some frustration...
I've seen a few posts about this, including on StackOverflow - but I can't find an answer.
In WPF, I created a ControlTemplate for a ComboBox, simply by clicking "Edit Template -> Copy" in visual studio.
Now my problem is that the items in the dropdown are presented in an ItemsPresenter, and I simply can't figure out how to use a VirtualizingStackPanel inside that ItemsPresenter. I tried settings the ItemsPanel of the control in the control's style, but that doesn't help.
Here is the XAML of the ControlTemplate. It is pretty standard. The ItemsPresenter is called PART_ItemsPresenter.
<ControlTemplate x:Key="ComboBoxControlTemplate" TargetType="{x:Type ComboBox}">
<Grid x:Name="templateRoot" SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"
Width="0" />
</Grid.ColumnDefinitions>
<Popup
x:Name="PART_Popup"
AllowsTransparency="True"
Grid.ColumnSpan="2"
IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="Fade"
Placement="Bottom">
<!--<themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=templateRoot}">-->
<Border
x:Name="DropDownBorder"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
<ScrollViewer
x:Name="DropDownScrollViewer">
<Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top"
Width="0">
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}"
Height="{Binding ActualHeight, ElementName=DropDownBorder}"
Width="{Binding ActualWidth, ElementName=DropDownBorder}" />
</Canvas>
<ItemsPresenter
x:Name="PART_ItemsPresenter"
KeyboardNavigation.DirectionalNavigation="Contained"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
</ItemsPresenter>
</Grid>
</ScrollViewer>
</Border>
<!--</themes:SystemDropShadowChrome>-->
</Popup>
<ToggleButton
x:Name="toggleButton"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Grid.ColumnSpan="2"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Focusable" Value="False" />
<Setter Property="ClickMode" Value="Press" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{StaticResource ControlBackgroundBrush}"
SnapsToDevicePixels="True">
<Border x:Name="splitBorder" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1" HorizontalAlignment="Right" Margin="0,-1,-1,-1"
Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
<Path
x:Name="Arrow"
Data="M0,0C0,0 3.5,4 3.5,4 3.5,4 7,0 7,0 7,0 0,0 0,0z"
Fill="{TemplateBinding BorderBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="templateRoot"
Value="{StaticResource ControlBackgroundMouseOverBrush}" />
<Setter Property="BorderBrush" TargetName="templateRoot"
Value="{StaticResource ControlBorderMouseOverBrush}" />
<Setter Property="BorderBrush" TargetName="splitBorder"
Value="{StaticResource ControlBorderMouseOverBrush}" />
<Setter Property="Fill" TargetName="Arrow"
Value="{StaticResource ControlBorderMouseOverBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="templateRoot" Value="#FFC4E5F6" />
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF2C628B" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="templateRoot" Value="#FFF4F4F4" />
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#FFADB2B5" />
<Setter Property="Background" TargetName="splitBorder" Value="#FFF4F4F4" />
<Setter Property="BorderBrush" TargetName="splitBorder" Value="#FFADB2B5" />
<Setter Property="Fill" TargetName="Arrow"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
<Border x:Name="Border" Background="{StaticResource ControlBackgroundBrush}"
Margin="{TemplateBinding BorderThickness}">
<TextBox x:Name="PART_EditableTextBox"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}"
Margin="{TemplateBinding Padding}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="AllowDrop" Value="True" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer
x:Name="PART_ContentHost"
Template="{Binding PART_ItemsPresenter.Template}"
Background="Transparent"
Focusable="False"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" TargetName="Border" Value="0.56" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="Foreground" Value="Black" />
</Trigger>
<!--<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="True">
<Setter Property="Margin" TargetName="shadow" Value="0,0,5,5"/>
<Setter Property="Color" TargetName="shadow" Value="#71000000"/>
</Trigger>-->
<Trigger Property="HasItems" Value="False">
<Setter Property="Height" TargetName="DropDownBorder" Value="95" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsGrouping" Value="True" />
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="ScrollViewer.CanContentScroll" Value="False" />
</MultiTrigger>
<Trigger Property="CanContentScroll" SourceName="DropDownScrollViewer" Value="False">
<Setter Property="Canvas.Top" TargetName="OpaqueRect"
Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}" />
<Setter Property="Canvas.Left" TargetName="OpaqueRect"
Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
This should be all you need in your ComboBox style:
<Setter Property="VirtualizingStackPanel.IsVirtualizing"
Value="True" />
<Setter Property="VirtualizingStackPanel.VirtualizationMode"
Value="Recycling" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel
IsItemsHost="True"
IsVirtualizing="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(VirtualizingStackPanel.IsVirtualizing)}"
VirtualizationMode="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(VirtualizingStackPanel.VirtualizationMode)}" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
Whether you use the Standard or Recycling virtualization mode is up to you. The Recycling mode tends to cause some odd artifacts on a ComboBox. For example: as you scroll, you may see more than one item highlighted with the 'selected' effect (but never more than one in view at a time).
However, there is a catch to making this work: you need to rename PART_ItemsPresenter to something else (I renamed it to ItemsPresenter). I have not been able to nail down why, but when you use the name PART_ItemsPresenter, your ItemsPanelTemplate doesn't get applied the virtualization is being negated somehow. I can see that the template is being applied, but there are clearly too many item containers being generated, which makes using a virtualizing panel rather pointless. Whatever the cause, simply giving your ItemsPresenter a different name appears to resolve the issue.
As #mm8 points out, you should also set MaxHeight="{TemplateBinding MaxDropDownHeight}" on DropDownBorder, or your popup will try to grow to accommodate all the items.
Lastly, I'm not sure what your intent was when you added the binding below, but you can't just add a named reference to the property path to set the binding source. Whatever your intent was, this binding is not going to satisfy it. I'd just get rid of it.
<ScrollViewer x:Name="PART_ContentHost"
Template="{Binding PART_ItemsPresenter.Template}"
... />
You need to do multiple things to support virtualization. Setting the ItemsPanelTemplate was part of the solution:
<Setter Property="VirtualizingPanel.IsVirtualizing" Value="True" />
<Setter Property="ScrollViewer.CanContentScroll" Value="True" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
Setting the ItemsPanel to a VirtualizingStackPanel does work:
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
However, in order for the actual virtualization to work, you should also set the MaxHeight property of the DropDownBorder element in your template (or don't comment out the SystemDropShadowChrome element):
<Border x:Name="DropDownBorder" MaxHeight="{TemplateBinding MaxDropDownHeight}" ...
I'm writing an small key application and I'm using a listbox to dynamically visualise a list from code. Now the issue is it needs to be used on windows 7 and I'm having multiple issues with the visualisation on that platform.
The code I have is:
<ListBox x:Name="listBoxSecrets" Margin="0,84,10,10" Background="{x:Null}"
HorizontalContentAlignment="Stretch" BorderBrush="{x:Null}" >
<ListBox.ItemTemplate>
<DataTemplate>
<!--<Border BorderBrush="#FFF3560D" CornerRadius="3" BorderThickness="3" Margin="0,0,0,10">-->
<Border BorderBrush="White" CornerRadius="10" BorderThickness="10" Margin="0,0,0,10">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<StackPanel Uid="{Binding Path=ID}" Grid.Row="0" Grid.Column="0">
...
</StackPanel>
<Button ... Grid.Row="0" Grid.Column="2">
...
</Button>
<Button ... Grid.Row="0" Grid.Column="3" >
...
</Button>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
I tried the following style to no effect:
<Window.Resources>
<Style x:Key="{x:Type ListBox}" TargetType="{x:Type ListBox}">
<Setter Property="Focusable" Value="False" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</Window.Resources>
This is how the selection looks - I don't want it to be selectable. (I have the same issue with the buttons btw - same solution would be applicable?)
Before:
After click:
Also: Bonus points if you can help me figure out how to remove the "aliasing" line between the grid and the border around it.. ;-; Only happens on the win 7 mahcine, not my win 8 machine.
I guess you want to remove the selection state of ListBoxItem, if thats right, Please use the below style,
in this i have commented out the triggers responsible for selection and mouse over state.
You can assign this style in ItemContainerStyle of ListBox,,
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/>
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#3DDADADA"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#FFDADADA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#3D26A0DA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF26A0DA"/>
<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Padding" Value="4,1"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<!--<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
</MultiTrigger>-->
<!--<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
</MultiTrigger>-->
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Why don't you remove the selection upon happening? Like this:
private void listBoxSecrets_SelectionChanged(object sender, EventArgs e)
{
listBoxSecrets.SelectedIndex = -1;
}
You then setup the listener like this:
<ListBox x:Name="listBoxSecrets" Margin="0,84,10,10" Background="{x:Null}"
HorizontalContentAlignment="Stretch" BorderBrush="{x:Null}" SelectionChanged="listBoxSecrets_SelectionChanged" >
I have a small question, I've created a ListBox that only contains 2 items. Each item is a Path control that has a Fill attribute set to Black.
Now, what I'm trying to do is, change the colour of this Fill attribute when you select one of the items in the listbox... I would think this should be done with a Style. But when doing so, the style contains a ContentPresenter that maps to the Path and this ContentPresenter has no Fill attribute to change through the IsSelected trigger!
So in other words, how can I still use a Style that maps the Fill attribute?
My current XAML code of the Window in the WPF project:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="XAMLPathStyleProblem.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<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="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<ListBox x:Name="ImageBar" ItemContainerStyle="{DynamicResource ListBoxItemStyle}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem>
<Path Data="M15.992466,14.680105C20.892824,14.680104 23.97299,17.360288 28.013305,17.360288 31.943504,17.360288 34.333683,14.680104 39.994102,14.680105 44.274425,14.680104 48.804641,17.000391 52.034961,21.0308 41.454162,26.831151 43.174373,41.942682 53.865043,45.983101 52.394974,49.24342 51.694851,50.703518 49.794819,53.583672 47.154625,57.614079 43.424389,62.624561 38.803959,62.664604 34.703705,62.704647 33.643696,59.994431 28.073246,60.024464 22.50292,60.054249 21.342806,62.714657 17.23254,62.674614 12.622241,62.634571 9.0819604,58.104115 6.441766,54.083717 -0.95864094,42.822647 -1.7287129,29.611443 2.8315349,22.590761 6.0717456,17.600301 11.19209,14.680104 15.992466,14.680105z M38.751411,0C39.321331,3.8093758 37.761547,7.538764 35.701835,10.178331 33.502144,12.997869 29.702673,15.197509 26.033186,15.077528 25.373277,11.438125 27.093038,7.6887398 29.172746,5.1591539 31.462427,2.3696117 35.39188,0.23996067 38.751411,0z"
Fill="Black" />
</ListBoxItem>
<ListBoxItem>
<Path Data="M32.127438,4.0459317E-05C34.679321,-0.0059787218,51.370113,0.63573532,60.553993,18.050023L60.522991,18.050023 60.543671,18.086075C61.200066,19.24132 68.004066,31.93957 59.575981,47.967091 59.575981,47.967091 51.176838,64.148377 30.558096,63.870453L29.65756,63.847004 29.649204,63.861397C29.644096,63.870198,29.641504,63.874661,29.641504,63.874661L29.638971,63.874695 29.681444,63.800747C30.804413,61.84562,39.865662,46.068413,42.345753,41.710415L42.378082,41.653572 42.392643,41.638874 42.472183,41.501145 42.692501,41.246766C44.087284,39.55642,45.09919,37.538369,45.595421,35.325478L45.613995,35.233231 45.681602,34.931549C45.857914,34.084336,45.977459,33.046578,45.939392,31.839535L45.927822,31.607016 45.927765,31.604247 45.927345,31.597495 45.913135,31.311926 45.901112,31.172703 45.89138,31.015126 45.867527,30.783802 45.865814,30.76396 45.8638,30.747662 45.831325,30.432713C45.783504,30.046782,45.720222,29.665644,45.64212,29.289938L45.605244,29.129017 45.579826,29.001641C45.3101,27.769034 44.871658,26.423209 44.200989,24.977549 43.870582,24.491171 43.539108,24.000555 43.182049,23.514327L42.899601,23.140976 60.287002,18.042616C60.287002,18.042616,39.292564,18.022913,34.351002,18.039915L34.393581,18.050023 34.172077,18.050023C33.849613,18.050023,33.54248,18.050023,33.252323,18.050023L33.158501,18.050023 32.880497,18.023783C32.497307,17.992794 32.109821,17.977 31.718649,17.977 31.350422,17.977 30.985464,17.990992 30.624279,18.018473L30.292705,18.050023 30.278829,18.050023C30.225145,18.050023 30.197481,18.050023 30.197481,18.050023 30.197481,18.050023 30.175093,18.049284 30.131918,18.049599 29.747402,18.052403 27.714258,18.138693 25.166611,19.573328L25.156681,19.579142 25.090729,19.612418C22.198151,21.138638,19.8955,23.632718,18.613605,26.663617L18.496868,26.959704 5.5749997,14.177C5.5749997,14.177,15.021078,30.765849,17.85829,35.692574L17.988001,35.917668 18.035503,36.093228C19.728666,42.05547 25.213291,46.422997 31.718649,46.422997 32.332252,46.422997 32.936783,46.384125 33.529907,46.308712L33.816097,46.268658 29.596954,63.874993 29.542429,63.874833C28.213777,63.865578 13.814976,63.407895 4.1510181,48.093563 4.1510176,48.093563 -5.6624084,32.728032 4.8882693,15.012328L5.3907794,14.192161 5.3934535,14.187385C5.6228327,13.780242 13.109029,0.74591898 31.796461,0.0057129142 31.796461,0.0057133239 31.911178,0.00055203911 32.127438,4.0459317E-05z"
Fill="Black" />
</ListBoxItem>
</ListBox>
</Grid>
</Window>
I recommend you using MVVM pattern with MVVM Light Toolkit. Then you should create Collection of data that you want to dispaly on the list. In your case it can be Data and Fill (Color). Then you need to handled Click event and that's all. I have code that provides such feature, so If you want it, please ask.
But in your case (without MVVM Light toolkit) I would rather do sth like this:
<Style x:Key="Path" TargetType="{x:Type Path}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource, AncestorType={x:Type ListBoxItem}}, Path=IsSelected" Value="True">
<Setter Property="Fill" Value="YouColor"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource, AncestorType={x:Type ListBoxItem}}, Path=IsSelected" Value="False">
<Setter Property="Fill" Value="YouAnotherColor"/>
</DataTrigger>
</Style.Triggers>
</Style>
Best regards.
Mateusz
Ok... found the answer myself!
When changing the Fill value inside the Path control to a binding one, all works as expected!
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"