WPF MVVM: zone de liste déroulante valeur après SelectionChanged
Je suis nouveau en C# et MVVM, et j'ai passé toute la journée à essayer d'obtenir la valeur d'un ComboBox
à mon ViewModel sur SelectionChanged
. J'ai réussi à le comprendre, à l'aide soit de CallMethodAction
ou InvokeCommandAction
avec les ressources:
System.Windows.Interactivity.dll
Microsoft.Expression.Interactions.dll
Mon problème, c'est que ces deux méthodes renvoient la valeur de la ComboBox
avant, il a changé. Quelqu'un pourrait-il expliquer comment obtenir la valeur après le changement?
J'ai passé des heures à chercher par soi et Google pour trouver une solution, donc je me demande si les autres sont trop. Tous les conseils seront appréciés!
Mon code est ci-dessous:
MainWindow.xaml
<Window x:Class="SelectionChange.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:si="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:vm="clr-namespace:SelectionChange"
Title="MainWindow" Width="300" Height="300">
<Window.DataContext>
<vm:ViewModel />
</Window.DataContext>
<Grid>
<ComboBox Name="SelectBox" VerticalAlignment="Top" SelectedIndex="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<si:CallMethodAction MethodName="SelectionChanged" TargetObject="{Binding}" />
<!--<i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding ElementName=SelectBox, Path=Text}" />-->
</i:EventTrigger>
</i:Interaction.Triggers>
<ComboBoxItem Content="Item 1" />
<ComboBoxItem Content="Item 2" />
<ComboBoxItem Content="Item 3" />
</ComboBox>
</Grid>
</Window>
ViewModel.cs
namespace SelectionChange
{
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
public class ViewModel
{
public ViewModel()
{
SelectionChangedCommand = new SelectionChangedCommand();
}
public ICommand SelectionChangedCommand
{
get;
set;
}
public void SelectionChanged(object sender, EventArgs e)
{
ComboBox SelectBox = (ComboBox)sender;
MessageBox.Show("Called SelectionChanged: " + SelectBox.Text);
}
}
}
SelectionChangedCommand.cs
namespace SelectionChange
{
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
public class SelectionChangedCommand : ICommand
{
public SelectionChangedCommand()
{
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
MessageBox.Show("Executed SelectionChangedCommand: " + parameter);
}
}
}
Edit: Ma Solution
Il s'avère que je ne comprenais pas Binding
assez bien et essayait plutôt de mettre en œuvre quelque chose de simple un peu compliqué! Au lieu d'utiliser les dépendances, j'ai réalisé ce que j'avais besoin de l'aide régulière de liaisons. Comme un exemple, j'ai lié une TextBox
à la SelectedIndex
de la ComboBox
, qui est mise à jour à l'aide de INotifyPropertyChanged
.
MainWindow.xaml
<Window x:Class="SelectionChange.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SelectionChange"
Title="MainWindow" Width="300" Height="300">
<Window.DataContext>
<vm:ViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ComboBox SelectedItem="{Binding SelectedItem}" SelectedIndex="0" Grid.Column="0" VerticalAlignment="Top">
<ComboBoxItem Content="Item 1" />
<ComboBoxItem Content="Item 2" />
<ComboBoxItem Content="Item 3" />
</ComboBox>
<!-- TextBox to display the ComboBox's SelectedIndex -->
<TextBox Text="{Binding SelectedIndex}" Grid.Column="1" VerticalAlignment="Top" />
</Grid>
</Window>
ViewModel.cs
namespace SelectionChange
{
using System;
using System.ComponentModel;
using System.Windows.Controls;
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
}
//Property to store /retrieve ComboBox's SelectedIndex
private int _SelectedIndex;
public int SelectedIndex { get; set; }
//Property to bind to ComboBox's SelectedItem
private ComboBoxItem _SelectedItem;
public ComboBoxItem SelectedItem
{
get { return _SelectedItem; }
set
{
_SelectedItem = value;
//SelectedItem's Content
string Content = (string)value.Content;
//SelectedItem's parent (i.e. the ComboBox)
ComboBox SelectBox = (ComboBox)value.Parent;
//ComboBox's SelectedIndex
int Index = SelectBox.SelectedIndex;
//Store the SelectedIndex in the property
SelectedIndex = Index;
//Raise PropertyChanged with the name of the stored property
RaisePropertyChanged("SelectedIndex");
}
}
//INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
Je vais juste laisser tomber une idée pour vous. Que diriez-vous lier SelectedItems propriété d'une propriété dans votre ViewModel avec le mode de liaison Bidirectionnelle? Pas besoin d'écouter les SelectionChanged de l'événement ou de la création de commandes. Chaque fois que le SelectedItems valeur est modifiée, vous obtiendrez notifié à l'intérieur de l'incubateur de votre bien dans le ViewModel. De l'essayer.
<ComboBox ItemsSource="{Binding Path=PropertyWhichHasList, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" SelectedItem="{Binding PropertyWhichHasSelectedItem}" </ComboBox>. Essayez quelque chose comme ça .
Merci à tous les 3 suggestions! Ils m'ont aidé à trouver une solution.
OriginalL'auteur Alistair Tweed | 2013-10-27
Vous devez vous connecter pour publier un commentaire.
Pourquoi ne pas le faire de la manière la plus simple
Dans votre ViewModel déclarer la liste déroulante des articles et utiliser une propriété "Source" pour revenir à la vue
Alors définir une propriété qui détient l'élément sélectionné
Aussi n'oubliez pas de mettre en œuvre l'interface INotifyPropertyChanged pendant le réglage de l'_source
Vous êtes les bienvenus @AlistairTweed.
OriginalL'auteur Sandesh
Si vous voulez juste pour être averti quand votre article, pourquoi ne pas utiliser des outils qui sont déjà partie de WPF à la place de toutes ces dépendances.
De la première à obtenir la vision sous-jacente à votre collection et l'utilisation de l'événement CurrentChanged.
Dans votre xaml vous venez de lier votre collection et de jeu de
IsSynchronizedWithCurrentItem
de vrai.OriginalL'auteur dowhilefor