【问题标题】:Programmatically run WPF event handler以编程方式运行 WPF 事件处理程序
【发布时间】:2015-09-20 08:11:30
【问题描述】:

对于 wpf 数据网格,我有以下两个事件:

1-CellEditEnding

2-PreviewKeyDown

当我在数据网格中的任何单元格中完成编辑时,首先运行 PreviewKeyDown 事件,然后运行 ​​CellEditEnding。但我需要先运行 CellEditEnding,然后再运行 PreviewKeyDown。所以我通过编写以下代码在 CellEditEnding 事件中以编程方式调用 PreviewKeydown 事件。

private void maingrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    TextBox t = e.EditingElement as TextBox;
    DataGridColumn dgc = e.Column;
    if ((string)dgc.Header == "Product Id")
    {
        if (vm_order.PopulateProductRow(maingrid.SelectedIndex, Convert.ToInt32(t.Text)) == false)
        {
            MessageBox.Show("Product does not exists           ", "Message", MessageBoxButton.OK);
        }
    }

    **maingrid.PreviewKeyDown += new maingrid_PreviewKeyDown(maingrid_PreviewKeyDown);**
}

请查看我以编程方式调用 PrevewKeyDownEvent 的最后一行代码,它给出了错误。

我已经看到了 wpf datagrid 的 mouse_up 事件的示例,它工作得非常好。以下是代码供参考:

public EventsSample()
{
    InitializeComponent();
    pnlMainGrid.MouseUp += new MouseButtonEventHandler(pnlMainGrid_MouseUp);
}

private void pnlMainGrid_MouseUp(object sender, MouseButtonEventArgs e)
{
    MessageBox.Show("You clicked me at " + e.GetPosition(this).ToString());
}

那么为什么我不能将它用于 PreviewKeyDown 事件?

【问题讨论】:

  • 您是否查看了 KeyDownEvent 而不是 PreviewKeyDown?预览前缀意味着此类事件必须领先
  • 代码行不仅调用PrevewKeyDownEvent处理程序,还尝试从中创建对象,并再次添加为事件。所以可能你只需要maingrid_PreviewKeyDown(sender, new KeyEventArgs())
  • 我已经编辑了我的问题。请查看工作正常的第二个示例。我想对 wpd 数据网格的 PreviewKeyDown 或 KeyDown 事件完全相同,谢谢,

标签: c# wpf


【解决方案1】:

有几个问题。首先行中有语法错误
maingrid.PreviewKeyDown += new maingrid_PreviewKeyDown(maingrid_PreviewKeyDown);
这是不正确的。 maingrid_PreviewKeyDown 是方法的名称,您不能“新建”方法。这就是您收到编译器错误的原因。订阅事件的正确方法是:
mainGrid.PreviewKeyDown += new KeyEventHandler(mainGrid_PreviewKeyDown);

查看您自己的 MouseUp 事件代码。这种形式和你自己的代码订阅鼠标事件的方式是一致的。但是请注意,这是一种非常古老的语法。由于 C# 2 或 C# 3 我们有一个更简单的形式。你可以写:
mainGrid.PreviewKeyDown += mainGrid_PreviewKeyDown;

pnlMainGrid.MouseUp += pnlMainGrid_MouseUp;

但是你有一个更大的问题。我将使用更正的语法在此处复制您的代码,然后尝试解释更大的问题是什么:

01  private void maingrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
02  {
03      TextBox t = e.EditingElement as TextBox;
04      DataGridColumn dgc = e.Column;
05      if ((string)dgc.Header == "Product Id")
06      {
07          if (vm_order.PopulateProductRow(maingrid.SelectedIndex, Convert.ToInt32(t.Text)) == false)
08          {
09              MessageBox.Show("Product does not exists           ", "Message", MessageBoxButton.OK);
10          }
11      }
12
13      mainGrid.PreviewKeyDown += new KeyEventHandler(mainGrid_PreviewKeyDown);
14  }

在第 13 行:
mainGrid.PreviewKeyDown += new KeyEventHandler(mainGrid_PreviewKeyDown);
您没有调用事件处理程序。您只是订阅该事件。换句话说,您是在告诉系统下次将引发事件 PreviewKeyDown 时,您希望调用方法 mainGrid_PreviewKeyDown。这意味着第一次调用maingrid_CellEditEnding 时,您正在订阅PreviewKeyDown。下次调用maingrid_CellEditEnding 时,您将再次订阅PreviewKeyDown。此时,您有两个与事件PreviewKeyDown 关联的事件处理程序(恰好是相同的方法)。当下次引发PreviewKeyDown 时,mainGrid_PreviewKeyDown 将针对同一事件被调用两次。在 CellEditEnding 被提升 10 次之后,maingrid_CellEditEnding 将被调用 10 次。事件PreviewKeyDown 也将被订阅 10 次。此时,下一次PreviewKeyDown 将被引发,它的事件处理程序——即方法mainGrid_PreviewKeyDown 将为同一事件调用10 次。

要查看实际情况,我建议您以这种方式实现 mainGrid_PreviewKeyDown 作为测试:

void mainGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
    Debug.WriteLine("mainGrid_PreviewKeyDown was called");
}

运行您的应用程序并密切关注 Visual Studio 调试输出。
注意:要显示调试输出窗口,请转到 [menu / DEBUG / Windows / Output]。

要解决此问题,您有多种选择:

选项 1
这仅在您的方法mainGrid_PreviewKeyDown 中不使用参数object senderKeyEventArgs e 中包含的信息时才有效。如果是这种情况,请执行以下操作:

  • 不再订阅PreviewKeyDown 事件。
  • 重写maingrid_CellEditEnding,以便在方法结束时执行通常在mainGrid_PreviewKeyDown 中执行的操作。这样,您将按照您需要的顺序执行操作。

选项 2
如果您确实需要参数object sender 或“KeyEventArgs e”中包含的信息。

  • 订阅CellEditEndingPreviewKeyDown 事件。
  • PreviewKeyDown 的处理程序被调用时,暂时不要做任何事情,只在某些字段中存储您以后需要的来自KeyEventArgs 的信息。
  • CellEditEnding 的处理程序被调用时,请执行任何处理CellEditEnding 的操作。完成后,使用您之前存储的有关 KeyEventArgs 的信息来执行有关 PreviewKeyDown 事件的任何操作。

选项 3
查找具有您喜欢的顺序的其他要订阅的事件。

【讨论】:

  • 我已经编辑了我的问题。请查看工作正常的第二个示例。我想对 wpd 数据网格的 PreviewKeyDown 或 KeyDown 事件完全相同,谢谢,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-12
相关资源
最近更新 更多