3

How to disable selection for an element in a Listview?

I don't want to change the background when I click the elem in ListView. Can you help me?

<ListView Name="milestone_listView" Margin="817,108,90,276" ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Visible" ItemsSource="{Binding}">
        <Grid Name="milestone_grid"></Grid>
    </ListView>
NVM
  • 5,442
  • 4
  • 41
  • 61
user1278322
  • 299
  • 2
  • 4
  • 4

6 Answers6

10

If you want none of the items to be selectable use an ItemsControl and not a ListView.

An ItemsControl can do everything that a ListView can do minus selection.

Edit:

If you need UI virtualization you will need to do more stuff with the ItemsControl. But I don't think you should worry about that now. From your code sample I don't even think you will need it anyway. Optimize your code when you need it don't prematurely try to optimize. At the moment just use the correct control for the job which is an ItemsControl.

NVM
  • 5,442
  • 4
  • 41
  • 61
  • 1
    It should be noted that `ItemsControl` doesn't support Virtualization by default, while a `ListView` does – Rachel Mar 19 '12 at 13:42
  • He can add a virtualizating panel for the ItemsControl ItemsPanel. – NVM Mar 19 '12 at 13:47
  • That's true, however there's [more to Virtualizing an ItemsControl than just using a `VirtualizingStackPanel`](http://stackoverflow.com/q/2783845/302677) – Rachel Mar 19 '12 at 14:09
  • Yes but its completely besides the point. Use an ItemsControl if you don't want selection rather than hack your way through a list control. If you then need virtualization solve that problem using a virtualizing panel in your ItemsControl. Yes its not a one line solution to add one but its not rocket science either. – NVM Mar 19 '12 at 14:30
  • I using your solution in my project, but the grid doesn't display any thing which I add to grid in .xaml.cs. What wrong with it? – user1278322 Mar 20 '12 at 20:38
  • You should not be adding it in code behind. To do it correctly you should bind the items from a view model using the [mvvm pattern](http://stackoverflow.com/questions/1405739/mvvm-tutorial-from-start-to-finish). And here's [Rachel's blog entry](http://rachel53461.wordpress.com/2011/09/17/wpf-itemscontrol-example/) on how to use an ItemsControl – NVM Mar 20 '12 at 20:50
  • ItemsControl does not have a View which is needed when you want to use the GridView – Wouter Apr 03 '14 at 10:09
  • Saved my day big time – electricalbah Jul 09 '14 at 07:19
8

Usually I just overwrite the SelectedItem brush to be transparent, although you can also use an ItemsControl to display your list if you don't want selection capabilities

<ListView.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" />
</ListView.Resources>

If you do use an ItemsControl instead, be warned that it doesn't implement virtualization by default so you have to implement it yourself if you want it

Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • The second part of you answer is a very poor workaround. What happens when the ListView template is updated in a future release to do more stuff on selection like for example an animation? Or what guarantees does this have of working on all themes? – NVM Mar 19 '12 at 13:44
3

The trick I use is to handle the SelectionChanged event and undo the selection, say by setting SelectedIndex to -1:

<ListView SelectionChanged="ListView_SelectionChanged" />

In the code-behind:

    private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var listView = sender as ListView;
        if (listView != null)
        {
            listView.SelectedIndex = -1;
        }
    }
user1454265
  • 868
  • 11
  • 25
2

Alternatively, you can just take the much easier approach of setting the IsEnabled property of your ListViewItem to False.

In the example below I have a 'Locked' property on the items that are bound to my ListView. When this is true I use the following data trigger to disable the associated ListViewItem, then I use other styles to visually differentiate it.

    <ListView.Resources>
        <Style TargetType="{x:Type ListViewItem}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Locked}" Value="True">
                    <Setter Property="IsEnabled" Value="False" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListView.Resources>
Wolfshead
  • 540
  • 6
  • 8
  • Unfortunately I don't use .NET any more, but I can only suggest that perhaps a later version has replaced/deprecated/broken the functionality... – Wolfshead Jul 13 '20 at 15:54
1

I solved it by setting IsHitTestVisible to false. Of course, it is not suitable for every possible case, but in some cases it can be helpful.

lena
  • 1,181
  • 12
  • 36
  • This works, but it disables everything, so if you have anything in the item, buttons, etc. you'd like the user to be able to interact with, it doesnt work. – Moulde Feb 15 '17 at 09:58
0

This solution lets you set certain elements within your ListViewItem template not trigger a row selection by blocking the click event bubbling.

Attach this property to an element.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace YourNamespaceName
{
    public class CancelMouseBubbling : DependencyObject
    {
        public static readonly DependencyProperty ActiveProperty = DependencyProperty.RegisterAttached(
            "Active",
            typeof(bool),
            typeof(CancelMouseBubbling),
            new PropertyMetadata(false, ActivePropertyChanged));

        /// <summary>
        /// Subscribe to the events we need.
        /// </summary>
        private static void ActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as FrameworkElement;
            if (element != null)
            {
                if ((e.NewValue as bool?).GetValueOrDefault(false))
                {
                    element.PreviewMouseLeftButtonDown += ElementOnPreviewMouseLeftButtonDown;
                    element.MouseLeftButtonDown += ElementOnMouseLeftButtonDown;
                }
                else
                {
                    element.PreviewMouseLeftButtonDown -= ElementOnPreviewMouseLeftButtonDown;
                    element.MouseLeftButtonDown -= ElementOnMouseLeftButtonDown;
                }
            }
        }

        /// <summary>
        /// Block some events from bubbling at the OriginalSource.
        /// </summary>
        private static void ElementOnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            if (mouseButtonEventArgs.Source is Panel)
            {
                mouseButtonEventArgs.Handled = true;
            }
        }

        /// <summary>
        /// Block all clicks from going past the element CancelMouseBubbling is set on
        /// </summary>
        private static void ElementOnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            mouseButtonEventArgs.Handled = true;
        }

        [AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
        [AttachedPropertyBrowsableForType(typeof(FrameworkElement))]
        public static bool GetActive(DependencyObject @object)
        {
            return (bool)@object.GetValue(ActiveProperty);
        }

        public static void SetActive(DependencyObject @object, bool value)
        {
            @object.SetValue(ActiveProperty, value);
        }
    }
}

Declare a namespace so that you can access it:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:ut="clr-namespace:YourNamespaceName"></UserControl>

And attach it to an element.

<Border ut:CancelMouseBubbling.Active="True" Background="#55171717">
...
</Border>
jv_
  • 1,784
  • 1
  • 16
  • 12