Я нашел очень простой и понятный способ сделать это с помощью триггеров Blend SDK Event. Чистый 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 (пробный, начиная с сетки), вы также можете поместить Триггер туда.
К сожалению, события 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>