wpf 如何将多个选择的列表视图绑定到视图模型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5741161/
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
How to bind multiple selection of listview to viewmodel?
提问by Ruben
I am implementing a listview, and a button next to it. I have to be able that when i select multiple items in a listview, and then click on a button, then the selected items are put into a list. But my question is , how do i bind the selected items towards the viewmodel? I changed my selectionmode to multiple. But then, do i just have to do:
我正在实现一个列表视图,以及它旁边的一个按钮。当我在列表视图中选择多个项目,然后单击一个按钮时,我必须能够做到这一点,然后将所选项目放入列表中。但我的问题是,如何将所选项目绑定到视图模型?我将选择模式更改为多个。但是,我是否只需要这样做:
SelectedItem={Binding path= selectedItems}
and then make in my viewmodel a property selectedItems, and it will set these items i have selected? Or what is the right solution to do this?
然后在我的视图模型中创建一个属性 selectedItems,它会设置我选择的这些项目?或者这样做的正确解决方案是什么?
采纳答案by Christian
What you can do is you can handle the Button_Click(...) in your code-behind. Then in that code-behind method you can create a List of selected items by iterating over the selected items of the listView.
你可以做的是你可以在你的代码隐藏中处理 Button_Click(...) 。然后在该代码隐藏方法中,您可以通过迭代 listView 的选定项目来创建选定项目的列表。
Since it is allowed to access the ViewModel from the View you can now call a method on your ViewModel and pass the list of selected items as a parameter.
由于允许从 View 访问 ViewModel,您现在可以在 ViewModel 上调用一个方法并将所选项目的列表作为参数传递。
I'm not sure if this would also work with Bindings only, however it is not bad practice to use code-behind as well.
我不确定这是否也仅适用于绑定,但是使用代码隐藏也不是坏习惯。
Example Code:
示例代码:
public void Button_Click(object sender, EventArguments arg)
{
List<ListViewItem> mySelectedItems = new List<ListViewItem>();
foreach(ListViewItem item in myListView.SelectedItems)
{
mySelectedItems.Add(item);
}
ViewModel.SomeMethod(mySelectedItems);
}
EDIT
编辑
Here is a minimalist example, XAML:
这是一个极简示例,XAML:
<DataTemplate
x:Key="CarTemplate"
DataType="{x:Type Car}">
</DataTemplate>
<ListView x:Name="myListView"
ItemsSource="{Binding Path=Cars}"
ItemTemplate="{StaticResource CarTemplate}">
</ListView>
CODE-BEHIND:
代码隐藏:
public void Button_Click(object sender, EventArguments arg)
{
List<Car> mySelectedItems = new List<Car>();
foreach(Car item in myListView.SelectedItems)
{
mySelectedItems.Add(item);
}
ViewModel.SomeMethod(mySelectedItems);
}
回答by Julio Nobre
Like Doctorhas already pointed out, you can bind SelectedItemsto XAML CommandParameter
就像Doctor已经指出的那样,您可以将SelectedItems绑定到 XAML CommandParameter
After a lot of digging and googling, I have finally found a simple solution to this common issue.
经过大量的挖掘和谷歌搜索,我终于找到了这个常见问题的简单解决方案。
To make it work you must follow ALL the following rules:
要使其工作,您必须遵循以下所有规则:
Following Ed Ball's suggestion', on you XAML command databinding, define CommandParameterproperty BEFORE Commandproperty. This a very time-consuming bug.
Make sure your ICommand's CanExecuteand Executemethods have a parameter of objecttype. This way you can prevent silencedcast exceptions that occurs whenever databinding CommandParametertype does not match your command method's parameter type.
private bool OnDeleteSelectedItemsCanExecute(object SelectedItems) { // Your goes here } private bool OnDeleteSelectedItemsExecute(object SelectedItems) { // Your goes here }
遵循Ed Ball 的建议',在您的 XAML 命令数据绑定上,定义CommandParameter属性 BEFORE Command属性。这是一个非常耗时的错误。
确保您的ICommand的CanExecute和Execute方法具有对象类型的参数。这样就可以防止沉默,每当发生数据绑定转换异常CommandParameter类型不匹配您的命令方法的参数类型。
private bool OnDeleteSelectedItemsCanExecute(object SelectedItems) { // Your goes here } private bool OnDeleteSelectedItemsExecute(object SelectedItems) { // Your goes here }
For example, you can either send a listview/listbox's SelectedItemsproperty to you ICommandmethods or the listview/listbox it self. Great, isn't it?
例如,您可以将列表视图/列表框的SelectedItems属性发送给您的ICommand方法或列表视图/列表框本身。很棒,不是吗?
Hope it prevents someone spending the huge amount of time I did to figure out how to receive SelectedItemsas CanExecuteparameter.
希望它可以防止有人花费大量时间来弄清楚如何将SelectedItems作为CanExecute参数接收。
回答by AbdouMoumen
It's kind of tricky to do this Mutliple Selection in MVVM, because the SelectedItems
property isn't a Dependency Property
. However, there are some tricks you can use. I found this triology of blog posts that describe the matter in some details and provide some useful solutions.
在 MVVM 中执行此多重选择有点棘手,因为该SelectedItems
属性不是Dependency Property
. 但是,您可以使用一些技巧。我发现这三篇博客文章详细描述了这个问题并提供了一些有用的解决方案。
Hope this helps
希望这可以帮助
回答by techhero
If you are using System.Windows.Interactivity and Microsoft.Expression.Interactions already, here is a workaround without any other code/behaviour to mess around. If you need these, it can be download from here
如果您已经在使用 System.Windows.Interactivity 和 Microsoft.Expression.Interactions,这里有一个解决方法,无需任何其他代码/行为。如果你需要这些,可以从这里下载
This workaround make use of interactivity event trigger and interactions set property mechanism in above assemblies.
此解决方法利用上述程序集中的交互事件触发器和交互设置属性机制。
Additional namespace declaration in XAML
XAML 中的其他命名空间声明
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
XAML:
XAML:
<ListView Name="MyListView" ItemsSource="{Binding ModelList}" DisplayMemberPath="Name" Grid.Column="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<ei:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedItems" Value="{Binding Path=SelectedItems, ElementName=MyListView}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
View Model:
查看型号:
public class ModelListViewModel
{
public ObservableCollection<Model> ModelList { get; set; }
public ObservableCollection<Model> SelectedModels { get; set; }
public ModelListViewModel() {
ModelList = new ObservableCollection<Model>();
SelectedModels = new ObservableCollection<Model>();
}
public System.Collections.IList SelectedItems {
get {
return SelectedModels;
}
set {
SelectedModels.Clear();
foreach (Model model in value) {
SelectedModels.Add(model);
}
}
}
}
In example above, your ViewModel will pick up the selected items whenever the selection on ListView changed.
在上面的示例中,只要 ListView 上的选择发生变化,您的 ViewModel 就会选取所选项目。
回答by Dummy01
Unfortunately the SelectedItems is a read only not bindable property.
不幸的是 SelectedItems 是只读的不可绑定属性。
I found a lot of help from this article How to Databind to a SelectedItems property in WPF
我从这篇文章如何数据绑定到 WPF 中的 SelectedItems 属性中 找到了很多帮助
回答by technicalflaw
If you are using Metro/WinRT
you may want to look at the WinRTXXAMLToolkitas it offers a bindable SelectedItems
dependency property as one of its extensions.
如果您正在使用,Metro/WinRT
您可能需要查看WinRTXXAMLToolkit,因为它提供了一个可绑定的SelectedItems
依赖属性作为其扩展之一。
回答by Doctor
You can't bind, but you can send to Command as an CommandParameter.
您无法绑定,但可以将其作为 CommandParameter 发送到 Command。
回答by Manas S
I did a solution for this, to me this was simple enough.
我为此做了一个解决方案,对我来说这很简单。
<ListBox ItemsSource="{Binding ListOfModel}" x:Name="ModelList"
SelectedItem="{Binding SelectedModel, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ExecuteListBoxSelectionChange}" CommandParameter="{Binding ElementName=ModelList}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
Then in the viewmodel:
然后在视图模型中:
public ICommand ExecuteListBoxSelectionChange { get; private set; }
ExecuteListBoxSelectionChange = DelegatingCommand<ListBox>.For(ListBoxSelectionChnageEvent).AlwaysEnabled();
SelectedModels is the list where I wanted the selection to be filled.
SelectedModels 是我想要填充选择的列表。
private void ListBoxSelectionChnageEvent(ListBox modelListBox)
{
List<ModelInfo> tempModelInfo = new List<ModelInfo>();
foreach(ModelInfo a in modelListBox.SelectedItems)
tempModelInfo.Add(a);
SelectedModels = tempModelInfo;
}
回答by Mitkins
As a slight variation on Christian's post, I implemented similar code using the ListView.SelectionChanged event. Instead of calling a method on the ViewModel, I set a property called SelectedItems:
作为 Christian 的帖子的一个细微变化,我使用 ListView.SelectionChanged 事件实现了类似的代码。我没有在 ViewModel 上调用方法,而是设置了一个名为 SelectedItems 的属性:
public void ListView_SelectionChanged( object s, SelectionChangedEventArgs e ) {
List<Car> mySelectedItems = new List<Car>();
foreach( Car item in myListView.SelectedItems )
mySelectedItems.Add(item);
ViewModel.SelectedItems = mySelectedItems;
}
This way, ViewModel.SelectedItems is available for any command you might have in your ViewModel andit can be used for data binding (if you turn it into an ObservableCollection).
这样,ViewModel.SelectedItems 可用于您可能在 ViewModel 中拥有的任何命令,并且可用于数据绑定(如果您将其转换为 ObservableCollection)。