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

问题描述 投票:0回答:6

如何使用 MVVM 模式引发/处理 WPF 的

SelectionChanged
ComboBox
事件?
请详细解释一下我是 WPF 新手。

我想要的是当

ComboBox
项目选择改变时做一些操作。我怎样才能以 MVVM 方式实现它?

wpf mvvm wpf-controls
6个回答
66
投票

MVVM解决方案:

ItemsSource
SelectedItem
ComboBox
属性绑定到 ViewModel 中的属性:

<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,你可以添加use this:

 <ComboBox SelectionChanged="ComboBox_SelectionChanged" />

并将其添加到 MainWindow.xaml.cs 中:

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Some logic here
}

43
投票

我非常喜欢这种方法。

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

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

6
投票

只是上面存在的解决方案的增强,如果您正在使用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> ,则参数为

null
如果您使用
<prism:InvokeCommandAction>,则 e 参数为
NOT null


2
投票
首先让我们澄清一下 - 您无法更改事件,但可以订阅。

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

SelectedItem

SelectedIndex
,这样它就会在选择更改时触发。

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

还有其他解决方案通过

view.DataContext

 访问 ViewModel 来在视图后面的代码中进行处理,但我建议避免这种做法,这是解决问题的情况。


0
投票
较新版本的 WPF 有一些重大更改

从 .NET Framework 4.6.2 和 .NET Core 开始,上述解决方案不起作用,它们适用于旧版本的 WPF。
这是新方法

  1. 安装

    Microsoft.Xaml.Behaviors.Wpf

  2. 使用命名空间

    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

    
    

  3. 那么comobox应该是

<ComboBox ItemsSource="{Binding Items}"> <i:Interaction.Triggers> <i:EventTrigger EventName="SelectionChanged"> <i:InvokeCommandAction Command="{Binding SelectionChangedCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> </ComboBox>
注意:代码根本没有任何变化,唯一需要的是Nuget包和更新命名空间

© www.soinside.com 2019 - 2024. All rights reserved.