Vishal
Vishal

Reputation: 6368

How to bring cell in edit mode as soon as it gets focus

Suppose I have a DataGrid. Suppose all the columns are TemplateColumns. When any cell gets focus I want it to go in EditMode.

What I have tried so far:

I have created a style for DataGridCell as follows:

<Style TargetType="{x:Type DataGridCell}">
    <EventSetter Event="GotFocus" Handler="DataGridCell_GotFocus" />
</Style>

In the Code-Behind of the Window :

private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
{
    DataGridCell cell = sender as DataGridCell;
    if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
    {
        cell.IsEditing = true;
    }
}

Problems in above try :

I have to single click the cell to bring it in edit mode.

Upvotes: 5

Views: 5291

Answers (2)

pushpraj
pushpraj

Reputation: 13679

Here is a trick to make it editable

BeginEdit() method brings the current cell into edit mode.

sample

    private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
        {
            var parent = VisualTreeHelper.GetParent(cell);
            while (parent != null && parent.GetType() != typeof(DataGrid))
            {
                parent = VisualTreeHelper.GetParent(parent);
            }
            DataGrid dGrid = parent as DataGrid;
            dGrid.BeginEdit();
        }
    }

if you have access to the data grid then finding it may not be necessary

eg

    private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
        {
            dGrid.BeginEdit();
        }
    }

Update: FocusManager trick

if focus is the only issue you can leverage FocusManager by setting FocusManager.FocusedElement. give it a try, it works without any code behind.

sample

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Name}" 
                     FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

note that I have set the FocusedElement to the TextBox by binding to self, this will bring the TextBox to focus once loaded (as it enters in edit mode)

Upvotes: 1

Rohit Vats
Rohit Vats

Reputation: 81253

On focus, cell goes into edit mode but the textBox doesn't have keyboard focus so next tab press will be eaten up by textBox and will get the focus.

As you mentioned you have to press Tab twice to move focus to next cell. What you can do is put focus on TextBox on loaded event:

XAML for dummy element:

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Name}" Loaded="TextBox_Loaded"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

Code behind:

private void TextBox_Loaded(object sender, RoutedEventArgs e)
{
    (sender as TextBox).Focus();
}

Of course you can move the handler to some base style for all your TextBoxes in dataGrid so you don't have to hook the handler for all cells.


In case you don't want to have handler, you can also do that using interactivity triggers like defined here:

<DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <TextBox Text="{Binding Name}">
            <Interactivity:Interaction.Triggers>
                <Interactivity:EventTrigger EventName="Loaded">
                    <local:TakeFocusAction />
                </Interactivity:EventTrigger>
            </Interactivity:Interaction.Triggers>
        </TextBox>
    </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

and behavior trigger action:

public class TakeFocusAction : TriggerAction<UIElement>
{
    protected override void Invoke(object parameter)
    {
        AssociatedObject.Focus();
    }
}

Upvotes: 6

Related Questions