2

私はMVVMを使用しています。2つのリストビューがあります。最初のリストビューは問題ありません。データを入力できます。IEnuerableです。私が達成したいのは、最初のリストビューの項目(行)をクリックしたときに、選択したものを2番目のリストビューに追加したいということです。誰でもこれについてアドバイスできますか?

4

3 に答える 3

4

MVVMを使用してやりたいことを行う方法を示すためItemViewModelに、リストビューにアイテムを表すものがあると仮定します。ListView.ItemTemplate各アイテムを適切にレンダリングするようにを設定する必要があります(または、ToStringメソッドをオーバーライドしてアイテムの文字列表現を返す)。

MainViewModel次の3つのプロパティが必要です。

  1. Items1アイテムのリストが含まれています。この例では、リストは更新されていないためIEnumerable<ItemViewModel>、十分です。

  2. SelectedItem1これは、最初のリストビュー(存在する場合)で現在選択されているアイテムを参照します。

  3. Items2これまでに選択したアイテムのリストが含まれています。このリストが更新されるため、ObservableCollection<ItemViewModel>使用されます。

の唯一の興味深いコードMainViewModelは、のセッターですSelectedItem1。これは、最初のリストビューでの選択が変更されるたびに変更されます。これが発生すると、選択したアイテムがコレクションに追加されますItems2

public class MainViewModel {

  ItemViewModel selectedItem1;

  public MainViewModel(IEnumerable<ItemViewModel> items1) {
    Items1 = items1;
    Items2 = new ObservableCollection<ItemViewModel>();
  }

  public IEnumerable<ItemViewModel> Items1 { get; private set; }

  public ObservableCollection<ItemViewModel> Items2 { get; private set; }

  public ItemViewModel SelectedItem1 {
    get { return this.selectedItem1; }
    set {
      this.selectedItem1 = value;
      if (this.selectedItem1 != null && !Items2.Contains(this.selectedItem1))
        Items2.Add(this.selectedItem1);
    }
  }

}

INotifyPropertyChangedこの例では必要ないため、この単純なビューモデルは実装されていないことに注意してください。

ビューは、次のようにXAMLを使用してビューモデルにバインドされます(たとえば、DataContextこのXAMLを含むものはすべてのインスタンスに設定する必要がありますMainViewModel)。

<StackPanel>
  <ListView ItemsSource="{Binding Items1}" SelectedItem="{Binding SelectedItem1}"/>
  <ListView ItemsSource="{Binding Items2}"/>
</StackPanel>

1つ目は、ビューモデルでListViewバインドされます。Items1での選択ListViewが変更されると、データバインディングSelectedItem1により、ビューモデルで設定されていることが保証されます。次に、セッターのコードがItems2プロパティを更新します。これはObservableCollection<T>新しいアイテムであるため、追加されたアイテムはデータバインディングを使用してプッシュされます(この場合は2番目に)ListView

ListViewあなたの場合、プロパティをバインドすることで、で選択イベントを処理することができSelectedItemます。ただし、データバインディングを使用して「イベントを処理」することが不可能な場合があります。解決策は、ビューのコードビハインドにイベントハンドラーを追加することですが、これにより、ビューモデルとビューの間に望ましくない依存関係が生じることがよくあります。代わりに、ブレンド動作を使用できます。独自のBehaviorクラスを作成することで、イベントを処理し、データバインドできるものに変換して、不要な依存関係を解消できます。ただし、特定の問題を解決するためにそれは必要ありません。

Behaviorを使用する場合は、BlendSDKは不要であることに注意してください。NuGetを使用して依存関係Blend.Interactivity.Wpf(またはフレームワークによっては同様のパッケージ)を追加し、BlendBehaviorsを使用するために必要な単一のDLLを取得できます。


したがって、クリックされたときに2番目のリストからアイテムの選択を解除する方法を拡張するには、ビヘイビアーを使用する必要があります。SelectedItem2番目にバインドされたプロパティのセッターでアクションが実行される上記と同じトリックを使用しようとするListViewと失敗します。2番目に新しいアイテムを追加するとListViewすぐにこのアイテムが選択され、すぐに新しく追加されたアイテムが削除されるためです。あなたが望むものではありません。

これは、MouseLeftButtonUpBehaviorコードビハインドなしで、コントロール上でマウスの左ボタンを離したときにコマンドを実行できるようにするものです。

class MouseLeftButtonUpBehavior : Behavior<Control> {

  public static readonly DependencyProperty CommandProperty
    = DependencyProperty.Register(
      "Command",
      typeof(ICommand),
      typeof(MouseLeftButtonUpBehavior)
    );

  public ICommand Command
  {
    get { return (ICommand) GetValue(CommandProperty); }
    set { SetValue(CommandProperty, value); }
  }

  protected override void OnAttached() {
    AssociatedObject.MouseLeftButtonUp += OnMouseLeftButtonUp;
  }

  protected override void OnDetaching() {
    AssociatedObject.MouseLeftButtonUp -= OnMouseLeftButtonUp;
  }

  void OnMouseLeftButtonUp(Object sender, MouseButtonEventArgs mouseButtonEventArgs) {
    if (Command != null)
      Command.Execute(mouseButtonEventArgs);
  }

}

XAMLをこれに変更する必要があります(NuGetを使用してBlend.Interactivity.Wpfパッケージへの参照を追加し、コントロールにインタラクションを追加できるようにすることができます)。

<StackPanel>
  <ListView ItemsSource="{Binding Items1}" SelectedItem="{Binding SelectedItem1}"/>
  <ListView ItemsSource="{Binding Items2}" SelectedItem="{Binding SelectedItem2}">
    <i:Interaction.Behaviors>
      <local:MouseLeftButtonUpBehavior Command="{Binding DeselectCommand}"/>
    </i:Interaction.Behaviors>
  </ListView>
</StackPanel>

ビューモデルには、次の2つの新しいプロパティが必要です。

public ItemViewModel SelectedItem2 { get; set; }

public ICommand DeselectCommand { get; private set; }

SelectedItem2、2番目のリストビューで選択されているアイテムを追跡するために使用されます。はDeselectCommand、2番目のリストビューでマウスの左ボタンアップイベントが発生したときに実行されます。実際に何か便利なことをするには、コマンドを作成する必要があります。を使用できますDelegateCommand。このクラスはWPFの一部ではありませんが、グーグルで検索すると、適切な実装を簡単に見つけることができます。Aは、選択したデリゲートを実行するDelegateCommandWPFを作成する方法にすぎません。ICommand

のコンストラクターでMainViewModel

DeselectCommand = new DelegateCommand(_ => Deselect());

そして、あなたはで実装する必要がありDeselectますMainViewModel

void Deselect() {
  if (SelectedItem2 != null)
    Items2.Remove(SelectedItem2);
}

これらすべてをまとめると、クリックされたときに2番目のリストビューからアイテムが削除されます。これにより、ビューにコードビハインドがなく、ビューからビューモデルへの不要な依存関係が作成される可能性があります(たとえば、ビューのコードはDeselectビューモデルを呼び出す必要があることを知っています)。

于 2012-10-29T14:56:44.493 に答える
1

panel / convas / gridに2つのリストビューを追加し、このコードを追加します。listView1のSelectionChangedイベント(イベントハンドラーlistView1_SelectionChanged)を必ず登録してください。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void listView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            listView2.Items.Add((listView1.SelectedItem));
        }

        private void Grid_Loaded(object sender, RoutedEventArgs e)
        {
            listView1.Items.Add("test 1");
            listView1.Items.Add("test 2");
        }
    }
}
于 2012-10-15T18:18:40.737 に答える
1

SelectionChangedイベントを使用します。その後、あなたは次のようなことをすることができます

Listview2.Items.Add(Listview1.SelectedItem);
于 2012-10-15T18:20:56.010 に答える