禁用列表视图中的元素选择?

Posted

技术标签:

【中文标题】禁用列表视图中的元素选择?【英文标题】:Disable selection of an element in Listview? 【发布时间】:2012-04-03 20:12:57 【问题描述】:

如何禁用列表视图中元素的选择?

我不想在单击 ListView 中的元素时更改背景。 你能帮帮我吗?

<ListView Name="milestone_listView" Margin="817,108,90,276" ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Visible" ItemsSource="Binding">
        <Grid Name="milestone_grid"></Grid>
    </ListView>

【问题讨论】:

你的意思是在 ListView 中绑定一个选中的项吗? 您不希望选择任何项目还是只选择特定项目? 我不希望所有项目都可以选择。 检查一下,我认为也适用于列表视图。 ***.com/questions/1398559/… 【参考方案1】:

通常我只是将SelectedItem 笔刷覆盖为透明,但如果您不想要选择功能,也可以使用ItemsControl 来显示您的列表

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

如果您确实使用 ItemsControl,请注意默认情况下它不会实现虚拟化,因此如果需要,您必须使用 implement it yourself

【讨论】:

您回答的第二部分是一个非常糟糕的解决方法。当 ListView 模板在未来的版本中更新以在选择上做更多的事情(例如动画)时会发生什么?或者这对所有主题都有什么保证?【参考方案2】:

如果您不希望任何项目可供选择,请使用 ItemsControl 而不是 ListView。

一个 ItemsControl 可以做任何 ListView 可以做的减去选择的事情。

编辑:

如果您需要 UI 虚拟化,您将需要使用 ItemsControl 做更多的事情。但我认为你现在不应该担心这个。从您的代码示例中,我什至认为您无论如何都不需要它。在需要时优化代码不要过早地尝试优化。目前,只需为作业使用正确的控件,即 ItemsControl。

【讨论】:

需要注意的是ItemsControl默认不支持虚拟化,而ListView支持 他可以为 ItemsControl ItemsPanel 添加一个虚拟化面板。 没错,不过有more to Virtualizing an ItemsControl than just using a VirtualizingStackPanel 是的,但这完全不是重点。如果您不想选择而不是通过列表控件破解您的方式,请使用 ItemsControl。如果您需要虚拟化,请使用 ItemsControl 中的虚拟化面板解决该问题。是的,它不是添加一个的单行解决方案,但它也不是火箭科学。 我在我的项目中使用了您的解决方案,但网格没有显示我在 .xaml.cs 中添加到网格的任何内容。有什么问题?【参考方案3】:

我使用的技巧是处理 SelectionChanged 事件并撤消选择,例如将 SelectedIndex 设置为 -1:

<ListView SelectionChanged="ListView_SelectionChanged" />

在代码隐藏中:

    private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    
        var listView = sender as ListView;
        if (listView != null)
        
            listView.SelectedIndex = -1;
        
    

【讨论】:

【参考方案4】:

或者,您可以采取更简单的方法,将 ListViewItem 的 IsEnabled 属性设置为 False。

在下面的示例中,我在绑定到我的 ListView 的项目上有一个“锁定”属性。如果是这样,我使用以下数据触发器禁用关联的 ListViewItem,然后使用其他样式在视觉上区分它。

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

【讨论】:

不幸的是,我不再使用 .NET,但我只能建议,也许以后的版本已经替换/弃用/破坏了功能......【参考方案5】:

我通过将 IsHitTestVisible 设置为 false 来解决它。当然,它并不适用于所有可能的情况,但在某些情况下会有所帮助。

【讨论】:

这行得通,但它会禁用一切,所以如果您希望用户能够与之交互的项目、按钮等中有任何东西,它就行不通。【参考方案6】:

此解决方案允许您在 ListViewItem 模板中设置某些元素,而不是通过阻止单击事件冒泡来触发行选择。

将此属性附加到元素。

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

声明一个命名空间以便你可以访问它:

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

并将其附加到元素上。

<Border ut:CancelMouseBubbling.Active="True" Background="#55171717">
...
</Border>

【讨论】:

以上是关于禁用列表视图中的元素选择?的主要内容,如果未能解决你的问题,请参考以下文章

Android:禁用列表视图内的元素滚动

Android:禁用网页视图中的文本选择

禁用 RecyclerView 的所有子视图

Django 2.2 如何在列表视图中禁用复选框

jQuery UI Draggable:克隆项目并禁用相同(原始项目)的第二次拖动

Android Studio 中的动态 ListView:选择随机元素并更新列表视图