WPF ListBox 可以“只读”吗?

Posted

技术标签:

【中文标题】WPF ListBox 可以“只读”吗?【英文标题】:Can a WPF ListBox be "read only"? 【发布时间】:2010-09-14 17:42:36 【问题描述】:

我们有一个场景,我们想要显示一个项目列表并指出哪个是“当前”项目(带有一个小箭头标记或改变了背景颜色)。

ItemsControl 对我们没有好处,因为我们需要“SelectedItem”的上下文。但是,我们希望以编程方式移动选择,并且不允许用户更改它。

有没有一种简单的方法可以让 ListBox 变成非交互式的?我们可以通过故意吞下鼠标和键盘事件来伪造它,但是我是否缺少一些基本属性(例如将“IsEnabled”设置为 false 而不会影响其视觉风格),这些属性可以满足我们的需求?

或者...是否有另一个 WPF 控件是两全其美的 - 具有 SelectedItem 属性的 ItemsControl?

【问题讨论】:

【参考方案1】:

一种选择是将ListBoxItem.IsEnabled 设置为false

<ListBox x:Name="_listBox">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsEnabled" Value="False"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

这可确保项目不可选择,但它们可能无法呈现您喜欢的样子。要解决此问题,您可以使用触发器和/或模板。例如:

<ListBox x:Name="_listBox">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsEnabled" Value="False"/>
            <Style.Triggers>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="Foreground" Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

【讨论】:

您的 ControlTemplate 正在执行 DataTemplate 的工作。除了 IsEnabled 的 Setter 之外,您只需要 您还可以将项目设置为对命中测试不可见(Setter Property="IsHitTestVisible" Value="False"),因此它们将照常呈现(因为被禁用而不是灰色)和滚动条仍然可以工作。【参考方案2】:

我有同样的问题。我通过将 IsEnabled 设置为 true 并处理 ListBox 的 PreviewMouseDown 事件来解决它。在处理程序中将 e.Handled 设置为 true,以防您不希望对其进行编辑。

    private void lstSMTs_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    
        e.Handled = !editRights;
    

【讨论】:

您仍然可以使用键盘更改选择。滚动条也不起作用【参考方案3】:

您的 ItemsControl/ListBox 是数据绑定的吗?

我只是想您可以将每个项目的背景画笔绑定到来自源数据的属性,或者通过转换器传递属性。类似的东西:

  <ItemsControl DataContext="Binding Source=StaticResource Things" ItemsSource="Binding" Margin="0">
    <ItemsControl.Resources>
      <local:SelectedConverter x:Key="conv"/>
    </ItemsControl.Resources>
    <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
        <local:Control Background="Binding Path=IsSelected, Converter=StaticResource conv"/>
      </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

【讨论】:

【参考方案4】:

能达到目的的魔法咒语是:

<ListBox IsHitTestVisible="False">

不幸的是,这也会阻止任何滚动条工作。

解决方法是将列表框放在滚动查看器中:

<ScrollViewer>
    <ListBox IsHitTestVisible="False">
    </ListBox>
</ScrollViewer>

【讨论】:

以上是关于WPF ListBox 可以“只读”吗?的主要内容,如果未能解决你的问题,请参考以下文章

WPF中的ListBox,ListView和DataGridView有啥区别

在wpf中,listbox中可以添加checkbox吗

从ROOT - 在Tkinter中将Listbox类移动到Toplevel时松散yScroll

将 WPF 控件设置为扩展以填充可用空间,仅此而已

WPF如何更改xaml代码里ListBox的数据绑定

WPF ListBox 自动滚动到结束