Automatic editing of WPF datagrid content when datagrid-cell gets focus

后端 未结 5 716
悲哀的现实
悲哀的现实 2021-02-04 09:00

I have a datagrid in WPF with a DataGridTextColum and a DataGridTemplateColum.



        
相关标签:
5条回答
  • 2021-02-04 09:13

    the simple answer for that create new control derived from datagrid control

      using System.Windows.Controls;
    
       public class CustomDataGrid : DataGrid
       {
    
        protected override void OnSelectedCellsChanged(SelectedCellsChangedEventArgs e)
        {
            //to make sure cell is selected
            var cells = e.AddedCells.FirstOrDefault();
            if (cells != null)
            {
                this.BeginEdit();
    
            }
            base.OnSelectedCellsChanged(e);
        }
    
       }
    
    0 讨论(0)
  • 2021-02-04 09:15

    I managed it, not the best solution but it works... When Cell gets focus I set it to editing mode.

    private void myDataGridMain_OnFocus(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell != null)
            cell.IsEditing = true;
        //var test = FindVisualChild<TextBlock>(cell);
    }
    

    On Keydown I search for the visual child and give the focus.

    private void myDataGridMain_KeyDown(object sender, KeyEventArgs e)
            {
                DataGridCell cell = sender as DataGridCell;
    
                if (e.Key == Key.Enter)
                {   //give cell the focus
                    cell.Focus();
                }
                else
                {
                    if ((cell != null))
                    {
                        TextBox textbox = FindVisualChild<TextBox>(cell);
                        if (textbox != null)
                        {   //TextBox has benn found
                            if ((textbox as TextBox).IsFocused == false)
                            {
                                (textbox as TextBox).SelectAll();
                            }
                            (textbox as TextBox).Focus();
                        }
    
                        CheckBox chkbox = FindVisualChild<CheckBox>(cell);
                        if (chkbox != null)
                        {   //Checkbox has been found
                            (chkbox as CheckBox).Focus();
                        }
    
                        ComboBox combbox = FindVisualChild<ComboBox>(cell);
                        if (combbox != null)
                        {   //ComboBox has been found
                            (combbox as ComboBox).Focus();
                        }
                    }
                }
            }
    

    Find Visual Child!

    public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
            if (child != null && child is T)
                return (T)child;
            else
            {
                T childOfChild = FindVisualChild<T>(child);
                if (childOfChild != null)
                    return childOfChild;
            }
        }
        return null;
    }
    
    0 讨论(0)
  • 2021-02-04 09:22

    This approach works for me. It uses the fact that the DataGrid will always create a new instance of the template when the editing starts:

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

    and in the code behind:

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

    As an added bonus, it also selects all text in the cell. It should work no matter how you enter the editing mode (double click, single click, pressing F2)

    0 讨论(0)
  • 2021-02-04 09:27

    Hisham's suggestion works perfectly for me, but I would use OnCurrentCellChanged instead, since OnSelectedCellsChanged will not work when the SelectionUnit is CellOrRowHeader. In the latter case BeginEdit() would only be triggered when selection moves to a cell in another row. Stepping left or right will not trigger the event at all.

    Also, it is probably advisable to add a DependencyProperty to the custom control and check against it before triggering BeginEdit(), to prevent this behavior if so desired (as done by other DataGrids, such as XCeed). But this is not a critic - just something that I usually do.

        protected override void OnCurrentCellChanged(EventArgs e)
        {
            // Make sure a cell is selected and only enter edit mode
            // if this is the desired behavior 
            if (CurrentCell != null && EditTrigger == EditTriggers.CellsCurrent)
            {
                this.BeginEdit();
            }
            base.OnCurrentCellChanged(e);
        }
    
    0 讨论(0)
  • 2021-02-04 09:31

    This seems to work :

        <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <TextBox  FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"></TextBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    
    0 讨论(0)
提交回复
热议问题