有没有办法将
ListBox
的选定项目作为WPF中事件ListBoxItem
(在SelectionChanged
上)中的ListBox
?
现在,当我致电
listBox.SelectedItems
时,我会收到数据源格式的项目列表。
例如,当我创建
ListBox
时,我将其绑定到 CustomListBoxViewModel
作为数据源,因此当我调用 SelectedItems
时,我会得到 CustomListBoxViewModel
对象的列表。
谢谢!
编辑:
所选答案中给出的代码非常适合我的用例。
另一方面,我完全理解这违反了 MVVM 模式。我将使用您在 xaml 视图后面的代码中提供的代码。
我最初问题背后的原因是我需要实现一个
ListBox
,其中有一些禁用的 ListBoxItems
。这些项目必须是不可选择的。
我尝试在我的 ListBoxItems
上使用附加属性
IsSelectable,但效果不佳。此附加属性受到这篇post的极大启发。问题是,当我直接选择一个禁用的项目时,附加的属性工作得很好。无法选择该项目,并且它不在 SelectedItems 集合内。但是,如果我想通过按 CTRL+A 选择所有项目,则所有
ListBoxItems
都会被选中,甚至禁用的项目也会被选中,并在 SelectedItems 集合中找到。
无论您这样做的原因是什么,这都可能严重违反 MVVM,让您终生后悔。
但是走向灭亡之路的第一步总是很容易的。
具体方法如下:
var listBox = (ListBox)sender;
var selectedListBoxItems =
listBox.SelectedItems.Cast<Object>()
.Select(item => (ListBoxItem)listBox.ItemContainerGenerator.ContainerFromItem(item))
.ToList();
当一切都以泪水结束时,请不要向我哭泣。
不,但是认真地说,有有一些很好的理由在 WPF 中执行此类操作,但它们远没有 WPF 新手所期望的那么常见。几乎任何正常情况的最佳处理方式是让 C# 代码仅与数据项交互,并通过样式和模板对 XAML 中的 ListBoxItems 执行操作。一旦你习惯了这种思维方式,它就会非常强大、灵活、高效且可维护。代码隐藏是当所有其他合理途径都失败时您对奇怪情况所做的事情。例如,拖放。
由于 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 :)
};
}
}