I am facing a problem while binding the double click event on Listbox item. I am using MVVM and Prism. I didn't understand what is wrong here.
View
<ListBox HorizontalAlignment="Center" ItemsSource="{Binding Cities , Source={StaticResource vmC}}" SelectedItem="{Binding SelectedCity , Source={StaticResource vmC}}" Width="100" Height="200">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.ItemSelectedCommand}"/>
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ViewModel
public class CityViewModel : ViewModelBase
{
public DelegateCommand ItemSelectedCommand { get; private set; }
public string SelectedCity { get; set; }
public List<string> Cities { get; private set; }
public CityViewModel()
{
ItemSelectedCommand = new DelegateCommand(OnItemSelected);
Cities = new List<string>() { "Bangalore", "New York", "Sydney", "London", "Washington" };
}
private void OnItemSelected()
{
var city = SelectedCity;
}
}
CodePudding user response:
MouseBinding
is not part of the visual tree. This means, you cannot use Binding.RelativeSource
as there is no tree to traverse.
Instead you must bind to the current DataContext
, which is the item's data model. To accomplish this, you would have tzo introduce a model class e.g. City
that exposes a Name
and ItemSelectedCommand
property.
If moving the command to the item model doesn't make sense in your scenario, you should use a RoutedCommand
and handle it e.g., in the parent Window
. InputBinding
is primarily intended to be used in the view only and therefore encourages the use of RoutedCommand
.
In your case, it seems you are only interested in notifying the CityViewModel
that the selection has changed. In this case simply call OnItemSelected
from the SelectedCity
property set()
:
public class CityViewModel : ViewModelBase
{
private string selectedCity;
public string SelectedCity
{
get => selectedCity;
set
{
selectedCity = value;
OnItemSelected();
}
}
public List<string> Cities { get; private set; }
public CityViewModel()
{
...
}
private void OnItemSelected()
{
var city = SelectedCity;
}
}