Как обработать событие SelectionChanged ComboBox с MVVM в wpf? - PullRequest
31 голосов
/ 29 декабря 2011

Как вызвать / обработать событие SelectionChanged для WPF ComboBox с использованием шаблона MVVM?
Подробно объясните, пожалуйста, я новичок в WPF.

Что я хочу, это сделать несколькооперации, когда выбор элемента ComboBox изменился.Как мне достичь этого, используя MVVM?

Ответы [ 5 ]

44 голосов
/ 29 декабря 2011

Решение MVVM :

Свяжите свойства ItemsSource и SelectedItem ComboBox со свойствами в вашей модели представления:

<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
}
16 голосов
/ 14 сентября 2017

Я большой поклонник этого метода.

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>
6 голосов
/ 29 декабря 2011

Ваша 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}"/> 
1 голос
/ 16 декабря 2018

Просто расширение этого решения , которое существует выше, на случай, если вы используете Prism Library
(если нет, то прекратите чтение сейчас, есть ничего для вас)

Мне действительно нравится это решение, и я думаю, что оно лучше, чем любое другое решение, я просто хочу сделать небольшое усовершенствование этого решения, предоставляемого Prism Library.

это решение использует

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

обратите внимание на i: перед InvokeCommandAction. Это означает, что класс 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}" />

Хорошо, мы можем это сделать, в чем выгода?
Чтобы заметить преимущество, напишите следующую команду в 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>
Параметр НЕ равен нулю , если вы используете <prism:InvokeCommandAction>

1 голос
/ 29 декабря 2011

Для начала давайте проясним ситуацию: вы не можете изменить событие, а можете подписаться на него.

Поскольку вы не предоставили никакой информации относительно того, откуда вы хотите обрабатывать изменения выбора, я приму наиболее распространенный сценарий - обработку в базовом ViewModel. Согласно MVVM ViewModel не должен ничего знать о View, поэтому вы не можете подписаться непосредственно из ViewModel на событие элемента управления View. Но вы можете привязать свойство ViewModel либо к SelectedItem, либо к SelectedIndex, чтобы оно срабатывало при изменении выбора.

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

Существуют и другие решения, выполняющие обработку кода за View путем доступа к ViewModel через view.DataContext, но я бы рекомендовал избегать такой практики, это обходной путь.

...