webentwicklung-frage-antwort-db.com.de

Wie handhabt man das SelectionChanged-Ereignis von ComboBox mit MVVM in wpf?

Wie kann das SelectionChanged-Ereignis von WPFs ComboBox mithilfe des MVVM-Musters ausgelöst werden?
Erklären Sie bitte ausführlich, ich bin neu bei WPF.

Ich möchte einige Operationen ausführen, wenn sich die Elementauswahl ComboBox geändert hat. Wie kann ich es auf eine MVVM-Weise erreichen?

27
Tanya

MVVM-Lösung :

Binden Sie die ItemsSource- und SelectedItem-Eigenschaften der ComboBox-Eigenschaft an Ihr ViewModel:

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

In MainViewModel.cs:

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

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

Code-Behind-Lösung :

Wenn Sie MVVM nicht verwenden möchten, können Sie Folgendes hinzufügen:

 <ComboBox SelectionChanged="ComboBox_SelectionChanged" />

Und fügen Sie dies in MainWindow.xaml.cs hinzu:

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

Ich bin ein großer Fan dieser Methode.

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>
13
Blackey

Ihr ViewModel muss INotifyPropertyChanged implementieren.

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"));
                }
            }
        }
    } 
}

Das zuvor veröffentlichte XAML ist korrekt:

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

Lassen Sie uns zunächst klarstellen, dass Sie das Ereignis nicht ändern können, sondern dass Sie es abonnieren können.

Da Sie keine Angaben dazu gemacht haben, von wo aus Sie Auswahländerungen bearbeiten möchten, gehe ich von den am häufigsten vorkommenden Szenarien aus - der Handhabung des zugrunde liegenden ViewModel. Laut MVVM sollte ViewModel nichts über View wissen, so dass Sie das View-Control nicht direkt von ViewModel aus abonnieren können. Sie können eine Eigenschaft von ViewModel jedoch entweder an SelectedItem oder an SelectedIndex binden, damit sie bei Auswahländerungen ausgelöst wird.

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

Es gibt andere Lösungen, die den Code hinter einem View durch Zugriff auf ein ViewModel über view.DataContext behandeln, aber ich würde vorschlagen, solche Praktiken zu vermeiden.

1
sll

Nur eine Erweiterung dieser Lösung die oben existiert, Falls Sie Prism Library verwenden 
(wenn nicht, dann hör jetzt auf zu lesen, es gibt nichts für dich)

Ich mag diese Lösung wirklich sehr, und ich denke, sie ist besser als jede andere Lösung. Ich möchte nur eine kleine Verbesserung der von Prism Library bereitgestellten Lösung vornehmen. 

diese Lösung verwendet 

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

beachten Sie den i: vor der InvokeCommandAction. Dies bedeutet, dass die InvokeCommandAction-Klasse im xmlns:i="http://schemas.Microsoft.com/expression/2010/interactivity"-Namespace vorhanden ist. Das ist gut und schön, aber beachten Sie, dass die Prism-Bibliothek genau dieselbe Klasse mit demselben Namen InvokeCommandAction hat. Es existiert nur in einem anderen Namespace, im Namespace xmlns:prism="http://prismlibrary.com/".

Sie können also die folgende XAML ersetzen

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

mit dieser XAML

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

OK, wir können das, was ist der Nutzen? 
Um den Nutzen zu bemerken, schreiben Sie den folgenden Befehl in das 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>
}

der Parameter ist null, wenn Sie <i:InvokeCommandAction> verwenden. 
Der Parameter ist NOT null, wenn Sie <prism:InvokeCommandAction> verwenden.

0
Hakam Fostok