wpfdatagridwpftoolkitwpf-4.0

How to select all the text when the edit textbox in a DataGridTemplateColumn receives focus?


I'm trying to get a DataGridTemplateColumn to behave identically to a TextColumn

Got the first one done ; however selecting all the text isn't working. As mentioned by a number of posts, tried hooking into the GotFocus event and selecting all the text in code-behind. This worked for a standalone textbox ; however for a Textbox which is the edit control for a TemplateColumn, this doesn't work.

Any ideas? Code Sample:

<Window.Resources>
            <Style x:Key="HighlightTextBoxStyle" TargetType="{x:Type TextBox}">
                <EventSetter Event="GotFocus" Handler="SelectAllText"/>
                <EventSetter Event="GotMouseCapture" Handler="SelectAllText"/>
                <Setter Property="Background" Value="AliceBlue"/>
            </Style>

            <DataTemplate x:Key="DefaultTitleTemplate">
                <TextBlock Text="{Binding Title}"/>
            </DataTemplate>
            <DataTemplate x:Key="EditTitleTemplate">
                    <TextBox x:Name="Fox"
                         FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"  
                         Text="{Binding Path=Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                         Style="{StaticResource HighlightTextBoxStyle}">
                    </TextBox>
            </DataTemplate>
        </Window.Resources>
        <DockPanel>
            <TextBox DockPanel.Dock="Top" x:Name="Test" Text="{Binding Path=(FocusManager.FocusedElement).Name, ElementName=MyWindow}" 
                     Style="{StaticResource HighlightTextBoxStyle}"/>
            <toolkit:DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
                <toolkit:DataGrid.Columns>
                    <toolkit:DataGridTemplateColumn Header="Templated Title" 
                        CellTemplate="{StaticResource DefaultTitleTemplate}"
                        CellEditingTemplate="{StaticResource EditTitleTemplate}" />

                    <toolkit:DataGridTextColumn Header="Title" Binding="{Binding Path=Title}" />
                </toolkit:DataGrid.Columns>
            </toolkit:DataGrid>
        </DockPanel>

Solution

  • Missed updating the post with an answer...

    The problem seems to be that for a custom data grid column (aka a DataGridTemplateColumn) the grid has no way of knowing the exact type of the editing control (which is specified via a DataTemplate and could be anything). For a DataGridTextColumn, the editing control type is known and hence the grid can find it and invoke a SelectAll() in it.

    So to achieve the end-goal for a TemplateColumn, you need to provide an assist. I forgotten how I solved it the first time around.. but here is something that I searched-tweaked out today. Create a custom derivation of a TemplateColumn with an override of the PrepareCellForEdit method as shown below (Swap Textbox with your exact editing control).

    public class MyCustomDataColumn : DataGridTemplateColumn
        {
            protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
            {
                var contentPresenter = editingElement as ContentPresenter;
    
                var editingControl = FindVisualChild<TextBox>(contentPresenter);
                if (editingControl == null)
                    return null;
    
                editingControl.SelectAll();
                return null;
            }
    
            private static childItem FindVisualChild<childItem>(DependencyObject obj) 
        }
    

    Here's an implementation for FindVisualChild.

    XAML:

       <WPFTestBed:MyCustomDataColumn Header="CustomColumn"
                        CellTemplate="{StaticResource DefaultTitleTemplate}"
                        CellEditingTemplate="{StaticResource EditTitleTemplate}"/>
    </DataGrid.Columns>
    

    Lot of code for an annoying inconsistency.