Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Binding UI events to commands in ViewModel

Tags:

c#

mvvm

wpf

I’m doing some refactoring of a simple application to follow MVVM and my question is how do I move a SelectionChanged event out of my code behind to the viewModel? I’ve looked at some examples of binding elements to commands but didn’t quite grasp it. Can anyone assist with this. Thanks!

Can anyone provide a solution using the code below? Many thanks!

public partial class MyAppView : Window 
{
    public MyAppView()
    {
        InitializeComponent();

        this.DataContext = new MyAppViewModel ();

        // Insert code required on object creation below this point.
    }

    private void contactsList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        //TODO: Add event handler implementation here.           
        //for each selected contact get the labels and put in collection 

        ObservableCollection<AggregatedLabelModel> contactListLabels = new ObservableCollection<AggregatedLabelModel>();

        foreach (ContactListModel contactList in contactsList.SelectedItems)
        {
            foreach (AggregatedLabelModel aggLabel in contactList.AggLabels)
            {
                contactListLabels.Add(aggLabel);
            }
        }
        //aggregate the contactListLabels by name
        ListCollectionView selectedLabelsView = new ListCollectionView(contactListLabels);

        selectedLabelsView.GroupDescriptions.Add(new PropertyGroupDescription("Name"));
        tagsList.ItemsSource = selectedLabelsView.Groups;
    }
}
like image 299
Ben Avatar asked Feb 04 '11 12:02

Ben


4 Answers

You should use an EventTrigger in combination with InvokeCommandAction from the Windows.Interactivity namespace. Here is an example:

<ListBox ...>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>

You can reference System.Windows.Interactivity by going Add reference > Assemblies > Extensions.

And the full i namespace is: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity".

like image 83
Pavlo Glazkov Avatar answered Nov 17 '22 15:11

Pavlo Glazkov


This question has a similar issue.

WPF MVVM : Commands are easy. How to Connect View and ViewModel with RoutedEvent

The way I deal with this issue is to have a SelectedItem property in the ViewModel, and then bind the SelectedItem of your ListBox or whatever to that property.

like image 37
Cameron MacFarland Avatar answered Nov 17 '22 15:11

Cameron MacFarland


To refactor this you need to shift your thinking. You will no longer be handling a "selection changed" event, but rather storing the selected item in your viewmodel. You would then use two-way data binding so that when the user selects an item, your viewmodel is updated, and when you change the selected item, your view it updated.

like image 10
sourcenouveau Avatar answered Nov 17 '22 17:11

sourcenouveau


Consider Microsoft.Xaml.Behaviors.Wpf, its owner is Microsoft which you can see in that page.

System.Windows.Interactivity.WPF owner is mthamil, anybody can tell me is it reliable ?

Example of Microsoft.Xaml.Behaviors.Wpf:

<UserControl ...
             xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
             ...>

<Button x:Name="button">
    <behaviors:Interaction.Triggers>
        <behaviors:EventTrigger EventName="Click" SourceObject="{Binding ElementName=button}">
            <behaviors:InvokeCommandAction Command="{Binding ClickCommand}" />
        </behaviors:EventTrigger>
    </behaviors:Interaction.Triggers>
</Button>

</UserControl>
like image 8
Joe Huang Avatar answered Nov 17 '22 16:11

Joe Huang