WPF:禁用ListBox,但启用滚动

时间:2009-02-09 17:42:07

标签: wpf listbox scrollbar

整个上午都在抨击我的头。

基本上,我有一个列表框,我希望让人们不要在长时间运行的过程中更改选择,但允许他们仍然滚动。

解决方案:

所有答案都很好,我选择了吞咽老鼠事件,因为那是最直接的。我将PreviewMouseDown和PreviewMouseUp连接到一个事件,它检查了我的backgroundWorker.IsBusy,如果将事件args的IsHandled属性设置为true。

12 个答案:

答案 0 :(得分:8)

如果你查看ListBox的控件模板,里面有一个ScrollBar和ItemsPresenter。因此,禁用ItemsPresenter,您将轻松获得此功能。使用ListBox上的波纹管样式,你就可以了。

    <Style x:Key="disabledListBoxWithScroll" TargetType="{x:Type ListBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBox}">
                    <Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="1">
                        <ScrollViewer Padding="{TemplateBinding Padding}" Focusable="false">
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" IsEnabled="False" IsHitTestVisible="True"/>
                        </ScrollViewer>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        </Trigger>
                        <Trigger Property="IsGrouping" Value="true">
                            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

在ListBox上使用Style

<ListBox    Style="{DynamicResource disabledListBoxWithScroll}" ..... />

答案 1 :(得分:2)

抱歉,差不多已经两年了,但我认为使用DataTrigger的解决方案更简单。 How to disable a databound ListBox item based on a property value?

答案 2 :(得分:2)

我发现在启用了自动滚动的ScrollViewer中放置一个禁用的ListBox会产生预期的效果。

答案 3 :(得分:1)

虽然适用于Silverlight,但是这篇博文可能会帮助您朝着正确的方向前进? Silverlight No Selection ListBox and ViewBox

答案 4 :(得分:1)

诀窍是不要真的禁用。禁用将锁定滚动框中的所有消息。

在长时间操作期间,使用其.ForeColor属性使列表框中的文本变灰并吞下所有鼠标单击。这将模拟禁用控件并允许不受阻碍地滚动。

答案 5 :(得分:1)

我使用这个解决方案,它非常简单并且完美无缺:

对于您放入SurfaceListBoxItem item的每个Listbox,请执行以下操作:

item.IsHitTestVisible = false;

答案 6 :(得分:1)

这对我来说效果最好。这很容易,整个代码都在XAML中,这是IMO十分整洁的。

<ListBox ItemsSource="{Binding MySource}">
  <ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
      <Style.Triggers>
        <DataTrigger Binding="{Binding IsEditing}" Value="True">
          <Setter Property="IsEnabled" Value="True"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding IsEditing}" Value="False">
          <Setter Property="IsEnabled" Value="False"/>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </ListBox.ItemContainerStyle>  
</ListBox>

答案 7 :(得分:0)

另一个值得考虑的选择是禁用ListBoxItems。这可以通过设置ItemContainerStyle来完成,如下面的代码片段所示。

<ListBox ItemsSource="{Binding YourCollection}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsEnabled" Value="False" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

如果您不希望文本为灰色,可以通过使用以下键向样式的资源添加画笔来指定禁用的颜色:{x:Static SystemColors.GrayTextBrushKey}。另一种解决方案是覆盖ListBoxItem控件模板。

这个问题和这个问题几乎相同:There ain't ListBox.SelectionMode=“None”, is there another way to disable selection in a listbox?我的回答是一样的。

答案 8 :(得分:0)

我找到了一个非常简单直接的解决方案,我希望它能为你做到这一点

<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
     <Setter Property="Focusable" Value="False"/>
 </Style>

答案 9 :(得分:0)

使用http://www.codeproject.com/Tips/60619/Scrollable-Disabled-ListBox-in-WPF

的完整答案

风格:

<Style TargetType="{x:Type local:CustomListBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomListBox}">
                <Border SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="1">
                    <ScrollViewer IsEnabled="True">
                        <ItemsPresenter IsEnabled="{Binding Path=IsEnabledWithScroll,  RelativeSource={RelativeSource TemplatedParent}}"  SnapsToDevicePixels="{TemplateBinding  UIElement.SnapsToDevicePixels}"/>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

班级

public class CustomListBox : ListBox
{
    public bool IsEnabledWithScroll
    {
        get { return (bool)GetValue(IsEnabledWithScrollProperty); }
        set { SetValue(IsEnabledWithScrollProperty, value); }
    }

    public static readonly DependencyProperty IsEnabledWithScrollProperty =
        DependencyProperty.Register("IsEnabledWithScroll", typeof(bool), typeof(CustomListBox), new UIPropertyMetadata(true));
}

然后,而不是在ListBox上设置IsEnabled,而是使用IsEnabledWithScroll。如果启用或禁用列表框,则滚动将起作用。

答案 10 :(得分:0)

似乎有很多方法可以为这只特殊的猫提供皮肤。我发现通过在XAML中的IsHitTestVisible上设置ItemsContainerStyle,我得到了我所需要的:

<ListBox IsHitTestVisible="true" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsHitTestVisible" Value="False" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

答案 11 :(得分:0)

好吧,我找到了提供此功能的好方法。我所做的是在 listBox 的 DataTemplate 中,我使用 Page 作为源将父布局启用属性与布尔标志绑定在一起。

步骤 1 - 为页面提供 x:Name 属性。如果您使用的页面是用基页扩展的,那么请确保基页不是抽象类并且具有不带任何参数的默认构造函数。

<Page x:Class="OPMS.Views.Registration"
    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"
    x:Name="MainPage"
    d:DesignWidth="1024"
    Title="Registration"
>

第 2 步 - 使用页面作为 DataTemplate 父布局项 IsEnabled 属性的来源

<ListBox Grid.Row="2"
    ItemsSource="{Binding TestGroups}"
    AlternationCount="2"
    Padding="0"
    Margin="10,5,10,10"
>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Name}"
                IsChecked="{Binding IsSelected}"
                IsEnabled="{Binding Source={x:Reference MainPage}, Path=DataContext.BindingVariableHere}"
            />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>