我整个早上都在苦思冥想这个问题。
基本上,我有一个列表框,我想在长时间运行的过程中防止人们更改选择,但仍允许他们滚动。
解决方案:
所有答案都很好,我选择了吞噬鼠标事件,因为这是最直接的方法。我将PreviewMouseDown和PreviewMouseUp连接到单个事件,该事件检查我的backgroundWorker.IsBusy,如果设置了IsHandled属性,则将其设置为true。
如果你查看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="{DynamicResource disabledListBoxWithScroll}" ..... />
诀窍在于不要真正禁用。禁用将锁定滚动框中的所有消息。
在长时间操作期间,使用其.ForeColor属性使列表框中的文本变灰,并吞噬所有鼠标点击。这将模拟禁用控件并允许无障碍滚动。
Listbox
中的每个 SurfaceListBoxItem item
,请执行以下操作:item.IsHitTestVisible = false;
这对我来说效果最好。它很简单,整个代码都在XAML中,我认为非常整洁。
<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>
<ListBox ItemsSource="{Binding YourCollection}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsEnabled" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
如果您不想将文本变成灰色,可以通过向样式资源添加刷子并使用以下键来指定禁用颜色:{x:Static SystemColors.GrayTextBrushKey}。另一种解决方案是覆盖ListBoxItem控件模板。
这个问题与没有ListBox.SelectionMode =“None”,是否有其他方法在列表框中禁用选择?几乎相同,我的答案也是一样的。
使用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。如果ListBox启用或禁用,滚动将正常工作。
ItemsContainerStyle
上的IsHitTestVisible
,我得到了我所需要的东西:<ListBox IsHitTestVisible="true" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
嗯,我找到了一个不错的方法来实现这个功能。我的做法是,在listBox的DataTemplate中,我使用Page作为源,将父布局的enable属性与布尔标志绑定。
步骤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"
>
步骤二 - 使用该页面作为数据模板父布局项的源,设置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>