WPF Style Selected Items of ListBox Using an ItemsPanelTemplate - wpf

How can I style the selected items in this listbox?
<ListBox x:Name="AssetTypeListBox" SelectionMode="Multiple">
<ListBox.ItemsPanel >
<ItemsPanelTemplate >
<UniformGrid Columns="6"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
I have tried
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#F15025"/>
and
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#F15025"/>
But they don't seem to affect the selected items as I would expect. Thanks.

If you just want to change the colour of the selection, then the easiest way is to set the solidcolorbrush as a resource on your Listbox:
<ListBox x:Name="AssetTypeListBox" SelectionMode="Multiple">
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#F15025"/>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#F15025"/>
</ListBox.Resources>
<ListBox.ItemsPanel >
<ItemsPanelTemplate >
<UniformGrid Columns="6"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
If you're wanting to customise the style of the selection of an item in the listbox, such as changing the selection colour or completely restyling the look of a selected item, you need to look at the ItemContainerStyle property.
The ItemsPanelTemplate doesn't affect this - it simply sets the ItemsControl type that should layout and present the items - such as a StackPanel or UniformGrid.
The basic hierarchy (with a pinch of salt) of a ListBox is:
ListBox
ItemsPanelTemplate (StackPanel by default)
ItemsContainerStyle (Selection highlighting is here)
ItemTemplate (You define the content of your list item here)
The differences between ItemTemplates and ItemsContainerStyle are covered here:
What's the difference between ItemTemplate and ItemContainerStyle in a WPF ListBox?

Related

WPF Listbox containing Expander controls

I've been playing around with wpf for a few months with mixed success but this one has me stumped. I have a ListBox containing Expanders, something like this:
<ListBox>
<Expander Header="Options">
<StackPanel>
<CheckBox Content="Option 1" />
<CheckBox Content="Option 2" />
<CheckBox Content="Option 3" />
</StackPanel>
</Expander>
<Expander Header="More Options">
<StackPanel>
<CheckBox Content="Option 1" />
<CheckBox Content="Option 2" />
<CheckBox Content="Option 3" />
</StackPanel>
</Expander>
</ListBox>
I'm trying to figure out how to:
Prevent the content portion of the Expander from changing colour when it is selected in the ListBox. I want only the Expander's header to have a blue background, not the CheckBoxes
Make an Expander the selected item in the ListView when its header is clicked. At the moment you have to click outside of the Expander's header's text to have it become selected in the list view
The solution to your first question is simple. Just add this into the ListBox.Resources:
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</ListBox.Resources>
You are free to change the colours to any that you prefer.
The solution to your second question is far from simple. I should like to say that declaring controls inside a ListBox is far from optimal. A much better solution is to create a data type class, bind a collection of these instances to the ListBox.ItemsSource property and then to create DataTemplates to define what each item should look like... that is where you should declare your Expander controls.
As at StackOverflow, we prefer one question to be asked per post, please try what I have just suggested, searching for the relevant terms online if necessary, and then come back with a new question, showing us your new code.

style of selected item in lisbox

I have a list box which is bound to a list of strings.
<ListBox Grid.Row="1"
Height="130"
Background="Black" BorderThickness="0"
ItemsSource="{Binding Images}"
ItemTemplate="{StaticResource PanoItemTemplate}"
SelectedItem="{Binding SelectedImage}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"
Height="110"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
and in VM I have:
public ObservableCollection<string> Images
{
get { return _images; }
}
public string SelectedImage
{
get { return _selectedImage; }
set
{
_selectedImage = value;
OnPropertyChanged("SelectedImage");
}
}
When I populate Image list and select one of them in listbox by clicking on it, I can get it in SelectedImage and the system works well.
When I click on an item on list box, it shows as selected I ListBox (Blue colour on white background).
If I set the SelectedImage in code to an item which is in image list, that item is selected on list, but the colour is different (it is white on white background).
How can I change the style of selectedImage when I select them via code to be the same as when user select them?
The ListBox will only highlight blue when it has user focus, otherwise it uses a different brush
When the ListBox is focused it used SystemColors.HighlightTextBrushKey, and when unfocused it uses SystemColors.InactiveSelectionHighlightBrushKey
So you could set the SystemColors.InactiveSelectionHighlightBrushKey to the SystemColors.HighlightColor, this will keep it blue in and out of focus.
Example:
<ListBox >
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="{x:Static SystemColors.HighlightColor}"/>
</ListBox.Resources>
</ListBox>
Edit:
For .NET4.0 and below you may have to use SystemColors.ControlBrushKey instead of SystemColors.InactiveSelectionHighlightBrushKey
<ListBox >
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="{x:Static SystemColors.HighlightColor}"/>
</ListBox.Resources>
</ListBox>

Styling `ListView` menu with round corners

I'm looking to build a menu using a ListView (I'm open to using anything else really that'll achieve the effect I'm looking for. The look I would like to emulate is the following.
Here is what I currently have for my XAML.
<ListView
ItemsSource="{Binding Decisions}"
SelectedItem="{Binding SelectedDecision}"
HorizontalAlignment="Left"
BorderThickness="0"
Width="350"
FontSize="12">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Border
BorderThickness="1"
BorderBrush="#DDD"
CornerRadius="2">
<TextBlock
Text="{Binding Converter={StaticResource DecisionTypeNameConverter}}"
Padding="8"
Background="#EEE" />
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This produces an alright looking menu until I select an item. Once an item is selected it is surrounded by an ugly dark blue. How can I recreate this look (the gradient effect isn't required) in XAML?
Do you need to track the SelectedItem?
If not, I would suggest using an ItemsControl
If so, you need to overwrite the selected item brush color so it doesn't show up. This is a system color, and I usually overwrite it like this:
<ListView.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</ListView>
In order to prevent the blue selection rectangle you would have to set the ItemContainerStyle instead of the ItemTemplate. Consult the MSDN on ListView Styles and Templates to find out about the ListViewItem default style, especially the "Selected" visual state.

How do I apply a Style Setter for ListBoxItems of a certain DataType?

My WPF ListBox contains two types of object: Product and Brand.
I want my Products selectable. I want my Brands not selectable.
Each of the two types has its own DataTemplate.
By default, anything may be selected:
<ListBox ... >
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:Product}">
...
</DataTemplate>
<DataTemplate DataType="{x:Type local:Brand}">
...
</DataTemplate>
</ListBox.Resources>
</ListBox>
I can set Focusable with a Setter, but then nothing may be selected:
<ListBox ... >
<ListBox.Resources>
...
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="False" />
</Style>
</ListBox.Resources>
</ListBox>
I cannot put the Setter within the DataTemplate.
I cannot put a DataType onto the Style.
How do I style only the ListBoxItems of type Brand?
Thanks to the StyleSelector class you can attach styles depending on type of data for the ItemContainerStyle. There is a really good example here : http://www.telerik.com/help/wpf/common-data-binding-style-selectors.html
Can you use a data trigger on your ListBoxItem style? If so, bind to the DataContext (your class) and use a value converter to test the type. If it's the one you're interested in, style the ListBoxItem so that it cannot appear selected.
I don't think you can disallow selection of an item in a Selector (parent of ListBox) without codebehind or a custom Behavior.

ListView Item Coming default selected with the first item in the list

I have a WPF ListView , where I bind an observable collection, and below is the code
<ListView Name="WOListView" IsSynchronizedWithCurrentItem="True"
DataContext="{Binding AllItems}"
ItemsSource="{Binding }"
SnapsToDevicePixels="True" Grid.IsSharedSizeScope="True"
customEvents:DoubleClickEvent.HandleDoubleClick="true"
customEvents:DoubleClickEvent.TheCommandToRun="{Binding Path=ItemCommand}"
BorderThickness="0" >
Here I have two issues
1) Dont know why, i always get an item selected when the load the list, and it is always the 1st item the the collection I bind.
2) The selected item is normally show in blue color by default, but when i click out side the listview,rather than deselecting the item.it shows the seleceted item as grey in color
For 1): This is due to the IsSynchronizedWithCurrentItem="True". If you want use the IsSynchronizedWithCurrentItem-feature, you propably want to influence the CurrentItem. Use the following code to do so...
var dv = CollectionViewSource.GetDefaultView(yourObservableCollection);
dv.MoveCurrentTo( /* here your desired selection */ );
... see here for more information.
For 2): this is the default behaviour of ListView (and other ListControls). If the list-control does not have anymore the focus, the selected items are showed in gray. This is done so to visualize which control has the focus (and which control has not).
If you want to change the selection-behaviour anyhow, put the following markup into the ListView
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Green"/>
</Style.Resources>
</Style>
</ListView.Resources>
Change the colors as you wish. But as I mentioned, the default behaviour is for showing the user which control has been selected and if you change this behaviour, some users may dislike...

Resources