Home > other >  Text of a cell is highlighted after starting editing
Text of a cell is highlighted after starting editing

Time:07-05

I load the contents of a database (mdb) into a DataTable object and display them in a DataGrid so that I can edit them. As soon as I start editing a cell (pressing F2), the entire text is selected.

Left (actual): All text is selected on edit. Right (expected): Caret is moved to end on edit.

Is there a way to prevent this marking?

My DataGrid markup:

<DataGrid VirtualizingStackPanel.VirtualizationMode="Standard" Height="750" Width="1920" CanUserResizeColumns="True" CanUserReorderColumns="False" CanUserResizeRows="False" RowHeight="25" FrozenColumnCount="1" x:Name="DataGrid1" CanUserAddRows="False" CanUserSortColumns="False" AutoGenerateColumns="False" FontSize="13" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,120" SelectionUnit="CellOrRowHeader" SelectionMode="Extended">

   <DataGrid.Columns>
       <DataGridTextColumn Width="450" Header=" Column1 " Binding="{Binding Column1}">
           <DataGridTextColumn.EditingElementStyle>
               <Style TargetType="TextBox">
                   <Setter Property="MaxLength" Value="150"></Setter>
               </Style>
           </DataGridTextColumn.EditingElementStyle>
       </DataGridTextColumn>
   
       <DataGridTextColumn Width="120" Header=" Column2 " Binding="{Binding Column2}">
           <DataGridTextColumn.EditingElementStyle>
               <Style TargetType="TextBox">
                   <Setter Property="MaxLength" Value="10"></Setter>
               </Style>
           </DataGridTextColumn.EditingElementStyle>
       </DataGridTextColumn>
   </DataGrid.Columns>
   
   <DataGrid.RowStyle>
       <Style TargetType="DataGridRow">
           <EventSetter Event="KeyDown"  Handler="DATAGRID_Keydown" ></EventSetter>
       </Style>
   </DataGrid.RowStyle>

</DataGrid>

My C# Code:

private void DATAGRID_Keydown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Tab | e.Key == Key.F2)
    {
      DataGrid1.BeginEdit();
    }
}

CodePudding user response:

As an alternative to adding a handler for PreparingCellEdit in code-behind, you could create a behavior that encapsulates the code for moving the caret of the TextBox in order to make it reusable across multiple views without copy-pasting the code for each instance.

You have to install the Microsoft.Xaml.Behaviors.Wpf NuGet package and create a behavior for DataGrid. The behavior adds a handler to PreparingCellEdit and sets the caret to the end. There is also an attached property which enables you to exclude columns from the behavior. By inverting the default value, you could disable the behavior by default and enable it explicitly for each column.

public class PrepareTextEditBehavior : Behavior<DataGrid>
{
   public static readonly DependencyProperty MoveCaretToEndProperty = DependencyProperty.RegisterAttached(
      "MoveCaretToEnd", typeof(bool), typeof(PrepareTextEditBehavior), new PropertyMetadata(true));

   public static bool GetMoveCaretToEnd(DependencyObject obj)
   {
      return (bool)obj.GetValue(MoveCaretToEndProperty);
   }

   public static void SetMoveCaretToEnd(DependencyObject obj, bool value)
   {
      obj.SetValue(MoveCaretToEndProperty, value);
   }

   protected override void OnAttached()
   {
      base.OnAttached();
      AssociatedObject.PreparingCellForEdit  = OnPreparingCellForEdit;
   }

   protected override void OnDetaching()
   {
      base.OnDetaching();
      AssociatedObject.PreparingCellForEdit -= OnPreparingCellForEdit;
   }

   private static void OnPreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
   {
      if (!GetMoveCaretToEnd(e.Column))
         return;

      var textBox = (TextBox)e.EditingElement;
      textBox.CaretIndex = textBox.Text.Length;
   }
}

To use the behavior, simply add it to the data grid in the Interaction.Behaviors tag.

<DataGrid ...>
   <b:Interaction.Behaviors>
      <local:PrepareTextEditBehavior/>
   </b:Interaction.Behaviors>
   <DataGrid.Columns>

      <DataGridTextColumn ...>
         <!-- ...column markup. -->
         <!-- ...the behavior is applied here by default. -->
      </DataGridTextColumn>

      <DataGridTextColumn ...
                          local:PrepareTextEditBehavior.MoveCaretToEnd="False">
         <!-- ...column markup. -->
         <!-- ...the behavior is NOT applied here explicitly. -->
      </DataGridTextColumn>
   </DataGrid.Columns>

</DataGrid>

CodePudding user response:

you can use the PreparingCellForEdit event for the DataGrid:

XAML

<DataGrid ... PreparingCellForEdit="DataGrid_PreparingCellForEdit">

C# (It will place the cursor at the end of the current cell text)

private void DataGrid_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
{
    ((TextBox)e.EditingElement).SelectionStart = ((TextBox)e.EditingElement).Text.Length;
}

You can use use ((TextBox)e.EditingElement).SelectionStart = 0; to place the cursor at the beginning of the original text of that cell.

  • Related