How do you handle a ComboBox SelectionChanged in MVVM?

How do you handle a ComboBox SelectionChanged in MVVM?

For those doing pure MVVM, how do you handle a ComboBox SelectionChanged event without reverting to code behind?

I tried e.g. AttachedBehaviors but Event="SelectedChanged" is not supported:

<ComboBox>
    <ComboBoxItem Content="Test1">
        <c:CommandBehaviorCollection.Behaviors>
            <c:BehaviorBinding Event="SelectionChanged" 
                               Command="{Binding SelectedChanged}"
                               CommandParameter="MainBorder123"/>
        </c:CommandBehaviorCollection.Behaviors>
    </ComboBoxItem>
    <ComboBoxItem Content="Test2"/>
    <ComboBoxItem Content="Test3"/>
</ComboBox>

 

回答1

This post is quite old, but since I got the same issue. Here is how I solved it (using framework 4.0) : the idea is to use System.Windows.Interactivity.

In the XAML :

<ComboBox ItemsSource="{Binding Items}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding SelectionChangedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ComboBox>

Then you just need to implement the SelectionChangedCommand in your viewmodel.

这里没写command怎么写,是否有参数

 

 

How to handle the SelectionChanged event of ComboBox with MVVM in wpf?

How to raise / handle the SelectionChanged event of WPF's ComboBox using the MVVM pattern?
Explain in detail please I am new to WPF.

What I want, is to do some operations when the ComboBox item selection changed. How can I achieve it, in an MVVM way?

回答1

MVVM solution:

Bind the ItemsSource and SelectedItem properties of the ComboBox to properties in your ViewModel:

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

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

 <ComboBox SelectionChanged="ComboBox_SelectionChanged" />

And add this in MainWindow.xaml.cs:

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

 

回答2

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>

 

回答3

Just an enhancement of this solution which 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.

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.

So actually you can replace the following XAML

<i:InvokeCommandAction Command="{Binding RegionChangedCmd}" />

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

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 null if you use <i:InvokeCommandAction>
e parameter is NOT null if you use <prism:InvokeCommandAction>

 

posted @ 2022-09-16 16:03  ChuckLu  阅读(191)  评论(0编辑  收藏  举报