DataGridCell — это TextBlock при опускании, но TextBox при подъеме

Итак, у меня есть DataGrid, который содержит элементы, которые выглядят так:

<DataGridTextColumn Header="Dto 1" Binding="{Binding Path=Dto1}">
    <DataGridTextColumn.EditingElementStyle>
        <Style TargetType="{x:Type TextBox}">
            <EventSetter Event="PreviewKeyDown" Handler="TextBox_PreviewKeyDown"/>
            <EventSetter Event="GotFocus" Handler="TextBox_GotFocus"/>
        </Style>
    </DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>

PreviewKeyDown работает отлично, когда я поднимаюсь, я могу без проблем вернуться в ячейку. Как я это вижу, для всех намерений и целей у меня есть TextBox.

Теперь, когда я пытаюсь спуститься с ячейки в событии:

private void dgPropuestas_GotFocus(object sender, RoutedEventArgs e) {
        var cell = e.OriginalSource as DataGridCell;
        if (cell != null) {
            var cp = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(cell, 0), 0) as ContentPresenter;
            var tb = cp.Content as TextBlock;
            if (tb != null)
                tb.Focus();
        }
    }

(Примечание: я дважды устанавливал метод VisualTreeHelper вручную, у меня есть метод FindVisualChildren, но я просмотрел дерево вручную и в отчаянии, чтобы немного ускориться, я поставил его вручную)

Если я попытаюсь объявить tb как cp.Content как TextBox, я получу ноль. По какой-то причине ContentPresenter имеет внутри TextBlock, а не TextBox. FindVisualChildren(cell) возвращает пустой IEnumerable.

Почему это проблема? Потому что мне нужно иметь возможность вызывать SelectAll() для текста, а textBlock не предлагает такой возможности. Любая помощь приветствуется. Заранее спасибо!

Позднее редактирование: по-видимому, когда не в режиме редактирования, сетка данных содержит текстовый блок. В режиме редактирования текстовое поле. Теперь datagrid.BeginEdit(), похоже, не работает, поскольку он не инициализирует TextBox и не запускает событие PrepareCellForEditing.


person Manu Andrei    schedule 24.06.2016    source источник


Ответы (2)


Совершенно неправильный подход к этому. Вы подписываетесь на события на TextBox, поэтому sender всегда будет называться TextBox.

person H.B.    schedule 24.06.2016
comment
Я не совсем понимаю, что вы имеете в виду. У меня есть только текстовые поля в моем DataGrid, и я пытаюсь переключить фокус на другое текстовое поле. Дело в том, что я использую клавиши со стрелками для навигации по DataGrid, поэтому всякий раз, когда я нажимаю клавишу со стрелкой, фокус устанавливается на следующую ячейку. Там я хочу иметь возможность выбрать свой TextBox и сделать SelectAll() - person Manu Andrei; 24.06.2016
comment
Разве вам не нужно просто сфокусироваться и выбрать все на Loaded, на которые вы можете подписаться на TextBox? - person H.B.; 24.06.2016
comment
(Кроме того, текстовый столбец по умолчанию уже фокусируется и выбирает текст по умолчанию, поэтому вам просто нужно войти в режим редактирования программно.) - person H.B.; 24.06.2016

Учитывая, что TextBox не будет инициализирован ни с помощью BeginEditing(), ни с помощью isEditing = true, проблема была устранена путем объявления полей как текстового поля и принудительного их размещения в сетке данных:

<DataGridTemplateColumn Header="Dto 2">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBox Text="{Binding Dto2}" GotFocus="TextBox_GotFocus" PreviewKeyDown="TextBox_PreviewKeyDown"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
person Manu Andrei    schedule 24.06.2016