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

Tan*_*nya 33 wpf mvvm wpf-controls

如何使用MVVM模式引发/处理SelectionChangedWPF的事件ComboBox
请详细解释,我是WPF的新手.

我想要的是在ComboBox项目选择改变时做一些操作.我怎样才能以MVVM的方式实现它?

snu*_*rre 44

MVVM解决方案:

在ViewModel中绑定to属性的ItemsSourceSelectedItem属性ComboBox:

<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}"/>
Run Code Online (Sandbox Code Playgroud)

在MainViewModel.cs中:

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

private string _mySelectedItem;
public string MySelectedItem
{
  get { return _mySelectedItem; }
  set
  {
    // Some logic here
    _mySelectedItem = value;
  }
}
Run Code Online (Sandbox Code Playgroud)

代码隐藏解决方案:

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

 <ComboBox SelectionChanged="ComboBox_SelectionChanged" />
Run Code Online (Sandbox Code Playgroud)

并在MainWindow.xaml.cs中添加:

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Some logic here
}
Run Code Online (Sandbox Code Playgroud)

  • 我试过这个,但它没有触发选择改变了事件. (2认同)

Bla*_*key 21

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

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>
Run Code Online (Sandbox Code Playgroud)

  • 这导致了我的错误,直到我将EventTrigger包装在此<i:Interaction.Triggers> </ i:Interaction.Triggers>中 (3认同)
  • 对于我来说,这是使用MVVM最简单的方法。谢谢! (2认同)
  • 同意,这是处理本身不支持 Command 的 UI 事件(例如按钮单击)的首选方法。如果有人仍然感兴趣的话,有一篇很好的 MS 文章.. https://social.technet.microsoft.com/wiki/contents/articles/18199.event-handling-in-an-mvvm-wpf-application.aspx (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"));
                }
            }
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

之前发布的XAML是正确的:

<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}"/> 
Run Code Online (Sandbox Code Playgroud)

  • 虽然这是一个很好的做法,但无助于解决问题。@Tanya 希望当用户更改 UI 中的选择时,她在视图模型中的代码能够收到通知,以便相应地执行一些操作。通知属性更改用于执行相反的操作。 (2认同)

Hak*_*tık 6

只是上面存在的这个解决方案的增强,如果您正在使用Prism 库
(如果没有,那么现在停止阅读,没有什么适合您)

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

该解决方案正在使用

<i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
Run Code Online (Sandbox Code Playgroud)

注意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}" />
Run Code Online (Sandbox Code Playgroud)

使用这个 XAML

<prism:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
Run Code Online (Sandbox Code Playgroud)

OK,我们可以这样做,有什么好处呢?
要注意到好处,请在 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>
}
Run Code Online (Sandbox Code Playgroud)

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