C# 使用 MVVM 管理多个选择
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/803216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Managing multiple selections with MVVM
提问by Paul Alexander
On my journey to learning MVVM I've established some basic understanding of WPF and the ViewModel pattern. I'm using the following abstraction when providing a list and am interested in a single selected item.
在学习 MVVM 的过程中,我对 WPF 和 ViewModel 模式有了一些基本的了解。我在提供列表时使用以下抽象并且对单个选定项目感兴趣。
public ObservableCollection<OrderViewModel> Orders { get; private set; }
public ICollectionView OrdersView
{
get
{
if( _ordersView == null )
_ordersView = CollectionViewSource.GetDefaultView( Orders );
return _ordersView;
}
}
private ICollectionView _ordersView;
public OrderViewModel CurrentOrder
{
get { return OrdersView.CurrentItem as OrderViewModel; }
set { OrdersView.MoveCurrentTo( value ); }
}
I can then bind the OrdersView along with supporting sorting and filtering to a list in WPF:
然后,我可以将 OrdersView 与支持排序和过滤功能一起绑定到 WPF 中的列表:
<ListView ItemsSource="{Binding Path=OrdersView}"
IsSynchronizedWithCurrentItem="True">
This works really well for single selection views. But I'd like to also support multiple selections in the view and have the model bind to the list of selected items.
这对于单选视图非常有效。但我还想支持视图中的多项选择,并将模型绑定到所选项目的列表。
How would I bind the ListView.SelectedItems to a backer property on the ViewModel?
我如何将 ListView.SelectedItems 绑定到 ViewModel 上的支持者属性?
采纳答案by Josh G
Add an IsSelected
property to your child ViewModel (OrderViewModel
in your case):
IsSelected
为您的孩子 ViewModel添加一个属性(OrderViewModel
在您的情况下):
public bool IsSelected { get; set; }
Bind the selected property on the container to this (for ListBox in this case):
将容器上的 selected 属性绑定到此(在本例中为 ListBox):
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
IsSelected
is updated to match the corresponding field on the container.
IsSelected
更新以匹配容器上的相应字段。
You can get the selected children in the view model by doing the following:
您可以通过执行以下操作在视图模型中获取选定的子项:
public IEnumerable<OrderViewModel> SelectedOrders
{
get { return Orders.Where(o => o.IsSelected); }
}
回答by Simon_Weaver
If you're using MVVM-LIGHT you can use this pattern:
如果您使用的是 MVVM-LIGHT,则可以使用以下模式:
https://galasoft.ch/posts/2010/05/handling-datagrid-selecteditems-in-an-mvvm-friendly-manner
https://galasoft.ch/posts/2010/05/handling-datagrid-selecteditems-in-an-mvvm-friendly-manner
Not especially elegant but looks like it should be reliable at least
不是特别优雅,但看起来至少应该是可靠的
回答by MichaelLo
One can try creating an attached property.
可以尝试创建附加属性。
Doing so will save one from adding the IsSelected
property for each and every list you bind. I have done it for ListBox
, but it can be modified for use a in a list view.
这样做可以避免IsSelected
为您绑定的每个列表添加属性。我已经为 完成了它ListBox
,但可以修改它以在列表视图中使用 a。
<ListBox SelectionMode="Multiple"
local:ListBoxMultipleSelection.SelectedItems="{Binding SelectedItems}" >
More info: WPF – Binding ListBox SelectedItems – Attached Property VS Style .
回答by Julio Nobre
I can assure you: SelectedItems
is indeed bindable as a XAML CommandParameter
我可以向你保证:SelectedItems
确实可以作为 XAML 绑定CommandParameter
There is a simple solution to this common issue; to make it work you must follow ALLthe following rules:
这个常见问题有一个简单的解决方案;要使其工作,您必须遵循以下所有规则:
Following Ed Ball's suggestion, on your XAML command databinding, define the
CommandParameter
attribute BEFOREtheCommand
attribute. This a very time-consuming bug.Make sure your
ICommand
'sCanExecute
andExecute
methods have a parameter of typeobject
. This way you can prevent silencedcast exceptions that occur whenever the databinding'sCommandParameter
type does not match yourCommand
method's parameter type:private bool OnDeleteSelectedItemsCanExecute(object SelectedItems) { // Your code goes here } private bool OnDeleteSelectedItemsExecute(object SelectedItems) { // Your code goes here }
继埃德球的建议,你的XAML命令绑定,定义
CommandParameter
属性之前的Command
属性。这是一个非常耗时的错误。确保您
ICommand
的CanExecute
和Execute
方法具有类型为的参数object
。这样就可以防止沉默的发生每当数据绑定的转换异常CommandParameter
类型不匹配Command
方法的参数类型:private bool OnDeleteSelectedItemsCanExecute(object SelectedItems) { // Your code goes here } private bool OnDeleteSelectedItemsExecute(object SelectedItems) { // Your code goes here }
For example, you can either send a ListView
/ListBox
's SelectedItems
property to your ICommand
methods or the ListView
/ListBox
itself. Great, isn't it?
例如,您可以将ListView
/ListBox
的SelectedItems
属性发送到您的ICommand
方法或ListView
/ListBox
本身。很棒,不是吗?
I hope this prevents someone from spending the huge amount of time I did to figure out how to receive SelectedItems
as a CanExecute
parameter.
我希望这可以防止有人花费我所做的大量时间来弄清楚如何将其SelectedItems
作为CanExecute
参数接收。