通过MVVM RelayCommand从ListBox中删除SelectedItems

时间:2010-05-10 14:59:58

标签: wpf mvvm mvvm-light

我有一个WPF ListBox中的项目列表。我想允许用户选择其中几个项目,然后单击“删除”按钮从列表中删除这些项目。

使用MVVM RelayCommand模式,我创建了一个带有以下签名的命令:

public RelayCommand<IList> RemoveTagsCommand { get; private set; }

在我的视图中,我将这样的RemoveTagsCommand连接起来:

<DockPanel>
<Button DockPanel.Dock="Right" Command="{Binding RemoveTagsCommand}" CommandParameter="{Binding ElementName=TagList, Path=SelectedItems}">Remove tags</Button>
<ListBox x:Name="TagList" ItemsSource="{Binding Tags}" SelectionMode="Extended">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.Resources>
        <DataTemplate DataType="{x:Type Model:Tag}">
            ...
        </DataTemplate>
    </ListBox.Resources>
</ListBox>
</DockPanel>

我的ViewModel构造函数设置命令的实例:

RemoveTagsCommand = new RelayCommand<IList>(RemoveTags, CanRemoveTags);

我目前对RemoveTags的实现感觉很笨重,有强制转换和复制。有没有更好的方法来实现这个?

    public void RemoveTags(IList toRemove)
    {
        var collection = toRemove.Cast<Tag>();
        List<Tag> copy = new List<Tag>(collection);

        foreach (Tag tag in copy)
        {
            Tags.Remove(tag);
        }
    }

4 个答案:

答案 0 :(得分:4)

我使用ItemContainerStyle上的ListBox将项目'IsSelected属性绑定到模型中的标志(而不是视图模型),例如:

 <ListBox.ItemContainerStyle> 
    <Style TargetType="{x:Type ListBoxItem}">  
      <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>  
    </Style> 
 </ListBox.ItemContainerStyle>

然后你不必担心你传递给你的命令的论点。另外,根据我的经验,当视图模型中的对象很容易知道用户选择它时,您会发现该信息的其他用途。

命令中的代码如下:

foreach (Tag t in Tags.Where(x => x.IsSelected).ToList())
{
   Tags.Remove(t);
}

答案 1 :(得分:2)

虽然您可以使用SelectedItemsMode=OneWayToSource绑定到VM上的属性,然后使用RemoveTags中的绑定集合属性,但这对我来说看起来相当干净。我不完全确定,但在这种情况下你可以使用强类型的IList集合。

答案 2 :(得分:0)

为什么不指定RelayCommand的类型参数为List<Tag>,因为这是你要获得的?没有必要指定比它更通用的类型,因为执行的处理程序是硬编码的,可以使用Tag个对象列表。既然你已经在那里建立了依赖关系,你也可以在类型参数上创建它。然后你执行的处理程序将不需要任何强制转换或复制。

答案 3 :(得分:0)

1。)在ViewModel中将“删除”按钮绑定到命令。

2。)设置绑定时,使用CommandParameter从ListBox获取Selecteditems,为ListBox命名并使用ElementName = NameOfListBox,Path = SelectedItems

3.确保ViewModel中的Command传递参数。您将获得一个可以作为IList进行投射的对象。

下面是一个简单的例子,这可以帮助您设置结构。

在视图中:

<Button Command="{Binding CommandInViewModelForRemove}"
        CommandParameter="{Binding ElementName=blah,Path=SelectedItems}"

<ListBox x:Name="blah" .... />

在ViewModel中:

public ViewModel(){
    RemoveCommand = new RelayCommand<object>(Remove, CanRemove);
}

private void Remove(object selectedItems){
   var list = (IList)selectedItems;
   //do some work, cast to view models that represent list items, etc
}

希望这有帮助!