Я знайшов дуже простий і чистий спосіб зробити це за допомогою тригерів події Blend SDK. Чистий MVVM, багаторазовий і без коду.
Напевно у вас вже є щось подібне:
<Style x:Key="MyListStyle" TargetType="{x:Type ListViewItem}">
Тепер включіть ControlTemplate для ListViewItem таким чином, якщо ви його ще не використовуєте:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<GridViewRowPresenter Content="{TemplateBinding Content}"
Columns="{TemplateBinding GridView.ColumnCollection}" />
</ControlTemplate>
</Setter.Value>
</Setter>
GridViewRowPresenter буде візуальним коренем усіх елементів "всередині", складаючи елемент рядка списку. Тепер ми можемо вставити тригер там, щоб шукати маршрутизовані події MouseDoubleClick і викликати команду через InvokeCommandAction так:
<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>
Якщо у вас є візуальні елементи "вище" GridRowPresenter (probalby, що починається з сітки), ви також можете поставити туди тригер.
На жаль, події MouseDoubleClick генеруються не з усіх візуальних елементів (наприклад, з елементів керування, але не з FrameworkElements). Вирішення завдання полягає в тому, щоб отримати клас з EventTrigger і шукати MouseButtonEventArgs з ClickCount 2. Це ефективно фільтрує всі не-MouseButtonEvents і всі MoseButtonEvents з 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);
}
}
}
Тепер ми можемо записати це ("h" - це область простору імен помічників):
<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>