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.

WPF MVVM: zone de liste déroulante valeur après SelectionChanged

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));
        }
    }
}
Si je comprends ce que vous essayez de faire, je pense que cela va aider stackoverflow.com/questions/4765362/mvvm-combobox-binding
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