从MainWindow的PreviewKeyDown将WPF键盘事件路由到子DataGrid

时间:2013-12-02 11:49:43

标签: c# wpf datagrid childcontrol event-routing

我有一个窗口,里面有几个单行文本框和一个DataGrid(Windows8上的.Net 4.5)。

我想将导航事件(向上/向下/ PgUp / PgDn等)路由到网格,无论哪个控件都有焦点。

我尝试在主窗口中覆盖PreviewKeyDown,如下所示:

private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
    switch (e.Key)
    {
        case Key.Up:
        case Key.Down:
            myDataGrid.RaiseEvent(e);
            break;
    }
}

问题是我收到了StackOverflowException,因为事件会反映回Window_PreviewKeyDown

我尝试了以下[丑陋]解决方法:

bool bEventRaised = false;
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if ( bEventRaised )
    {
        bEventRaised = false;
        return;
    }

    switch (e.Key)
    {
        case Key.Up:
        case Key.Down:
            bEventRaised = true;
            myDataGrid.RaiseEvent(e);
            break;
    }
}

我希望将if ( bEventRaised )替换为if ( sender == myDataGrid ),但唉,发件人始终是主窗口。

尽管如此,这让我更进一步。我现在能够看到键盘事件到达myDataGrid.PreviewKeyDown,但仍然 - 事件不会在myDataGrid中被触发。

我很乐意帮助理解我做错了什么,或者是否有不同的方法将事件路由到子DataGrid。

感谢。

1 个答案:

答案 0 :(得分:0)

Sry关于早期的ans,但使用AttachedEvent可以应用相同类型的逻辑 像:

enter image description here

在TextBox上提升TextChanged事件:

<TextBox Name="TxtBox1"  TextChanged="TxtBox1_TextChanged" />

在Grid上监听TextChanged(这是AttachedEvent的强大功能,Grid没有TextChanged的自然概念):

<Grid TextBoxBase.TextChanged="Grid_TextChanged" >

创建AttachedEvent:

   public static readonly System.Windows.RoutedEvent MyTextChanged = EventManager.RegisterRoutedEvent(
        "MyTextChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TextBox));

代码背后:

private void TxtBox1_TextChanged(object sender, TextChangedEventArgs e)
{
    RaiseEvent(new RoutedEventArgs(MyTextChanged, sender));
}

// For demo only: simulate selecting the grid row
// You will have to roll your own logic here
// ***NEVER code like this, very bad form***
private void Grid_TextChanged(object sender, TextChangedEventArgs e)
{
    var textBox = e.Source as TextBox;
    if (textBox == null) return;
    var txt = textBox.Text;
    switch (txt)
    {
        case "a":
            _myGrid._dataGrid.SelectedIndex = 0;
            break;
        case "g":
            _myGrid._dataGrid.SelectedIndex = 1;
            break;
        case "o":
            _myGrid._dataGrid.SelectedIndex = 2;
            break;
        case "p":
            _myGrid._dataGrid.SelectedIndex = 3;
            break;
    }
}