WPF ListBox.SelectedItems 作为 ListBoxItem

问题描述 投票:0回答:2

有没有办法将

ListBox
的选定项目作为WPF中事件
ListBoxItem
(在
SelectionChanged
上)中的
ListBox

现在,当我致电

listBox.SelectedItems
时,我会收到数据源格式的项目列表。

例如,当我创建

ListBox
时,我将其绑定到
CustomListBoxViewModel
作为数据源,因此当我调用
SelectedItems
时,我会得到
CustomListBoxViewModel
对象的列表。

谢谢!

编辑:

所选答案中给出的代码非常适合我的用例。

另一方面,我完全理解这违反了 MVVM 模式。我将使用您在 xaml 视图后面的代码中提供的代码。

我最初问题背后的原因是我需要实现一个

ListBox
,其中有一些禁用的
ListBoxItems
。这些项目必须是不可选择的。

我尝试在我的 ListBoxItems 上使用附加属性

IsSelectable
,但效果不佳。此附加属性受到这篇post的极大启发。问题是,当我直接选择一个禁用的项目时,附加的属性工作得很好。无法选择该项目,并且它不在 SelectedItems 集合内。但是,如果我想通过按 CTRL+A 选择所有项目,则所有
ListBoxItems
都会被选中,甚至禁用的项目也会被选中,并在 SelectedItems 集合中找到。

c# wpf xaml data-binding wpf-controls
2个回答
5
投票

无论您这样做的原因是什么,这都可能严重违反 MVVM,让您终生后悔。

但是走向灭亡之路的第一步总是很容易的。

具体方法如下:

var listBox = (ListBox)sender;
var selectedListBoxItems = 
    listBox.SelectedItems.Cast<Object>()
    .Select(item => (ListBoxItem)listBox.ItemContainerGenerator.ContainerFromItem(item))
    .ToList();

当一切都以泪水结束时,请不要向我哭泣。

不,但是认真地说,有一些很好的理由在 WPF 中执行此类操作,但它们远没有 WPF 新手所期望的那么常见。几乎任何正常情况的最佳处理方式是让 C# 代码仅与数据项交互,并通过样式和模板对 XAML 中的 ListBoxItems 执行操作。一旦你习惯了这种思维方式,它就会非常强大、灵活、高效且可维护。代码隐藏是当所有其他合理途径都失败时您对奇怪情况所做的事情。例如,拖放。


0
投票

由于 MVVM 现在已经非常流行,在尊重 viewModel 原则的情况下,使用行为确实是我能找到的最简单的方法。

首先捕获事件并将其发送到 viewModel 中的 iCommand

Xaml:

<ListBox SelectionMode="Multiple" ItemsSource="{Binding SelectorFiles}" x:Name="Box">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding OnSelectionChanged}" CommandParameter="{Binding Path=SelectedItems, ElementName=Box}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

视图模型: 抓住它,打包它,投掷它,然后跳起你快乐的舞蹈。

public class XXXViewModel()
{
  public ObservableCollection<FileInfo> SelectorFiles { get; set; } = new();
  public List<FileInfo> SelectedFiles { get; set; } = new();

  public ICommand OnSelectionChanged { get; set; }

  ctor()
  {
    OnSelectionChanged = new DelegateCommand<ObservableCollection<FileInfo>>(Format());
  }

  private Action<ObservableCollection<FileInfo>> Format()
  {
    return items =>
    {
    SelectedFiles = items.ToList();
    // or do stuff :)
    };
  }

}
© www.soinside.com 2019 - 2024. All rights reserved.