WPF: Disable ListBox, but enable scrolling

我们两清 提交于 2019-11-30 03:51:47

问题


Been banging my head against this all morning.

Basically, I have a listbox, and I want to keep people from changing the selection during a long running process, but allow them to still scroll.

Solution:

All the answers were good, I went with swallowing mouse events since that was the most straight forward. I wired PreviewMouseDown and PreviewMouseUp to a single event, which checked my backgroundWorker.IsBusy, and if it was set the IsHandled property on the event args to true.


回答1:


The trick is to not really disable. Disabling will lock out all messages from the scroll box.

During the long operation, gray out the text in the list box using its .ForeColor property and swallow all mouse clicks. This will simulate disabling the control and allow scrolling unimpeded.




回答2:


If you look in to the control template of the ListBox, there is a ScrollBar and ItemsPresenter inside. So Make the ItemsPresenter Disabled and you will get this easily. Use the bellow Style on the ListBox and you are good to go.

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

On the ListBox use the Style

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



回答3:


sorry it has been almost two years, but I think this solution that uses DataTrigger is even simpler. How to disable a databound ListBox item based on a property value?




回答4:


I found that putting a disabled ListBox in a ScrollViewer with auto scrolling enabled gives the desired effect.




回答5:


While it's for Silverlight, maybe this blog post would help you get going in the right direction? Silverlight No Selection ListBox and ViewBox




回答6:


I used this solution, it's really easy and works perfectly:

For every SurfaceListBoxItem item you put in the Listbox, do this:

item.IsHitTestVisible = false;



回答7:


This worked best for me. It's easy and whole code is in XAML which is IMO very neat.

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



回答8:


Another option worth considering is disabling the ListBoxItems. This can be done by setting the ItemContainerStyle as shown in the following snippet.

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

If you don't want the text to be grey you can specify the disabled color by adding a brush to the style's resources with the following key: {x:Static SystemColors.GrayTextBrushKey}. The other solution would be to override the ListBoxItem control template.

This question is pretty much the same as this one: There ain't ListBox.SelectionMode=“None”, is there another way to disable selection in a listbox? and my answer is the same.




回答9:


I found a very simple and straight forward solution working for me, I hope it would do for you as well

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




回答10:


A complete answer using http://www.codeproject.com/Tips/60619/Scrollable-Disabled-ListBox-in-WPF

The Style:

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

The class

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

Then instead of setted IsEnabled on the ListBox, use IsEnabledWithScroll instead. Scrolling will work if the listbox is enabled or disabled.




回答11:


There seem to be many ways to skin this particular cat. I found that by setting IsHitTestVisible on the ItemsContainerStyle in XAML I got exactly what I needed:

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


来源:https://stackoverflow.com/questions/529121/wpf-disable-listbox-but-enable-scrolling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!