WPF ListView turn off selection

WpfListview

Wpf Problem Overview


Is it possible to turn off the selection of a WPF ListView, so when user clicks row, the row is not highlighted?

ListView

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>

Wpf Solutions


Solution 1 - Wpf

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}" />
					

Solution 2 - Wpf

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>

Solution 3 - Wpf

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>

Solution 4 - Wpf

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>

Solution 5 - Wpf

The easiest way I found:

<Setter Property="Focusable" Value="false"/>

Solution 6 - Wpf

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>

Solution 7 - Wpf

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

  1. Disable the ListViewItem, which screws up the styles and disables all the children controls
  2. Remove from the hit-test stack, i.e. children controls never get a mouse-over or click
  3. 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>

Solution 8 - Wpf

One of the properties of the listview is IsHitTestVisible. Uncheck it.

Solution 9 - Wpf

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>

Solution 10 - Wpf

This is for others who may encounter the following requirements:

  1. Completely replace the visual indication of "selected" (e.g. use some kind of shape), beyond just changing the color of the standard highlight
  2. Include this selected indication in the DataTemplate along with the other visual representations of your model, but,
  3. 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.
  4. Require items to be selectable in the ListView
  5. 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):

ListView appearance

Solution 11 - Wpf

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> 

Solution 12 - Wpf

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>

Solution 13 - Wpf

        <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>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMartin KonicekView Question on Stackoverflow
Solution 1 - WpfrmooreView Answer on Stackoverflow
Solution 2 - WpfMark MarkindaleView Answer on Stackoverflow
Solution 3 - WpfHayley GuillouView Answer on Stackoverflow
Solution 4 - WpfBen WildeView Answer on Stackoverflow
Solution 5 - WpfMartin KonicekView Answer on Stackoverflow
Solution 6 - WpfReddogView Answer on Stackoverflow
Solution 7 - WpfBradley BurnsideView Answer on Stackoverflow
Solution 8 - WpfJacob LevertovView Answer on Stackoverflow
Solution 9 - WpfJorge FreitasView Answer on Stackoverflow
Solution 10 - WpfBCAView Answer on Stackoverflow
Solution 11 - WpfSaikat ChakrabortyView Answer on Stackoverflow
Solution 12 - WpfmincasoftView Answer on Stackoverflow
Solution 13 - Wpfuser3526723View Answer on Stackoverflow