如何在wpf中使用MVVM处理ComboBox的SelectionChanged事件?

时间:2011-12-29 09:53:43

标签: wpf mvvm wpf-controls

如何使用MVVM模式引发/处理WPF SelectionChanged的{​​{1}}事件?
请详细解释,我是WPF的新手。

我想要的是在ComboBox项目选择发生变化时进行一些操作。我怎样才能以MVVM的方式实现它?

5 个答案:

答案 0 :(得分:44)

MVVM解决方案

ItemsSource的{​​{1}}和SelectedItem属性绑定到ViewModel中的属性:

ComboBox

在MainViewModel.cs中:

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

代码隐藏解决方案

如果您不想使用MVVM,可以添加使用:

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

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

并在MainWindow.xaml.cs中添加:

 <ComboBox SelectionChanged="ComboBox_SelectionChanged" />

答案 1 :(得分:14)

我是这种方法的忠实粉丝。

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>

答案 2 :(得分:6)

您的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}"/> 

答案 3 :(得分:1)

首先让我们说清楚 - 你不能改变事件而不是订阅。

由于您没有提供有关您希望处理选择更改的位置的任何信息,因此我将假设最常见的场景 - 在底层ViewModel中进行处理。根据MVVM,ViewModel不应该对View有任何了解,因此您无法直接从ViewModel订阅View控件的事件。但是您可以将ViewModel的属性绑定到SelectedItemSelectedIndex,以便在选择更改时触发。

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

还有其他解决方案通过view.DataContext访问ViewModel来处理View后面的代码,但我建议避免这种做法,这可以解决这些问题。

答案 4 :(得分:0)

只是上面solution的增强,如果您正在使用 Prism Library
(如果没有,请立即停止阅读,没有任何内容为您)

我真的很喜欢这个解决方案,并且我认为它比任何其他解决方案都要好,我只想对Prism库提供的那个解决方案做些小的改进。

该解决方案正在使用

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

e参数为
如果您使用<prism:InvokeCommandAction>

,则参数为不为空