2

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

4 に答える 4

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);
}
于 2010-05-10T17:32:03.553 に答える
3

これは私にはかなりきれいに見えますがSelectedItems、VM のプロパティにバインドしMode=OneWayToSourceRemoveTags.
完全にはわかりませんが、この場合、厳密に型指定された IList コレクションを使用できる可能性があります。

于 2010-05-10T16:29:27.073 に答える
0

RelayCommandとにかく取得しようとしているので、の型引数をに指定してみませんList<Tag>か?Tag実行されるハンドラーはオブジェクトのリストを処理するようにハードコーディングされているため、それよりも一般的なタイプを指定しても意味がありません。すでに依存関係を作成しているので、type引数にも依存関係を作成することをお勧めします。そうすれば、実行されたハンドラーはキャストやコピーを必要としません。

于 2010-05-10T16:22:27.237 に答える
0

1.) ViewModel で [削除] ボタンをコマンドにバインドします。

2.) バインディングを設定するときは、ListBox に名前を付けて ElementName=NameOfListBox, Path=SelectedItems を使用することにより、CommandParameter を使用して ListBox から Selecteditem を取得します。

3.) ViewModel の Command が引数を渡すようにします。IList としてキャストできるオブジェクトを取得します。

以下は簡単な例です。これは、構造をセットアップするのに役立ちます。

ビューで:

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

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

ビューモデルで:

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
}

お役に立てれば!

于 2010-05-10T18:39:22.213 に答える