views:

1254

answers:

1
     <data:DataGridTemplateColumn Header="Name">
        <data:DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}">
            </DataTemplate>
        </data:DataGridTemplateColumn.CellTemplate> 
        <data:DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Name}">
            </DataTemplate>
        </data:DataGridTemplateColumn.CellEditingTemplate> 
    </data:DataGridTemplateColumn>

It's clear example of Template column, right? What could be wrong with that? So, here is the thing - when a user navigates through DataGrid with hitting TAB-key, it needs to hit the TAB twice(!) to be able to edit text in TextBox. How could I make it editable as soon as the user gets the column focus, I mean even if he just starts typing?

Ok. I found a way - into Grid.KeyUp() I put the code below:

 if (Grid.CurrentColumn.Header.ToString() == "UserName")
        {
            if (e.Key != Key.Escape) 
            {
                Grid.BeginEdit();

                // Simply send another TAB press
                if (Keyboard.FocusedElement is Microsoft.Windows.Controls.DataGridCell)
                {
                    var keyEvt = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Tab) { RoutedEvent = Keyboard.KeyDownEvent };
                    InputManager.Current.ProcessInput(keyEvt);
                }
            }
        }
+1  A: 

your issue stems from the fact that each cell puts its editor in a content control which first receives focus, then you have to tab once again to the editor. If you have a look at the code for DataGridTemplateColumn in the GenerateEditingElement method it calls a method LoadTemplateContent which does this:

private FrameworkElement LoadTemplateContent(bool isEditing, object dataItem, DataGridCell cell)
{
    DataTemplate template = ChooseCellTemplate(isEditing);
    DataTemplateSelector templateSelector = ChooseCellTemplateSelector(isEditing);
    if (template != null || templateSelector != null)
    {
        ContentPresenter contentPresenter = new ContentPresenter();
        BindingOperations.SetBinding(contentPresenter, ContentPresenter.ContentProperty, new Binding());
        contentPresenter.ContentTemplate = template;
        contentPresenter.ContentTemplateSelector = templateSelector;
        return contentPresenter;
    }

    return null;
}

see how it creates a new content presenter to put the template in. Other people have dealt with this problem in a variety of ways, I derive my own column type to deal with this stuff. (so i dont create an extra element or set the content presenter to not receive focus) In this example they are using focus manager to deal with the same issue (i havent tested this code)

<tk:DataGridTemplateColumn.CellEditingTemplate>
   <DataTemplate>
      <Grid FocusManager.FocusedElement="{Binding ElementName=txt1}">
         <TextBox Name="txt1" Text="{Binding XPath=@ISBN}" 
                  BorderThickness="0" GotFocus="TextBox_GotFocus"/>
      </Grid>
   </DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>

If you have a user control as your editor then you can use the pattern with the focus manager or use an event handler for the OnLoaded event.

Aran Mulholland