Znalazłem bardzo łatwy i czysty sposób na zrobienie tego za pomocą wyzwalaczy zdarzeń Blend SDK. Czysty MVVM, wielokrotnego użytku i bez kodu źródłowego.
Prawdopodobnie masz już coś takiego:
<Style x:Key="MyListStyle" TargetType="{x:Type ListViewItem}">
Teraz dołącz ControlTemplate dla ListViewItem w ten sposób, jeśli jeszcze go nie używasz:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<GridViewRowPresenter Content="{TemplateBinding Content}"
Columns="{TemplateBinding GridView.ColumnCollection}" />
</ControlTemplate>
</Setter.Value>
</Setter>
GridViewRowPresenter będzie wizualnym korzeniem wszystkich elementów „wewnątrz” tworzących element wiersza listy. Teraz możemy wstawić tam wyzwalacz, aby szukać zdarzeń kierowanych przez MouseDoubleClick i wywołać polecenie za pośrednictwem InvokeCommandAction w następujący sposób:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<GridViewRowPresenter Content="{TemplateBinding Content}"
Columns="{TemplateBinding GridView.ColumnCollection}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding DoubleClickCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</GridViewRowPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
Jeśli masz elementy wizualne „nad” GridRowPresenter (prawdopodobnie zaczynając od siatki), możesz również umieścić tam wyzwalacz.
Niestety zdarzenia MouseDoubleClick nie są generowane z każdego elementu wizualnego (pochodzą z Controls, ale nie na przykład z FrameworkElements). Sposób obejścia problemu polega na wyprowadzeniu klasy z EventTrigger i wyszukaniu MouseButtonEventArgs z wartością ClickCount równą 2. To skutecznie odfiltrowuje wszystkie zdarzenia inne niż MouseButtonEvents i wszystkie zdarzenia MoseButtonEvents z wartością ClickCount! = 2.
class DoubleClickEventTrigger : EventTrigger
{
protected override void OnEvent(EventArgs eventArgs)
{
var e = eventArgs as MouseButtonEventArgs;
if (e == null)
{
return;
}
if (e.ClickCount == 2)
{
base.OnEvent(eventArgs);
}
}
}
Teraz możemy napisać to ('h' to przestrzeń nazw powyższej klasy pomocniczej):
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<GridViewRowPresenter Content="{TemplateBinding Content}"
Columns="{TemplateBinding GridView.ColumnCollection}">
<i:Interaction.Triggers>
<h:DoubleClickEventTrigger EventName="MouseDown">
<i:InvokeCommandAction Command="{Binding DoubleClickCommand}" />
</h:DoubleClickEventTrigger>
</i:Interaction.Triggers>
</GridViewRowPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>