@cicatrix
было бы большой ошибкой думать

WPF. Почему не стреляет PreviewMouseDown?

День добрый. Столкнулся со странным явлением в WPF, не могу понять, в чём проблема.
Имеется приложение, выполняющее рисование на контексте DrawingVisual. Затем рисунок просто добавляется на Canvas, к которому прикручен обработчик события PreviewMouseDown. Ожидал, что это событие будет всегда срабатывать, когда пользователь щёлкает по холсту, но не тут-то было.
Я подготовил минимальную демонстрацию проблемы, буду благодарен, если кто-нибудь поможет разобраться, как ловить события мыши в данном случае.
Для воспроизведения:
1. Запустить
2. Нажать Render
3. Щёлкнуть по красному квадрату - событие не сработает. Щелкнуть по зелёной области - событие работает.
Почему PreviewMouseDown не срабатывает?

Имеем следующий XAML:
<Window x:Class="MouseDownTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Click="Button_Click">Render</Button>
        <Canvas Grid.Row="1" x:Name="HostCanvas" PreviewMouseDown="HostCanvas_PreviewMouseDown" 
                Background="Green"
                Width="300" Height="300"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"/>
    </Grid>
</Window>


И следующий код:
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace MouseDownTest
{
    public partial class MainWindow : Window
    {
        public class VisualHost : UIElement
        {
            public Visual Visual { get; set; }
            public VisualHost(Visual childVisual) { Visual = childVisual; }
            protected override int VisualChildrenCount => (Visual is null) ? 0 : 1;
            protected override Visual GetVisualChild(int index) { return Visual; }
        } // class VisualHost
        public MainWindow() => InitializeComponent();
        // Not FIRING inside a red square
        private void HostCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e) => MessageBox.Show("Got a click!");

        private void Render()
        {
            this.HostCanvas.Children.Clear();
            this.HostCanvas.InvalidateVisual();
            DrawingVisual vis = new();
            using (DrawingContext dc = vis.RenderOpen())
            {
                var rect = new Rect(50, 50, 50, 50);
                var redbrush = new SolidColorBrush(Colors.Red);
                var redpen = new Pen(redbrush, 2);
                dc.DrawRectangle(redbrush, redpen, rect);
            }
            var vh = new VisualHost(vis);
            this.HostCanvas.Children.Add(vh);
            System.Diagnostics.Debug.Assert(this.HostCanvas.Children.Count > 0);
        }
        private void Button_Click(object sender, RoutedEventArgs e) => Render();
    }
}


1nDbM.png
  • Вопрос задан
  • 132 просмотра
Решения вопроса 1
@cicatrix Автор вопроса
было бы большой ошибкой думать
А ларчик просто открывался. Просто надо было сделать vh.IsHitTestVisible = false;
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы