如何使用MVVM模式引发/处理WPF SelectionChanged
的{{1}}事件?
请详细解释,我是WPF的新手。
我想要的是在ComboBox
项目选择发生变化时进行一些操作。我怎样才能以MVVM的方式实现它?
答案 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的属性绑定到SelectedItem
或SelectedIndex
,以便在选择更改时触发。
<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>