.net 正在ViewModel中获取WPF ListView.SelectedItems
有一些帖子讨论了为.net 正在ViewModel中获取WPF ListView.SelectedItems,.net,wpf,listview,data-binding,mvvm,.net,Wpf,Listview,Data Binding,Mvvm,有一些帖子讨论了为ListView添加数据绑定功能。在我的场景中,我不需要从ViewModel中设置它,只需要获取所选项目以对其执行操作,它由命令触发,因此也不需要推送更新 是否有一个简单的解决方案(在代码行方面),可能是在代码隐藏中?只要View和ViewModel不需要相互引用,我就可以使用代码隐藏。我认为这是一个更一般的问题:“VM从按需视图获取数据的最佳实践”,但我似乎什么也找不到……/P> < P>我认为认为“强->视图和视图模型不需要互相了解< /强>”是正确的条件;在MVVM视图中
ListView添加数据绑定功能。在我的场景中,我不需要从ViewModel
中设置它,只需要获取所选项目以对其执行操作,它由命令触发,因此也不需要推送更新
是否有一个简单的解决方案(在代码行方面),可能是在代码隐藏中?只要View
和ViewModel
不需要相互引用,我就可以使用代码隐藏。我认为这是一个更一般的问题:“VM从按需视图获取数据的最佳实践”,但我似乎什么也找不到……/P> < P>我认为认为“强->视图和视图模型不需要互相了解< /强>”是正确的条件;在MVVM视图中,始终了解ViewModel
我也遇到过这样的情况,我必须在视图的代码隐藏中访问ViewModel,然后填充一些数据(如所选项目),这在使用第三方控件(如ListView、DataGrid等)时是必要的
如果无法直接绑定VM属性,则我将侦听ListViw.SelectionChanged事件,然后在该事件中更新我的ViewModels SelectedItems属性
更新:
要启用VM从视图中提取数据,您可以在视图上公开一个处理视图特定功能的接口,并且ViewModel将通过该接口引用您的视图;使用界面仍然可以使视图和视图模型在很大程度上保持解耦,但我不喜欢这样
我仍然更喜欢在视图中处理事件并保持VM更新的方法(使用所选项目),这样VM在执行任何操作之前不必担心提取数据,它只需要使用可用的数据(因为这些数据总是更新的).要仅在执行命令时获取SelectedItems
,请使用CommandParameter
并传入列表视图。选择editems
<ListBox x:Name="listbox" ItemsSource="{Binding StringList}" SelectionMode="Multiple"/>
<Button Command="{Binding GetListItemsCommand}" CommandParameter="{Binding SelectedItems, ElementName=listbox}" Content="GetSelectedListBoxItems"/>
这可以通过如下交互触发器实现
SelectionChangedCommand = new DelegateCommand<object> (items => {
var itemList = (items as ObservableCollection<object>).Cast<YourDto>().ToList();
}
您需要添加对的引用
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;}
public DelegateCommand SelectionChangedCommand{get;set;}
在Viewmodel的构造函数中初始化命令,如下所示
SelectionChangedCommand = new DelegateCommand<object> (items => {
var itemList = (items as ObservableCollection<object>).Cast<YourDto>().ToList();
}
SelectionChangedCommand=newdelegateCommand(项=>{
var itemList=(项目作为ObservableCollection.Cast().ToList();
}
我可以向您保证:SelectedItems确实可以绑定为XAMLCommandParameter
经过大量的挖掘和谷歌搜索,我终于找到了这个常见问题的简单解决方案
要使其正常工作,您必须遵守以下所有规则:
在XAML命令数据绑定之后,在命令属性之前定义命令参数属性。这是一个非常耗时的错误
确保您的ICommand的CanExecute和Execute方法具有object类型的参数。这样可以防止在数据绑定CommandParameter类型与您的命令方法的参数类型不匹配时发生沉默强制转换异常
private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)
{
// Your goes heres
}
private bool OnDeleteSelectedItemsExecute(object SelectedItems)
{
// Your goes heres
}
例如,您可以将listview/listbox的SelectedItems属性发送给您ICommand方法,也可以将listview/listbox本身发送给您。太好了,不是吗
希望它能防止有人花费我所做的大量时间来找出如何将SelectedItems作为CanExecute参数来接收。因为其他答案对我都没有帮助(使用SelectedItems
作为CommandParameter
总是null
),这是一个针对通用Windows平台(UWP)应用程序的解决方案。它使用Microsoft.Xaml.Interactivity
和Microsoft.Xaml.interactiviations.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>
请注意,如果您要在选择完成后从原始集合中删除项目(用户按下按钮等),它还将从您的\u selectedItems
列表中删除项目!如果您在foreach循环中执行此操作,您将获得无效操作异常
。要避免此情况,只需在标记的位置添加一个防护,如:
if (_deletingItems)
return;
然后,在您删除项目的方法中,执行以下操作:
_deletingItems = true;
foreach (var item in _selectedItems)
YourOriginalCollection.Remove(item);
_deletingItems = false;
抱歉,我不清楚。互不了解意味着一方不引用另一方。注册到SelectionChanged
事件也不是完全必要的,因为ViewModel只需要在执行命令时获取所选项目。这更像是“VM如何根据需要从视图中提取数据”。SelectedItems
(复数)不支持数据绑定。请参阅和。它也不作为CommandParameter
工作,在使用SelectedItem
(单数)时,我总是得到null
很好。@user986080我没有意识到SelectedItems
不支持绑定。我从答案中删除了它。但是CommandParameter
确实有效,我已经测试了它,并且能够查看所选项目的列表。我的XAML示例显示了一个列表框
,但我也测试了一个列表视图
,并且可以从命令参数中获取所选项目。我想我正在点击,这是一个很麻烦的解决方法。但理想情况下,您的答案是正确的。非常感谢您提供此CommandParameter解决方案。对我来说效果非常好