How do you handle a ComboBox SelectionChanged in MVVM?
Asked Answered
W

4

39

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>
Wench answered 4/6, 2009 at 13:15 Comment(0)
H
3

You would use a data trigger to trigger an event on a different UI element such as "enable / disable, or visible /invisible"

If you want the selected element to show the object data in other UI elements then you would use data binding and set the datacontext of the UI data display elements to be bound to the currently selected item in the combo box.

Hueston answered 4/6, 2009 at 13:40 Comment(3)
ok, I could do that if all I want to do is change the XAML, but what if I want to e.g. use a comboxbox to execute code that does something that XAML cannot do, e.g. load a new resource file and attach it to the current window? or e.g. change some data in the database, etc.Wench
Then you could use a binding your View Model to the combo box SelectionChanged. I'm not sure where you would look for an example but Karl Shifflet and Josh Smith are the two main blogs I go to for MVVM help the links to their blogs are below. karlshifflett.wordpress.com/2009/06/03/… joshsmithonwpf.wordpress.com/2009/05/20/… Sorry I can't help more on the specifics, i'm fairly new to WPF and MVVM myself.Hueston
oops forgot to mention Karl Shifflet has been doing a lot of WPF Line OF Business events, look on his blog for them, they contain some excellent powerpoint examples and code samples also.Hueston
D
85

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.

Deteriorate answered 28/4, 2011 at 21:20 Comment(6)
Also there is CallMethodAction if you don't need a Command though it does require adding ref to Microsoft.Expression.Interactions.dllTessitura
and how would you bind the SelectedItem or SelectedValue of the ComboBox here without giving it a name?Koetke
@Koetke or anybody else looking to pass the selected item as a parameter: use binding, see here. In my case, I named the ComboBox, e.g., "MyCombo", and then the binding was a simple {Binding ElementName=MyCombo, Path=SelectedItem}.Snapp
After adding a reference to System.Windows.Interactivity you need to add this namespace to the XAML header: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity".Ritualist
for .net core, you will need this nuget: https://github.com/Microsoft/XamlBehaviorsWpf. Add the following into your window layout xml to the <Window/> -> xmlns:i="http://schemas.microsoft.com/xaml/behaviors" More on this: hereEnshrine
This works for .NET Framework, but it is outdated for .NET. See this answer stackoverflow.com/a/77564589 for a solution compatible with .NETGuttery
O
26

I'm not sure if what you're after is possible, but the way I do it is to simply bind the SelectedItem to a property on view model. Then within the property setter, I call any custom code that I want to happen i.e. setting other properties based on rule. If I need the selected item to be bound to an object aswell (for other bound controls to update) I set this in the setter too and send out a notification.

Opine answered 9/9, 2009 at 15:42 Comment(2)
I think this way makes the most sense, and it's working well for me so far. Thanks for posting this.Fluidize
I find this to be an incredibly painful way to do it. For simple applications, doing this instead of a command is easy. But it quickly becomes unwieldy. Properties should hold data, not perform actions. It breaks async, and makes it more difficult to debug as Visual Studio will step over property setters/ getters by default.Leprose
H
3

You would use a data trigger to trigger an event on a different UI element such as "enable / disable, or visible /invisible"

If you want the selected element to show the object data in other UI elements then you would use data binding and set the datacontext of the UI data display elements to be bound to the currently selected item in the combo box.

Hueston answered 4/6, 2009 at 13:40 Comment(3)
ok, I could do that if all I want to do is change the XAML, but what if I want to e.g. use a comboxbox to execute code that does something that XAML cannot do, e.g. load a new resource file and attach it to the current window? or e.g. change some data in the database, etc.Wench
Then you could use a binding your View Model to the combo box SelectionChanged. I'm not sure where you would look for an example but Karl Shifflet and Josh Smith are the two main blogs I go to for MVVM help the links to their blogs are below. karlshifflett.wordpress.com/2009/06/03/… joshsmithonwpf.wordpress.com/2009/05/20/… Sorry I can't help more on the specifics, i'm fairly new to WPF and MVVM myself.Hueston
oops forgot to mention Karl Shifflet has been doing a lot of WPF Line OF Business events, look on his blog for them, they contain some excellent powerpoint examples and code samples also.Hueston
M
3

For .NET CORE and above


  1. Install Microsoft.Xaml.Behaviors.Wpf package

  2. Use the namespace xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

  3. Then the comobox should be

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

notice: there are no changes to the code at all, the only needed thing is the Nuget package and updating the namespace

Mcnalley answered 28/11, 2023 at 14:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.