Comment déclencher/gérer l'événement SelectionChanged
du ComboBox
de WPF à l'aide du modèle MVVM?
Expliquez en détail s'il vous plaît que je suis nouveau à WPF.
Ce que je veux, c’est faire quelques opérations lorsque la sélection de l’élément ComboBox
a changé. Comment puis-je y arriver, d'une manière MVVM?
Solution MVVM :
Liez les propriétés ItemsSource
et SelectedItem
de la ComboBox
aux propriétés de votre ViewModel:
<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}"/>
Dans MainViewModel.cs:
public ObservableCollection<string> MyItems { get; set; }
private string _mySelectedItem;
public string MySelectedItem
{
get { return _mySelectedItem; }
set
{
// Some logic here
_mySelectedItem = value;
}
}
Solution code-behind :
Si vous ne voulez pas utiliser MVVM, vous pouvez ajouter ceci:
<ComboBox SelectionChanged="ComboBox_SelectionChanged" />
Et ajoutez ceci dans MainWindow.xaml.cs:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Some logic here
}
Je suis un grand fan de cette méthode.
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>
Votre ViewModel doit implémenter 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"));
}
}
}
}
}
Le XAML précédemment posté est correct:
<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}"/>
En premier lieu, clarifions les choses: vous ne pouvez pas changer d’événement, mais vous pouvez vous y abonner.
Étant donné que vous n'avez fourni aucune information concernant le lieu où vous souhaitez gérer les modifications de sélection, je supposerai le scénario le plus courant - la gestion dans le ViewModel sous-jacent. Selon MVVM, ViewModel ne doit rien savoir de View, vous ne pouvez donc pas vous abonner directement de ViewModel à l'événement d'un contrôle View. Mais vous pouvez lier une propriété de ViewModel à SelectedItem
ou SelectedIndex
afin qu'elle se déclenche lorsque la sélection change.
<ComboBox
SelectedIndex="{Binding SelectedIndexPropertyName}"
... />
Il existe d'autres solutions permettant de manipuler le code derrière une vue en accédant à un ViewModel via view.DataContext
, mais je suggérerais d'éviter cette pratique, car il s'agit de cas de contournement.
Juste une amélioration de cette solution qui existe ci-dessus, si vous utilisez Prism Library
(si non, alors arrêtez de lire maintenant, il n'y a rien pour vous)
J'aime beaucoup cette solution et je pense que c'est mieux que toute autre solution. Je souhaite simplement apporter une petite amélioration à cette solution fournie par la bibliothèque Prism.
cette solution utilise
<i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
remarquez le i:
avant le InvokeCommandAction
. Cela signifie que la classe InvokeCommandAction
existe dans l’espace de nom xmlns:i="http://schemas.Microsoft.com/expression/2010/interactivity"
. C'est bien, mais notez que la bibliothèque Prism a exactement la même classe avec le même nom InvokeCommandAction
. Il existe simplement dans un autre espace de noms, dans l'espace de noms xmlns:prism="http://prismlibrary.com/"
.
Donc, en réalité, vous pouvez remplacer le XAML suivant
<i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
avec ce XAML
<prism:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
OK, on peut faire ça, quel est l'avantage?
Pour constater l’avantage, écrivez la commande suivante dans le 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>
}
le paramètre est null si vous utilisez <i:InvokeCommandAction>
Le paramètre e est NOT null si vous utilisez <prism:InvokeCommandAction>