如何在 wpf 中使用 MVVM 处理 ComboBox 的 SelectionChanged 事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8666256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to handle the SelectionChanged event of ComboBox with MVVM in wpf?
提问by Tanya
How to raise / handle the SelectionChanged
event of WPF's ComboBox
using the MVVM pattern?
Explain in detail please I am new to WPF.
如何使用 MVVM 模式引发/处理SelectionChanged
WPF 的事件ComboBox
?
请详细解释我是WPF的新手。
What I want, is to do some operations when the ComboBox
item selection changed. How can I achieve it, in an MVVM way?
我想要的是在ComboBox
项目选择改变时做一些操作。我怎样才能以 MVVM 的方式实现它?
回答by snurre
MVVM solution:
MVVM 解决方案:
Bind the ItemsSource
and SelectedItem
properties of the ComboBox
to properties in your ViewModel:
将 的ItemsSource
和SelectedItem
属性绑定ComboBox
到 ViewModel 中的属性:
<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}"/>
In MainViewModel.cs:
在 MainViewModel.cs 中:
public ObservableCollection<string> MyItems { get; set; }
private string _mySelectedItem;
public string MySelectedItem
{
get { return _mySelectedItem; }
set
{
// Some logic here
_mySelectedItem = value;
}
}
Code-behind solution:
代码隐藏解决方案:
If you don't want to use MVVM, you can add use this:
如果你不想使用 MVVM,你可以添加使用这个:
<ComboBox SelectionChanged="ComboBox_SelectionChanged" />
And add this in MainWindow.xaml.cs:
并在 MainWindow.xaml.cs 中添加:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Some logic here
}
回答by Blackey
I'm a big fan of this method.
我是这种方法的忠实粉丝。
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>
回答by Steven Licht
Your ViewModel needs to implement INotifyPropertyChanged.
您的 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"));
}
}
}
}
}
The previously posted XAML is correct:
之前发布的 XAML 是正确的:
<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}"/>
回答by Hakan F?st?k
Just an enhancement of this solutionwhich exists above, In case you are using Prism Library
(if not, then stop reading now, there is nothing for you)
只是上面存在的这个解决方案的增强,如果你正在使用棱镜库
(如果没有,那么现在停止阅读,没有什么适合你)
I really like this solution and I think it is better than any other solution, I just want to make a small enhancement to that solution provided by the Prism Library.
我真的很喜欢这个解决方案,我认为它比任何其他解决方案都要好,我只是想对 Prism 库提供的解决方案做一个小的改进。
that solution is using
该解决方案正在使用
<i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
notice the i:
before the InvokeCommandAction
. It means that the InvokeCommandAction
class exists in the xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
namespace. This is good and fine, but notice that the Prism library has exactly the same class with the same name InvokeCommandAction
. It just exists in another namespace, in the xmlns:prism="http://prismlibrary.com/"
namespace.
注意i:
之前的InvokeCommandAction
。这意味着InvokeCommandAction
该类存在于xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
命名空间中。这很好也很好,但请注意 Prism 库具有完全相同的同名类InvokeCommandAction
。它只是存在于另一个命名空间中,在xmlns:prism="http://prismlibrary.com/"
命名空间中。
So actually you can replace the following XAML
所以实际上你可以替换下面的XAML
<i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
with this XAML
使用这个 XAML
<prism:InvokeCommandAction Command="{Binding RegionChangedCmd}" />
OK, we can do this, what is the benefit?
To notice the benefit, write the following command in the ViewModel
好的,我们可以这样做,有什么好处?
要注意好处,请在 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>
}
e parameter is nullif you use <i:InvokeCommandAction>
e parameter is NOT nullif you use <prism:InvokeCommandAction>
如果使用e 参数为null如果使用<i:InvokeCommandAction>
e 参数为NOT null如果使用<prism:InvokeCommandAction>
回答by sll
As first let's make things clear - you can not change event rather you can subscribe to.
首先让我们把事情说清楚——你不能改变事件而你可以订阅。
Since you've not provided any information regarding where from you want to handle selection changes I will assume most common scenario - handling in the underlying ViewModel. According to MVVM ViewModel should not know anything about View so you can not subscribe directly from ViewModel to the event of a View's control. But you can bind a property of ViewModel to either SelectedItem
or SelectedIndex
so it would trigger whilst selection changes.
由于您没有提供任何有关从何处处理选择更改的信息,我将假设最常见的情况 - 在底层 ViewModel 中处理。根据 MVVM ViewModel 不应该对 View 一无所知,因此您不能直接从 ViewModel 订阅 View 控件的事件。但是您可以将 ViewModel 的属性绑定到任一SelectedItem
或SelectedIndex
这样它会在选择更改时触发。
<ComboBox
SelectedIndex="{Binding SelectedIndexPropertyName}"
... />
There are other solutions doing handling in code behind of a View by accessing a ViewModel via view.DataContext
but I would suggest avoid such practice, this are work around cases.
还有其他解决方案通过访问 ViewModel 通过在视图后面的代码中进行处理,view.DataContext
但我建议避免这种做法,这是解决情况。