AVIDeveloper
AVIDeveloper

Reputation: 3516

Route WPF keyboard events to child DataGrid from MainWindow's PreviewKeyDown

I have a window with several single-line Textboxes and one DataGrid (.Net 4.5 on Windows8).

I'd like to route navigation events (Up/Down/PgUp/PgDn, etc) to the grid, regardless of which control has the focus.

I tried overriding PreviewKeyDown in the main window like this:

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

The problem is that I'm getting a StackOverflowException because the events keep reflecting back to Window_PreviewKeyDown.

I tried the following [ugly] workaround:

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;
    }
}

I would have preferred to replace if ( bEventRaised ) with if ( sender == myDataGrid ), but alas, the sender is always the main window.

Nonetheless, this got me a bit further. I am now able to see the keyboard event reaching myDataGrid.PreviewKeyDown, but still - the event does not get fired inside myDataGrid.

I'd love to get some help understanding what I'm doing wrong, or if there's a different way to route the events to the child DataGrid.

Thanks.

Upvotes: 1

Views: 2140

Answers (1)

narendra
narendra

Reputation: 163

Sry about the earlier ans, but the same type of logic could apply using an AttachedEvent Like:

enter image description here

Raise the TextChanged event on the TextBox:

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

Listen for the TextChanged at the Grid (this is the power of AttachedEvent, Grid has no natural notion of TextChanged):

<Grid TextBoxBase.TextChanged="Grid_TextChanged" >

Create the AttachedEvent:

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

Code behind:

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;
    }
}

Upvotes: 0

Related Questions