1

I have a community toolkit datagrid bound to an observable collection. I also have an "add" button bound to a command that adds a new element to the collection and thus adds a new row to the datagrid. Now I want to automatically start editing the first cell of the new row when the button is clicked. I tried adding this to the end of my command:

MyDataGrid.Focus(FocusState.Programmatic);
MyDataGrid.SelectedIndex = MyCollection.Count;
MyDataGrid.CurrentColumn = MyDataGrid.Columns[0];
MyDataGrid.BeginEdit();

Though this only works when the focus was already on the datagrid before the button is clicked. Does anyone have any idea how to solve this ?

Thanks in advance

Marcel Barc
  • 137
  • 1
  • 9
  • If you check the [WindowsCommunityToolkit](https://github.com/windows-toolkit/WindowsCommunityToolkit) source code, you will know that it's by design. You could submit your 'Feature Request' on [Github](https://github.com/windows-toolkit/WindowsCommunityToolkit/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22). – Xie Steven Jun 17 '19 at 08:02
  • @XavierXie this is supported, just not intuitive. – Michael Hawker - MSFT Aug 22 '19 at 19:03

1 Answers1

0

I did this in XAML Studio for the known namespaces in settings. It's an ObservableCollection bound to the ItemsSource of the DataGrid.

In addition to having a button for the Add action and putting code in its callback, you need to add an event handler on the DataGrid for the PreparingCellForEdit event.

So in your add method, you can create a new element in your collection and start editing the new item like so:

        private void AddNamespaceButton_Click(object sender, RoutedEventArgs e)
        {
            // Add new Row and begin editing
            KnownNamespaces.Insert(0, new XmlnsNamespace(string.Empty, string.Empty));

            NamespaceDataGrid.SelectedIndex = 0;

            NamespaceDataGrid.ScrollIntoView(NamespaceDataGrid.SelectedItem, null);

            NamespaceDataGrid.Focus(FocusState.Keyboard);

            NamespaceDataGrid.BeginEdit();
        }

The next piece is the key for the DataGridTextColumn type to ensure the focus of the cell gets transferred to the focus of the TextBox inside when editing:


        private void NamespaceDataGrid_PreparingCellForEdit(object sender, Microsoft.Toolkit.Uwp.UI.Controls.DataGridPreparingCellForEditEventArgs e)
        {
            if (e.EditingElement is TextBox t)
            {
                t.Focus(FocusState.Keyboard);
            }
        }

It's also important to note that the class that your ObservableCollection consists of should implement the IEditableObject interface to work properly with the DataGrid.


Here's my XAML for completeness:

<StackPanel Margin="{StaticResource SettingsSubheaderMargin}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock x:Uid="SettingsPanel_KnownNamespaces"
                                       Margin="0,8,0,12"
                                       Style="{StaticResource BodyTextStyle}" />
                            <Button x:Uid="SettingsPanel_KnownNamespaces_Button_Add" Click="AddNamespaceButton_Click" Style="{StaticResource VSCodeAppBarHeaderButtonStyle}">
                                <SymbolIcon Symbol="Add" />
                            </Button>
                        </StackPanel>
                        <controls:DataGrid x:Name="NamespaceDataGrid"
                                           MaxHeight="450"
                                           AutoGenerateColumns="False"
                                           Background="{ThemeResource Brush-Blue-Dark-1}"
                                           CanUserReorderColumns="False"
                                           CanUserSortColumns="True"
                                           IsReadOnly="False"
                                           ItemsSource="{x:Bind KnownNamespaces, Mode=OneWay}"
                                           PreparingCellForEdit="NamespaceDataGrid_PreparingCellForEdit"
                                           RowEditEnded="DataGrid_RowEditEnded">
                            <controls:DataGrid.Columns>
                                <controls:DataGridTextColumn Width="SizeToCells"
                                                             Binding="{Binding Name}"
                                                             FontSize="20"
                                                             Header="Shortcut" />
                                <controls:DataGridTextColumn Width="SizeToCells"
                                                             Binding="{Binding Path}"
                                                             FontSize="20"
                                                             Header="Namespace" />
                                <controls:DataGridTemplateColumn>
                                    <controls:DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <Button x:Uid="SettingsPanel_KnownNamespaces_Button_Remove"
                                                    Click="RemoveNamespaceButton_Click"
                                                    CommandParameter="{Binding}"
                                                    Style="{StaticResource VSCodeAppBarHeaderButtonStyle}">
                                                <SymbolIcon Symbol="Delete" />
                                            </Button>
                                        </DataTemplate>
                                    </controls:DataGridTemplateColumn.CellTemplate>
                                </controls:DataGridTemplateColumn>
                            </controls:DataGrid.Columns>
                        </controls:DataGrid>
                    </StackPanel>

I use the RowEditEnding event to save my data model back to disk.

Michael Hawker - MSFT
  • 1,572
  • 12
  • 18