Поведение WPF MenuItem vs Button в новом окне, когда мышь все еще нажата

Я не знал, как сделать «проблему» (другое поведение) более ясной в заголовке, но я объясню здесь.

В нашем приложении WPF мы используем элемент управления DataGrid для вывода списка сущностей. После двойного щелчка по строке мы открываем новое окно, и в этом окне, среди прочего, есть несколько элементов управления MenuItem.

Проблема в том, что когда окно открывается в позиции, где один из пунктов меню находится прямо под указателем мыши, пункт меню фактически щелкается там при двойном щелчке мыши вверх.

Когда вместо этого мы используем кнопку, событие нажатия кнопки не запускается автоматически в той же ситуации.

Сейчас мы думаем об использовании кнопок вместо пунктов меню (или создании пользовательских меню), но, возможно, у кого-то здесь есть объяснение или решение, чтобы изменить это поведение? Лично я не могу придумать случая, когда это было бы вообще выгодно. Заранее спасибо!

Пример кода ниже. Чтобы понять, что я имею в виду, дважды щелкните строку DataGrid, чтобы открыть новое окно, и, удерживая нажатой кнопку мыши, перейдите к элементу меню и отпустите кнопку мыши (в TestWindow.xaml замените MenuItem на элемент управления Button, чтобы увидеть разница в поведении):

MainWindow.xaml

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <Style x:Key="DataGridRowStyle"
           TargetType="{x:Type DataGridRow}">
        <EventSetter Event="MouseDoubleClick" Handler="DataGridRow_MouseDoubleClick" />
    </Style>
</Window.Resources>
<DataGrid RowStyle="{StaticResource DataGridRowStyle}" x:Name="MyDataGrid">
    <DataGrid.Columns>
        <DataGridTextColumn Header="String" Binding="{Binding}" IsReadOnly="True" />
    </DataGrid.Columns>
</DataGrid>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        ObservableCollection<string> myCollection = new ObservableCollection<string>();

        myCollection.Add("test");

        MyDataGrid.ItemsSource = myCollection;

        this.DataContext = this;
    }

    private void DataGridRow_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        TestWindow window = new TestWindow();
        window.Show();
        window.Activate();
    }
}

Тествиндов.xaml

<Window x:Class="WpfApplication2.TestWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="TestWindow" Height="300" Width="300">
<Grid>
    <MenuItem Header="Test" Click="Button_Click" />
</Grid>

TestWindow.xaml.cs

public partial class TestWindow : Window
{
    public TestWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.Close();
    }
}

person Colin B    schedule 26.07.2010    source источник


Ответы (1)


Вы можете попробовать изменить обработчик DataGridRow_MouseDoubleClick следующим образом:

private void DataGridRow_MouseDoubleClick( object sender, MouseButtonEventArgs e )
{
    this.Dispatcher.BeginInvoke(
        ( Action )delegate
        {
            TestWindow window = new TestWindow();
            window.Show();
            window.Activate();
        },
        System.Windows.Threading.DispatcherPriority.Background,
        null
        );
}

Это может решить проблему, позволив незавершенным событиям «установиться» перед созданием нового окна.

person Adel Hazzah    schedule 27.07.2010
comment
Спасибо за ответ, но это не работает. Не самое лучшее решение, если бы оно работало, но опять же, кажется, что хорошего решения может и не быть. ;) - person Colin B; 28.07.2010