WPF ListView и ScrollViewer скрывают MouseLeftButtonDown
Чтобы продемонстрировать проблему, у меня есть этот Xaml:
<DockPanel MouseLeftButtonDown="DockPanel_MouseLeftButtonDown" MouseLeftButtonUp="DockPanel_MouseLeftButtonUp">
<ListView>
<ListViewItem>ListViewItem</ListViewItem>
</ListView>
<TextBlock>TextBlock</TextBlock>
</DockPanel>
и обработчики событий:
private void DockPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("DockPanel_MouseLeftButtonDown");
}
private void DockPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("DockPanel_MouseLeftButtonUp");
}
Когда вы запускаете приложение и нажимаете на слова TextBlock, вы запускаете MouseDown, а затем MouseUp. Все идет нормально. Но когда вы нажимаете на слова ListViewItem, запускается только MouseUp. Та же проблема для ScrollViewer (представление списка включает в себя, так что я предполагаю, что это та же проблема). Кто-нибудь знает, почему и если это можно исправить. Под фиксированным я имею в виду заставить его срабатывать, а не пытаться использовать другое событие или другой механизм все вместе.
2 ответа
Первая проблема: как и предполагалось, проблема в ScrollViewer: http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Controls/ScrollViewer.cs,488ab4a977a015eb
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (Focus())
e.Handled = true;
base.OnMouseLeftButtonDown(e);
}
Как вы можете видеть, он устанавливает MouseButtonEventArgs.Handled в true, что останавливает всплывание события.
Теперь решение - это способ, которым вы добавляете обработчик:
MyListView.AddHandler(
ListView.MouseLeftButtonDownEvent,
new MouseButtonEventHandler(ListView_MouseLeftButtonDown),
true);
Обратите внимание, что последний параметр (true) вызывает обработчик, даже если для EventArgs.Hanlded установлено значение true. Тогда вы можете сбросить его:
private void ListView_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = false;
}
У меня была похожая ситуация, когда ScrollViewer блокировал мое событие MouseLeftButtonDown. У меня был элемент управления контентом, завернутый в ScrollViewer:
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ContentControl x:Name="Details" />
</ScrollViewer>
и это было внутри Popup, который имел поведение перетаскивания. Итак, поскольку мое поведение не получало это событие, оно не работало. Когда я добавил IsHitTestVisible="True" в ScrollViewer, мое поведение начало работать, но, конечно, мой ContentControl не реагировал ни на какие щелчки. Тогда я увидел это:
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (Focus())
e.Handled = true;
base.OnMouseLeftButtonDown(e);
}
и попытался добавить Focusable="False", чтобы исключить ScrollViewer из моего клика - это работает. Мое поведение работает, и элементы управления внутри ContentControl получают все события мыши.
<ScrollViewer VerticalScrollBarVisibility="Auto" Focusable="False">
<ContentControl x:Name="Details" />
</ScrollViewer>
Надеюсь, это кому-нибудь поможет.