我正在实现一个ListView和一个相应的按钮。我需要能够在选择了多项ListView中的项目后,点击按钮将选定的项目放入列表中。但我的问题是,如何将选定的项目绑定到ViewModel? 我将SelectionMode更改为Multiple。那么,我只需要执行以下操作吗:
SelectedItem={Binding path= selectedItems}
然后在我的视图模型中创建一个selectedItems属性,它会设置我所选的这些项?或者有什么正确的解决方案可以做到这一点?
我正在实现一个ListView和一个相应的按钮。我需要能够在选择了多项ListView中的项目后,点击按钮将选定的项目放入列表中。但我的问题是,如何将选定的项目绑定到ViewModel? 我将SelectionMode更改为Multiple。那么,我只需要执行以下操作吗:
SelectedItem={Binding path= selectedItems}
然后在我的视图模型中创建一个selectedItems属性,它会设置我所选的这些项?或者有什么正确的解决方案可以做到这一点?
就像Doctor已经指出的一样,你可以将SelectedItems绑定到XAML CommandParameter
经过大量挖掘和搜索,我终于找到了一个简单的解决方案来解决这个常见问题。
要使它工作,您必须遵循以下所有规则:
按照Ed Ball的建议,在您的XAML命令数据绑定中,在定义Command属性之前定义CommandParameter属性。这是一个非常耗时的错误。
确保您的ICommand的CanExecute和Execute方法具有object类型的参数。这样,您就可以防止CommandParameter类型与您的命令方法的参数类型不匹配时发生的静默转换异常。
private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)
{
// Your goes here
}
private bool OnDeleteSelectedItemsExecute(object SelectedItems)
{
// Your goes here
}
例如,您可以将列表视图/Listbox的 SelectedItems 属性发送到您的 ICommand 方法或列表视图/Listbox本身。很棒,不是吗?
希望它可以防止有人像我一样花费巨额时间来弄清楚如何将 SelectedItems 作为 CanExecute 参数接收。
SelectedItems
在System.Windows.Controls
中,而我在ViewModels中没有引用它。解决方案是将预期的命令参数类型设置为System.Collections.IEnumerable
,然后使用Cast<>
进行转换。 - Benjolxmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
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>
视图模型:
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);
}
}
}
}
在上面的示例中,无论何时ListView上的选择发生更改,您的ViewModel都将获取所选项。
ListBox
的Loaded
事件,并在其中对我的SelectModels
属性运行循环,逐个将所有这些模型添加到ListBox的SelectedItems
中。 - undefined您可以在代码后台处理Button_Click(...)。然后在此代码后台方法中,通过遍历listView的选定项创建所选项列表。
由于允许从视图访问ViewModel,因此现在可以在ViewModel上调用一个方法并将所选项列表作为参数传递。
我不确定这是否仅适用于绑定,但使用代码后台也不是不好的做法。
示例代码:
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);
}
编辑
以下是一个极简示例,使用XAML:
<DataTemplate
x:Key="CarTemplate"
DataType="{x:Type Car}">
</DataTemplate>
<ListView x:Name="myListView"
ItemsSource="{Binding Path=Cars}"
ItemTemplate="{StaticResource CarTemplate}">
</ListView>
后台代码:
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);
}
我为此提供了一个解决方案,对我来说这非常简单。
<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>
然后在视图模型中:
public ICommand ExecuteListBoxSelectionChange { get; private set; }
ExecuteListBoxSelectionChange = DelegatingCommand<ListBox>.For(ListBoxSelectionChnageEvent).AlwaysEnabled();
SelectedModels 是我想要填充选择的列表。
private void ListBoxSelectionChnageEvent(ListBox modelListBox)
{
List<ModelInfo> tempModelInfo = new List<ModelInfo>();
foreach(ModelInfo a in modelListBox.SelectedItems)
tempModelInfo.Add(a);
SelectedModels = tempModelInfo;
}
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;
}
这样,ViewModel.SelectedItems 可以在 ViewModel 中的任何命令中使用,并且可以用于数据绑定(如果将其转换为 ObservableCollection)。