web-dev-qa-db-ja.com

wpfのMVVMでComboBoxのSelectionChangedイベントを処理する方法は?

MVVMパターンを使用してWPFのSelectionChangedComboBoxイベントを発生/処理する方法は?
詳しく説明してください。WPFの初心者です。

私が望むのは、ComboBoxアイテムの選択が変更されたときにいくつかの操作を行うことです。 MVVMの方法でどのように達成できますか?

33
Tanya

MVVMソリューション

ItemsSourceSelectedItemおよびComboBoxプロパティをViewModelのプロパティにバインドします。

<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}"/>

MainViewModel.cs内:

public ObservableCollection<string> MyItems { get; set; }

private string _mySelectedItem;
public string MySelectedItem
{
  get { return _mySelectedItem; }
  set
  {
    // Some logic here
    _mySelectedItem = value;
  }
}

コードビハインドソリューション

MVVMを使用したくない場合は、これを使用して追加できます。

 <ComboBox SelectionChanged="ComboBox_SelectionChanged" />

そして、これをMainWindow.xaml.csに追加します。

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Some logic here
}
44
snurre

私はこの方法の大ファンです。

xmlns:i="http://schemas.Microsoft.com/expression/2010/interactivity"

<ComboBox Grid.Column="2"  DisplayMemberPath="Data.name" ItemsSource="{Binding Model.Regions}" SelectedItem="{Binding Model.SelectedRegion}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ComboBox>
19
Blackey

ViewModelはINotifyPropertyChangedを実装する必要があります。

public class MyViewModel : INotifyPropertyChanged
{
    private string _mySelectedItem;
    public string MySelectedItem
    {
        get
        {
            return _mySelectedItem;
        }
        set
        {
            if (_mySelectedItem != value)
            {
                _mySelectedItem = value;
                // Perform any pre-notification process here.
                if (null != PropertyChanged)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("MySelectedItem"));
                }
            }
        }
    } 
}

以前に投稿されたXAMLは正しいです:

<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}"/> 
6
Steven Licht

これを拡張しただけです ソリューション 上記にあります、Prism Libraryを使用している場合
(そうでない場合、今すぐ読むのをやめて、あなたには何もありません)

私はこのソリューションが本当に好きで、他のどのソリューションよりも優れていると思います。PrismLibraryが提供するそのソリューションを少し強化したいだけです。

そのソリューションは使用しています

<i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />

InvokeCommandActionの前のi:に注意してください。これは、InvokeCommandActionクラスがxmlns:i="http://schemas.Microsoft.com/expression/2010/interactivity"名前空間に存在することを意味します。これは問題ありませんが、PrismライブラリにはInvokeCommandActionという同じ名前のまったく同じクラスがあることに注意してください。 xmlns:prism="http://prismlibrary.com/"名前空間の別の名前空間に存在するだけです。

実際には、次のXAMLを置き換えることができます

<i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />

このXAMLで

<prism:InvokeCommandAction Command="{Binding RegionChangedCmd}" />

OK、これを行うことができます、利点は何ですか?
利点を確認するには、ViewModelで次のコマンドを記述します

public ICommand RegionChangedCmd { get; }

public ViewModelConstructor() 
{
   RegionChangedCmd = new DelegateCommand<SelectionChangedEventArgs>(RegionChangedCmdExecuted);
}

public void RegionChangedCmdExecuted(SelectionChangedEventArgs e)
{
   // e parameter is null     if you use <i:InvokeCommandAction>
   // e parameter is NOT null if you use <prism:InvokeCommandAction>
}

<i:InvokeCommandAction>を使用する場合、eパラメーターはnull
eパラメータはNOT null<prism:InvokeCommandAction>を使用する場合

2
Hakan Fıstık

最初に、物事を明確にしましょう-イベントを変更することはできず、購読することができます。

選択の変更を処理する場所に関する情報を提供していないため、最も一般的なシナリオ-基礎となるViewModelでの処理を想定します。 MVVMによると、ViewModelはViewについて何も知らないため、ViewModelからViewのコントロールのイベントに直接サブスクライブすることはできません。ただし、ViewModelのプロパティをSelectedItemまたはSelectedIndexのいずれかにバインドできるため、選択が変更されるとトリガーされます。

<ComboBox 
       SelectedIndex="{Binding SelectedIndexPropertyName}" 
       ... />

view.DataContextを介してViewModelにアクセスすることにより、Viewの背後にあるコードを処理する他のソリューションがありますが、このような慣行を避けることをお勧めします。

1
sll