ListView.SelectedItems
添加数据绑定能力,需要大量的代码。在我的情况下,我不需要从 ViewModel 设置它,只需获取所选项目以便对其执行操作,并且它是由命令触发的,因此不需要推送更新。
是否有简单的解决方案(以代码行数为单位),也许在代码后台? 只要 View 和 ViewModel 不需要相互引用,我就可以使用代码后台。 我认为这是一个更通用的问题:“ VM按需从视图获取数据的最佳实践”,但我似乎找不到任何东西...
ListView.SelectedItems
添加数据绑定能力,需要大量的代码。在我的情况下,我不需要从 ViewModel 设置它,只需获取所选项目以便对其执行操作,并且它是由命令触发的,因此不需要推送更新。
是否有简单的解决方案(以代码行数为单位),也许在代码后台? 只要 View 和 ViewModel 不需要相互引用,我就可以使用代码后台。 我认为这是一个更通用的问题:“ VM按需从视图获取数据的最佳实践”,但我似乎找不到任何东西...
当仅在执行命令时获取所选项 (SelectedItems
) 时,可以使用 CommandParameter
并传入 ListView.SelectedItems
。
<ListBox x:Name="listbox" ItemsSource="{Binding StringList}" SelectionMode="Multiple"/>
<Button Command="{Binding GetListItemsCommand}" CommandParameter="{Binding SelectedItems, ElementName=listbox}" Content="GetSelectedListBoxItems"/>
可以通过以下交互触发器来实现:
您需要添加对以下内容的引用:
Microsoft.Expression.Interactions System.Windows.Interactivity
将以下xmlns添加到您的xaml中
xmlns:i="http://schemas.microsoft.com/expression//2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
请在您的GridView标签内添加以下代码
<GridView x:Name="GridName">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding Datacontext.SelectionChangedCommand, ElementName=YourUserControlName}" CommandParameter="{Binding SelectedItems, ElementName=GridName}" />
</i:EventTrigger>
</i:Interaction.Triggers>
在 ViewModel 中声明以下属性的代码:
public DelegateCommand<object> SelectionChangedCommand {get;set;}
在 Viewmodel 的构造函数中,将 Command 初始化如下:
SelectionChangedCommand = new DelegateCommand<object> (items => {
var itemList = (items as ObservableCollection<object>).Cast<YourDto>().ToList();
}
SelectionChanged
事件并不是必须的,因为 ViewModel 只需要在执行命令时获取选定项。这更像是“VM如何按需从View中拉取数据”。 - NS.X.Following Ed Ball's suggestion', on you XAML command databinding, define CommandParameter property BEFORE Command property. This a very time-consuming bug.
Make sure your ICommand's CanExecute and Execute methods have a parameter of object type. This way you can prevent silenced cast exceptions that occurs whenever databinding CommandParameter type does not match your command method's parameter type.
private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)
{
// Your goes heres
}
private bool OnDeleteSelectedItemsExecute(object SelectedItems)
{
// Your goes heres
}
由于其他答案都没有帮助到我(使用SelectedItems
作为CommandParameter
始终为null
),这里提供了一种适用于通用 Windows 平台 (UWP) 应用程序的解决方案。它使用了Microsoft.Xaml.Interactivity
和Microsoft.Xaml.Interactions.Core
。
以下是视图:
<ListView x:Name="ItemsList">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="SelectionChanged">
<Core:InvokeCommandAction Command="{x:Bind ViewModel.SelectedItemsChanged}" />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<!-- content etc. -->
</ListView>
RelayCommand
是 MVVM Light 中的一个类):private List<YourType> _selectedItems = new List<YourType>();
private RelayCommand<SelectionChangedEventArgs> _selectedItemsChanged;
public RelayCommand<SelectionChangedEventArgs> SelectedItemsChanged
{
get
{
if (_selectedItemsChanged == null)
_selectedItemsChanged = new RelayCommand<SelectionChangedEventArgs>((selectionChangedArgs) =>
{
// add a guard here to immediatelly return if you are modifying the original collection from code
foreach (var item in selectionChangedArgs.AddedItems)
_selectedItems.Add((YourType)item);
foreach (var item in selectionChangedArgs.RemovedItems)
_selectedItems.Remove((YourType)item);
});
return _selectedItemsChanged;
}
}
_selectedItems
列表中删除这些项目! 如果您在foreach循环中执行此操作,则会收到InvalidOperationException
。 为避免出现此问题,请在标记位置添加保护,例如:if (_deletingItems)
return;
然后在你移除项目的方法中,执行以下操作:
_deletingItems = true;
foreach (var item in _selectedItems)
YourOriginalCollection.Remove(item);
_deletingItems = false;
SelectedItems
(复数)不支持数据绑定。请参见此链接和此链接。即使在使用CommandParameter
时也无法正常工作,我始终获得null
,而使用SelectedItem
(单数)就可以。 - NS.X.SelectedItems
不支持绑定。我已经从答案中删除了它。然而,CommandParameter
是有效的,我已经测试过并且能够获取所选项目的列表。 - evanbGetListItemsCommand
是在ViewModel中定义的命令时会发生什么?第一个绑定使用ViewModel作为DataContext,而第二个绑定到参数则使用自身作为DataContext... - rhcpfan