How to disable highlighting on listbox but keep selection? - wpf

I am having trouble finding how to not allow my ListBox to highlight the item selected. I know that I didn't add a trigger to highlight the item.
<ListBox Name="CartItems" ItemsSource="{Binding}"
ItemTemplate="{StaticResource TicketTemplate}"
Grid.Row="3" Grid.ColumnSpan="9" Background="Transparent"
BorderBrush="Transparent">
</ListBox>

<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Content.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource Self}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>

Late answer, but there's a much better and simpler solution:
<ListBox>
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</ListBox.Resources>
</ListBox>
This allows you to have a LisBox that looks just like an itemscontrol, but has support for selection.
Edit: How it works
This alters "colors of the system", in other words your windows theme, only for this ListBox and its children (we actually want to target the ListboxItem).
For example hovering a ListboxItem usually gives it a deep blue background, but here we set it to transparent (HighlightBrushKey).
Edit (30 June 2016):
It seems for latest Windows version this is not enough anymore, you also need to redefine InactiveSelectionHighlightBrushKey
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent" />
Thanks to #packoman in the comments

removing the highlighting completely feels very odd, as you dont know if you've selected anything, but here's a version of the control template that uses WhiteSmoke (which is very subtle) instead of Blue
<Window.Resources>
<Style x:Key="ListBoxItemStyle1" 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" 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>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="WhiteSmoke"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<ListBox HorizontalAlignment="Left" VerticalAlignment="Top" ItemContainerStyle="{DynamicResource ListBoxItemStyle1}">
<ListBoxItem Content="Item1"/>
<ListBoxItem Content="Item2"/>
<ListBoxItem Content="Item3"/>
<ListBoxItem Content="Item4"/>
<ListBoxItem Content="Item5"/>
<ListBoxItem Content="Item6"/>
</ListBox>
</Grid>

here's what worked for me.
<Style x:Key="ListBoxNoHighlight" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<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="Transparent"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>

In the Properties tab, there is an Enabled Field with 2 options, true and false. By turning this to false, the Listbox remains white and selection is not avaliable. Just figured this out!

I'm talking about a trick I did in my WP8 app.
I added a transparent frame image above it (the image's border was seen, think of it like a picture frame). The scroll was functional, any manipulation event was firing just that the Listbox items weren't selected anylonger.
<Grid
Grid.Row="0"
Margin="10,15"
Background="#FF008F88">
<ListBox
x:Name="listBox_content"
Margin="20,15"
VirtualizingStackPanel.VirtualizationMode="Recycling">
</ListBox>
<!-- TV image, middle is transparent so the ListBox can be seen -->
<Image
x:Name="image_tv"
Source="/Assets/Images/tvFrame.png"
Stretch="Fill"/>
<!---->
</Grid>
I guess this could work with a full transparent image set to Fill as well.

You will have to re-template ListBoxItem. In the default template, it has a trigger that highlights itself when IsSelected property is true. You just have to create a template that does not have that trigger.

I think you need to create a custom control template for the ListBoxItem, and include the trigger to change the background color to "Transparent" when the item is selected. Here is an example of how you can do this:
<ListBox x:Name="MyListBox">
<ListBox.Resources>
<ControlTemplate x:Key="ListBoxItemControlTemplate" TargetType="ListBoxItem">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="Content" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" TargetName="Bd" Value="Transparent"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template" Value="{StaticResource ListBoxItemControlTemplate}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

Related

How do I remove the white lines beside each TabItem?

I've recently taken to learning WPF for a project. I've been styling a TabControl to fit the colors of a component library I'm using, but these strange white lines have appeared beside each TabItem, but only between items or before the first item.
What are they, and how can I get rid of them? I tried using the inspector provided in Visual Studio but they aren't selectable, which leads me to believe they are some internal part of TabItem, but I'm stuck at this point.
Usage:
<TabControl Grid.Row="1"
TabStripPlacement="Bottom"
BorderBrush="#00000000"
BorderThickness="0"
Resources="{StaticResource TabControlResources}">
<TabItem Header="Story">
<local:Workspace />
</TabItem>
<TabItem Header="Test">
Test Tab
</TabItem>
<TabItem Header="Test">
Test Tab 2
</TabItem>
</TabControl>
And style definition:
<ResourceDictionary x:Key="TabControlResources">
<Style TargetType="TabControl">
<Setter Property="Background"
Value="{StaticResource Fluent.Ribbon.Brushes.RibbonTabControl.Background}"/>
<Setter Property="Foreground"
Value="{StaticResource Fluent.Ribbon.Brushes.IdealForegroundColorBrush}" />
</Style>
<Style TargetType="TabItem">
<Setter Property="Foreground"
Value="{StaticResource Fluent.Ribbon.Brushes.IdealForegroundColorBrush}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background"
Value="{StaticResource Fluent.Ribbon.Brushes.RibbonTabControl.Background}" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Background"
Value="{StaticResource Fluent.Ribbon.Brushes.RibbonTabItem.Active.Background}" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Those are part of the TabItem. You can add the setter in the tab item style within your resource which should do the job:
<Style TargetType="{x:Type TabItem}">
<Setter Property="BorderBrush" Value="Red"/>
</Style>
And the result will be such:
Alternatively:
You can completely remove it, but unfortunately it is part of the template and the template has to be modified:
In Visual studio designer right click on one of the tab items and go to "Edit template" then "Edit a copy".
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid x:Name="templateRoot" SnapsToDevicePixels="true">
<Border x:Name="mainBorder" BorderBrush="Red" BorderThickness="0" Background="{TemplateBinding Background}" Margin="0">
<Border x:Name="innerBorder" BorderBrush="{StaticResource TabItem.Selected.Border}" BorderThickness="0" Background="{StaticResource TabItem.Selected.Background}" Margin="-1" Opacity="0"/>
</Border>
<ContentPresenter x:Name="contentPresenter" ContentSource="Header" Focusable="False" HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
</Grid>
In there you have to modify the BorderThichness of mainBorder and innerBoarder to BorderThickness="0"
Result:

ComboBox Size Differences

I have 2 ComboBox's in a app settings flyout. One of which has an ItemTemplate defined and the other does not:
<StackPanel Orientation="Horizontal"
Margin="5">
<Label Content="Accent"
VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding MetroAccents}"
SelectedItem="{Binding SelectedAccent}"
Margin="5">
<ComboBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Name}"
Margin="0"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<StackPanel Orientation="Horizontal"
Margin="5">
<Label Content="Grid Lines"
VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding GridLinesVisibilityList}"
SelectedItem="{Binding SelectedGridLinesVisibility}"
Margin="5"/>
However, the ComboBox with the ItemTemplate has a larger height than the other ComboBox. Analysing the control with the 'Enable Selection' debugging tool, the ComboBox with the ItemTemplate seems to have a TextBlock with the Label (defined in the template). Whereas the other ComboBox only has a Label. Does anyone know why this is?
Label will take more space due to it's default style which looks like this:
<Style x:Key="LabelStyle1" TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Which as you can see has padding on it. While the TextBlock does not. This is why it takes more space.
Bear in mind that Label supports key bindings with _ underscore and also other UI elements as it's content. I personally don't use it unless I need key bindings, but even then I use AccessText MSDN.

Change Background Color of SelectedItem in ListBox in .NET 4.5 WPF

I want to change the background color of a ListBox's SelectedItem. I tried the below code :
<ListBox Grid.Column="0" ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ItemsSource="{Binding Parents}" DisplayMemberPath="Title"
Height="35" FontSize="18" BorderThickness="0" Background="#FF2A2A2A"
Foreground="White" SelectedIndex="0">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="DodgerBlue" />
</Trigger>
</Style.Triggers>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
Color="Transparent" />
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
But I cannot see any change in SelectedItems's Background Color. Can anybody point the mistake in above XAML?
Also I want to use this style for this specific ListBox, so I don't want to change ControlTemplate.
Try this:
<ListBox Grid.Column="1" Grid.Row="1" Margin="2" SelectionMode="Multiple" ItemsSource="{Binding NavigationMenuItems}" DisplayMemberPath="Name">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
<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>
<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>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
In .NET 4.5 system does not use SystemColors by default, therefore you should:
1) create your own Style/ControlTemplate;
2) create a BlankListBoxContainer like in this example:
<Style x:Key="BlankListBoxContainerStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FocusVisualStyle" Value="{x:Null} "/>
</Style>
3) remove the difference between the frameworks, like this:
FrameworkCompatibilityPreferences.AreInactiveSelectionHighlightBrushKeysSupported = false;
before any Window are created, for example before InitializeComponent().
From MSDN:
AreInactiveSelectionHighlightBrushKeysSupported:
Gets or sets a value that indicates whether the application should use the InactiveSelectionHighlightBrush and InactiveSelectionHighlightTextBrush properties for the colors of inactive selected items.

TextBox TextTrimming

I would like to apply a TextTrimming option on a TextBox (Not a TextBlock).
The compiler tells me that the TextTrimming options is not a valid property of the Textbox.
I could do a fancy control that is a Textblock and once it's clicked will become a Textbox and conversely go back to being a Textblock once the focus is lost.
Before going this way I would like to know if a built-in function already exists (or is there a smarter way) to allow you to do that?
EDIT: What I want to have in the end is a TextBox which is trim (the full content will be display in a tooltip) but when the user select the TextBox (enter in "edit mode") the full content will be display (without trim) therefore the user will be able to modify the full text. when the TextBox lost the focus (go back to "view mode") the content will be trim again.
Thanks
Try a style like this (I've added background colours to make the change obvious):
<Style TargetType="TextBox">
<Setter Property="Background" Value="Yellow" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<TextBlock Text="{TemplateBinding Text}" TextTrimming="CharacterEllipsis" Background="Red" />
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Dan Puzey has a great answer, but I wanted to add more so that the style of the TextBlock appeared like a TextBox.
Here is the XAML style I came up with:
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border BorderThickness="1" CornerRadius="1">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFABADB3" Offset="0"/>
<GradientStop Color="#FFABADB3" Offset="0.044"/>
<GradientStop Color="#FFE2E3EA" Offset="0.060"/>
<GradientStop Color="#FFE3E9EF" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<TextBlock Padding="4,2,0,0" Text="{TemplateBinding Text}" TextTrimming="CharacterEllipsis"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
This is what the control looks like when it has no keyboard focus:
This is what the control looks like after gaining keyboard focus:
I think wat you are looking for is this
<TextBox Text="{Binding Path=String, Converter={StaticResource StringConverter}, ConverterParameter=Trim:Argument:AnotherArgument}" />
I hope it helps :)
It will call the trim function and pass any arguments, if you want.
You can also use split and pass the delimiters as arguments.
You can find more on Binding.Converter here
I would use different control template: template with trimming when text box is not focused, whereas text box is focused I would use the regular template to allow text selection.
Needs to replace TextBox control template.
<ControlTemplate TargetType="{x:Type TextBox}"
x:Key="ControlTemplateTextBoxNormal">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Border x:Name="ErrorElement"
Visibility="Collapsed"
BorderThickness="1.25"
BorderBrush="{StaticResource BrushError}">
<Grid>
<Polygon x:Name="toolTipCorner"
Panel.ZIndex="2"
Margin="-1"
Points="9,9 9,0 0,0"
Fill="{StaticResource BrushError}"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Polygon.ToolTip>
<ToolTip Style="{StaticResource ToolTipStyleError}"
Content="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" />
</Polygon.ToolTip>
</Polygon>
</Grid>
</Border>
<ScrollViewer x:Name="PART_ContentHost"
Padding="{TemplateBinding Padding}"
BorderThickness="0"
IsTabStop="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}" />
<TextBlock Text="{Binding Path=(behaviors:TextBoxBehaviors.WatermarkText), RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
IsHitTestVisible="False"
Visibility="Collapsed"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
Foreground="Gray"
x:Name="watermark" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused"
Value="False">
<Setter Property="Visibility"
TargetName="watermark"
Value="Visible" />
</Trigger>
<Trigger Property="Validation.HasError"
Value="True">
<Setter Property="Visibility"
TargetName="ErrorElement"
Value="Visible" />
</Trigger>
<!--<Trigger Property="behaviors:TextBoxBehaviors.WatermarkText"
Value="True">
<Setter Property="Visibility"
TargetName="ErrorElement"
Value="Visible" />
</Trigger>-->
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource {x:Type TextBox}}"
x:Key="TextBoxStyleTrimming">
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Validation.ErrorTemplate"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Border x:Name="ErrorElement"
Visibility="Collapsed"
BorderThickness="1.25"
BorderBrush="{StaticResource BrushError}">
<Grid>
<Polygon x:Name="toolTipCorner"
Panel.ZIndex="2"
Margin="-1"
Points="9,9 9,0 0,0"
Fill="{StaticResource BrushError}"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Polygon.ToolTip>
<ToolTip Style="{StaticResource ToolTipStyleError}"
Content="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" />
</Polygon.ToolTip>
</Polygon>
</Grid>
</Border>
<TextBlock Padding="{TemplateBinding Padding}"
Text="{TemplateBinding Text}"
TextTrimming="CharacterEllipsis"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}" />
<TextBlock Text="{Binding Path=(behaviors:TextBoxBehaviors.WatermarkText), RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
IsHitTestVisible="False"
Visibility="Collapsed"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
Foreground="Gray"
x:Name="watermark" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused"
Value="False">
<Setter Property="Visibility"
TargetName="watermark"
Value="Visible" />
</Trigger>
<Trigger Property="Validation.HasError"
Value="True">
<Setter Property="Visibility"
TargetName="ErrorElement"
Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsKeyboardFocused"
Value="True">
<Setter Property="Template"
Value="{StaticResource ControlTemplateTextBoxNormal}" />
</Trigger>
</Style.Triggers>
</Style>
You may create a control template for your TextBox that display the usual editor when focused, and a TextBlock with trimming when it's not.

WPF ListView turn off selection

Is it possible to turn off the selection of a WPF ListView, so when user clicks row, the row is not highlighted?
(source: konim5am at artax.karlin.mff.cuni.cz)
I would like the row 1 to look just like row 0 when clicked.
Possibly related: can I style the look of the hover / selection? Eg. to replace the blue gradient hover look (line 3) with a custom solid color. I have found this and this, unfortunately not helping.
(Achieving the same without using ListView is acceptable too. I'd just like to be able to use logical scrolling and UI virtualization as ListView does)
The XAML for ListView is:
<ListView Height="280" Name="listView">
<ListView.Resources>
<!-- attempt to override selection color -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightColorKey}"
Color="Green" />
</ListView.Resources>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
<!-- more columns -->
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Per Martin Konicek's comment, to fully disable the selection of the items in the simplest manner:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Focusable" Value="false"/>
</Style>
</ListView.ItemContainerStyle>
...
</ListView>
However if you still require the functionality of the ListView, like being able to select an item, then you can visually disable the styling of the selected item like so:
You can do this a number of ways, from changing the ListViewItem's ControlTemplate to just setting a style (much easier). You can create a style for the ListViewItems using the ItemContainerStyle and 'turn off' the background and border brush when it is selected.
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="{x:Null}" />
<Setter Property="BorderBrush"
Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
...
</ListView>
Also, unless you have some other way of notifying the user when the item is selected (or just for testing) you can add a column to represent the value:
<GridViewColumn Header="IsSelected"
DisplayMemberBinding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />
Moore's answer doesn't work, and the page here:
Specifying the Selection Color, Content Alignment, and Background Color for items in a ListBox
explains why it cannot work.
If your listview only contains basic text, the simplest way to solve the problem is by using transparent brushes.
<Window.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#00000000"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#00000000"/>
</Style.Resources>
</Style>
</Window.Resources>
This will produce undesirable results if the listview's cells are holding controls such as comboboxes, since it also changes their color. To solve this problem, you must redefine the control's template.
<Window.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border SnapsToDevicePixels="True"
x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<GridViewRowPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Columns="{TemplateBinding GridView.ColumnCollection}"
Content="{TemplateBinding Content}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Set the style of each ListViewItem to have Focusable set to false.
<ListView ItemsSource="{Binding Test}" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Here's the default template for ListViewItem from Blend:
Default ListViewItem Template:
<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 HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</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.InactiveSelectionHighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
Just remove the IsSelected Trigger and IsSelected/IsSelectionActive MultiTrigger, by adding the below code to your Style to replace the default template, and there will be no visual change when selected.
Solution to turn off the IsSelected property's visual changes:
<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 HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
The easiest way I found:
<Setter Property="Focusable" Value="false"/>
Okay, little late to the game, but none of these solutions quite did what I was trying to do.
These solutions have a couple problems
Disable the ListViewItem, which screws up the styles and disables all the children controls
Remove from the hit-test stack, i.e. children controls never get a mouse-over or click
Make it not focusable, this just plain didn't work for me?
I wanted a ListView with the grouping headers, and each ListViewItem should just be 'informational' without selection or hover over, but the ListViewItem has a button in it that I want to be click-able and have hover-over.
So, really what I want is the ListViewItem to not be a ListViewItem at all, So, I over rode the ListViewItem's ControlTemplate and just made it a simple ContentControl.
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ContentControl Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
Further to the solution above... I would use a MultiTrigger to allow the MouseOver highlights to continue to work after selection such that your ListViewItem's style will be:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsMouseOver" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
One of the properties of the listview is IsHitTestVisible.
Uncheck it.
Use the code below:
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
This is for others who may encounter the following requirements:
Completely replace the visual indication of "selected" (e.g. use some kind of shape), beyond just changing the color of the standard highlight
Include this selected indication in the DataTemplate along with the other visual representations of your model, but,
Don't want to have to add an "IsSelectedItem" property to your model class and be burdened with manually manipulating that property on all model objects.
Require items to be selectable in the ListView
Also would like to replace the visual representation of IsMouseOver
If you're like me (using WPF with .NET 4.5) and found that the solutions involving style triggers simply didn't work, here's my solution:
Replace the ControlTemplate of the ListViewItem in a style:
<ListView ItemsSource="{Binding MyStrings}" ItemTemplate="{StaticResource dtStrings}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
..And the DataTemplate:
<DataTemplate x:Key="dtStrings">
<Border Background="LightCoral" Width="80" Height="24" Margin="1">
<Grid >
<Border Grid.ColumnSpan="2" Background="#88FF0000" Visibility="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsMouseOver, Converter={StaticResource conBoolToVisibilityTrueIsVisibleFalseIsCollapsed}}"/>
<Rectangle Grid.Column="0" Fill="Lime" Width="10" HorizontalAlignment="Left" Visibility="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected, Converter={StaticResource conBoolToVisibilityTrueIsVisibleFalseIsCollapsed}}" />
<TextBlock Grid.Column="1" Text="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />
</Grid>
</Border>
</DataTemplate>
Results in this at runtime (item 'B' is selected, item 'D' has mouse over):
Below code disables ListViewItem row selection and also allows to add padding, margin etc.
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ListViewItem Padding="0" Margin="0">
<ContentPresenter />
</ListViewItem>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
Below code disable Focus on ListViewItem
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ListView Grid.Row="1" ItemsSource="{Binding Properties}" >
<!--Disable selection of items-->
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid Background="{TemplateBinding Background}">
<Border Name="Selection" Visibility="Collapsed" />
<!-- This is used when GridView is put inside the ListView -->
<GridViewRowPresenter Grid.RowSpan="2"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="90" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Width="90" CellTemplateSelector="{StaticResource customCellTemplateSelector}" />
</GridView>
</ListView.View>
</ListView>
Another similar control to ListView and ListBox that doesn't offer selection is ItemsControl, consider using that instead.
One more way to disable selection.
<ListView ...>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsEnabled="False"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
It's like
<ListView IsEnabled="False">
but without disabled scroller

Resources