Reputation: 45991
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?
Upvotes: 1
Views: 7817
Reputation: 2363
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.
Upvotes: 0
Reputation: 37800
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"/>
Upvotes: 9