Search code examples
windows-phone-7mvvm-lightrelaycommandeventtrigger

Correct way to use a Interaction Trigger on SelectionChanged Event


I have a command wired to the event such that it does fire, but what I get in the CommandParameter is the previously selected item, or maybe it's the selected item before the SelectionChanged completes.

Either way, not sure what to change to get the newly selected item from the event.

<i:Interaction.Triggers>
  <i:EventTrigger EventName="SelectionChanged">
    <cmd:EventToCommand 
    Command="{Binding Main.SelectedRecordCommand, Source={StaticResource Locator}}" 
    CommandParameter="{Binding SelectedItem, ElementName=listBillingRecords}" 
    />
   </i:EventTrigger>
</i:Interaction.Triggers>

Thanks


Solution

  • Is it worth using a trigger? If whatever your XAML element is for the collection (listbox, grid, etc) is bound to a property exposing a collection on your viewmodel, you can leverage both databinding and the built-in MVVM Light messenger to notify you of a property change with both old and new values in a more MVVM-friendly way. This example isn't necessarily WP7-specific, but I think it would work the same.

    For example, this might be the databound collection:

        public const string BillingRecordResultsPropertyName = "BillingRecordResults";
        private ObservableCollection<BillingRecord> _billingRecordResults = null;
        public ObservableCollection<BillingRecord> BillingRecordResults
        {
            get
            {
                return _billingRecordResults;
            }
    
            set
            {
                if (_billingRecordResults == value)
                {
                    return;
                }
    
                var oldValue = _billingRecordResults;
                _billingRecordResults = value;
    
                // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
                RaisePropertyChanged(BillingRecordResultsPropertyName, oldValue, value, true);
            }
        }
    

    I like to expose a property on my ViewModel that is a "selected item" of whatever collection I'm exposing. So, to the ViewModel, I would add this property using the MVVMINPC snippet:

        public const string SelectedBillingRecordPropertyName = "SelectedBillingRecord";
        private BillingRecord _selectedBillingRecord = null;
        public BillingRecord SelectedBillingRecord
        {
            get
            {
                return _selectedBillingRecord;
            }
    
            set
            {
                if (_selectedBillingRecord == value)
                {
                    return;
                }
    
                var oldValue = _selectedBillingRecord;
                _selectedBillingRecord = value;
    
                // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
                RaisePropertyChanged(SelectedBillingRecordPropertyName, oldValue, value, true);
            }
        }
    

    Now, if you bind the SelectedItem of the XAML element to this exposed property, it will populate when selected in the View via databinding.

    But even better, when you leverage the snippet MVVMINPC, you get to choose whether or not to broadcast the results to anyone listening. In this case, we want to know when the SelectedBillingRecord property changes. So, you can have this in the constructor for your ViewModel:

    Messenger.Default.Register<PropertyChangedMessage<BillingRecord>>(this, br => SelectedRecordChanged(br.NewValue));
    

    And elsewhere in your ViewModel, whatever action you want to have happen:

        private void SelectedRecordChanged(BillingRecord br)
        {
            //Take some action here
        }
    

    Hope this helps...