Search code examples
c#wpfmvvmcombobox

How to trigger the comboBox SelectionChanged Event from a behavior attached to it


I have some ComboBox controls, each with some values. Each selected value triggers one of my events. When item selected from ComboBoxA, my event is triggerd with the value of the selected item. When one of my combo boxes is just opened and closed, no value changed in it, the event is not triggerd (this is the default behaviour of a combobox). But this is not what i need.

What i did, is to create a behavior that will associate with the DropDownClosed event, but i don't know how to trigger the SelectionChanged event.

Edit:

This question can be generalized: How to 'manually' trigger an event of a UI control? or - Is there a way to invoke the methods assosiated with an event?

Edit 2:

I'll try to explain the problem more clearly. I have this code, which takes a list of items, and present them as categories (Radio button) and items under category (ComboBox inside RadioButton). When selecting an item - the selection changed event is triggerd. OK! when selecting another radio button - an event is triggered. OK!!

Special case that not work (as default for ComboBox behavior): when opening one of the combo that is not selected and than closing it without changing its selection - no event is triggered. BUT - this combo is under a not selected category that i want to be selected now, sincr the user thouched it. My idea was to use behavior (is in xaml code, but so far is not working...)

The code (more or less...):

<ListBox ItemsSource="{Binding Categories}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <RadioButton Content="{Binding CategotyName}" GroupName="TestCategory" IsChecked="{Binding IsSelected}"
                                 cal:Message.Attach="SelectionChanged($dataContext)]"/>
                    <ComboBox cal:Message.Attach="SelectionChanged($dataContext)]" 
                              ItemsSource="{Binding TestsNamesUnderCategory}" SelectedIndex="{Binding SelectedTestInx, Mode=TwoWay}">
                        <i:Interaction.Behaviors>
                            <local:ComboBoxReSelectionBehavior />
                        </i:Interaction.Behaviors>
                    </ComboBox>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

the line cal:Message.Attach="SelectionChanged($dataContext)]" is using Caliburn framework, it just send the trigger to my method.

Hope this is more clear now. Thanks!


Solution

  • Why are you not just binding the selection to your viewmodels properties, and then do whatever logic that is required there?

    Xaml:

    <...
       <ComboBox ItemsSource={Binding YourSource} SelectedItem={Binding YourSelectedItem}/>
    .../>
    

    ViewModel:

    private string yourItem; // assuming we are just dealing with strings...
    public String YourItem {
       get { return yourItem; }
       set {
              if( String.Equals(yourItem, value, StringComparison.OrdinalIgnoreCase) )
                 return;
    
              OnYourItemChanged(); // Do your logics here
              RaisePropertyChanged("YourItem");
            }
       }
    
       private void OnYourItemChanged()
       {
           // .. do stuff here 
       }
    

    If you absolutely need to use events use event-to-command instead...

    Assuming you are using System.Windows.Interactivity & Galasoft MVVM light

    References:

     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"      
     xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
    

    Xaml:

    <...
       <ComboBox ItemsSource={Binding YourSource} SelectedItem={Binding YourSelectedItem}>
           <i:Interaction.Triggers>
               <i:EventTrigger EventName="SelectionChanged">
                   <cmd:EventToCommand Command="{Binding SomeCommand}" PassEventArgsToCommand="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
       </ComboBox>
    .../>
    

    This will hook your event up to a command, which will be executed on the viewmodel with parameters as requested.

    ViewModel:

     public class YourViewModel : ViewModelBase 
     {
          public ICommand SomeCommand { get; set; }
    
          public YourViewModel(......)
          {
              SomeCommand = new RelayCommand<SelectionChangedEventArgs>(YourCommandMethod);
          }
    
          private void YourCommandMethod(SelectionChangedEventArgs e)
          {
              // Do your magic here.... 
          }
     }
    

    Note I wrote this without any access to vs on this computer... There are plenty of examples on how to do this. Hope it helps.