简体   繁体   中英

ListBox SelectionChanged event with MVVM and CommandParameter

I'm developing a MVVM app with WPF, C# and .NET Framework 4.6.1.

I'm trying to implement ListBox SelectionChanged event using MVVM. To do it I have done this:

Install nuget package: PM> Install-Package System.Windows.Interactivity.WPF .
Add xmlns:interactivity="http://schemas.microsoft.com/expression/2010/interactivity" on xaml.
Add this code to my ListBox in xaml:

<ListBox x:Name="listBoxTrzType" Grid.Column="1" Margin="10,0,25,0" VerticalAlignment="Center" Height="25" ItemsSource="{Binding TrzTypes}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <interactivity:Interaction.Triggers>
        <interactivity:EventTrigger EventName="SelectionChanged">
            <interactivity:InvokeCommandAction Command="{Binding ListBoxTrzTypeSelectionChanged}"
                                                CommandParameter="{Binding ElementName=listBoxTrzType, Path=SelectedItem}">
            </interactivity:InvokeCommandAction>
        </interactivity:EventTrigger>
    </interactivity:Interaction.Triggers>
</ListBox>

On ViewModel I have:

public ICommand ListBoxTrzTypeSelectionChanged
{
    get { return new DelegateCommand(TrzTypeSelectionChanged); }
}

private void TrzTypeSelectionChanged()
{
    throw new NotImplementedException();
}

And DelegateCommand class:

public class DelegateCommand : ICommand
{
    private readonly Action _action;

    public DelegateCommand(Action action)
    {
        _action = action;
    }

    public void Execute(object parameter)
    {
        _action();
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

#pragma warning disable 67
    public event EventHandler CanExecuteChanged { add { } remove { } }
#pragma warning restore 67
}

But my problem is that I don't know how to pass CommandParameter="{Binding ElementName=listBoxTrzType, Path=SelectedItem}" to private void TrzTypeSelectionChanged() .

I've been searching a lot on Internet and I haven't found any example (only examples with CanExecute ).

How do I have to modify my ViewModel class to access SelectedItem parameter?

Actually, to use interaction behaviors for such task is overkill.
You even don't need a command here. It's enough to add SelectedItem property into view model and listen for property changes:

public class SomeVm : INotifyPropertyChanged
{
    // INPC implementation is omitted

    public IEnumerable<SomeType> Items { get; }
    public SomeType SelectedItem
    {
        get { return selectedItem; }
        set
        {
            if (selectedItem != value)
            {
                selectedItem = value;
                OnPropertyChanged();
                // do what you want, when property changes
            }
        }
    }
}

XAML:

<ListBox ItemsSource="{Binding Items}"
         SelectedItem="{Binding SelectedItem}"
         DisplayMemberPath="Name"/>

In your DelegateCommand
change private readonly Action _action; to private readonly Action<object> _action; then in your execute method

public void Execute(object parameter)
{
    _action.Invoke(parameter);
}  

Now your ViewModel function needs to look like this:

private void TrzTypeSelectionChanged(object parameter)
{
    throw new NotImplementedException();
}  

And you are good to go.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM