c# - tutorial - Edición automática del contenido de la cuadrícula de datos de WPF cuando la celda de la cuadrícula de datos se enfoca
wpf presentacion (4)
Este enfoque funciona para mí. Utiliza el hecho de que DataGrid
siempre creará una nueva instancia de la plantilla cuando comience la edición:
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding MyProperty}"
Loaded="TextBox_Loaded"></TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
y en el código detrás:
private void TextBox_Loaded(object sender, RoutedEventArgs e)
{
((TextBox)sender).Focus();
((TextBox)sender).SelectAll();
}
Como una ventaja adicional, también selecciona todo el texto en la celda. Debería funcionar sin importar cómo ingrese al modo de edición (haga doble clic, presione un solo botón, presione F2)
Tengo una cuadrícula de datos en WPF con un DataGridTextColum y un DataGridTemplateColum .
<DataGridTextColumn Width="4*" IsReadOnly="True" x:Name="dataGridColumnDescription"
Header="Description" Binding="{Binding Description}">
</DataGridTextColumn>
<DataGridTemplateColumn CellStyle="{StaticResource CellEditing}" IsReadOnly="False" Width="*" Header="Value"
CellEditingTemplateSelector="{StaticResource myCellEditingTemplateSelectorValue}"
CellTemplateSelector="{StaticResource myCellTemplateSelectorValue}">
</DataGridTemplateColumn>
CellTemplateSelectors devuelve un DataTemplate con un TextBlock para la respuesta Celltemplate. un TextBox para la edición de celdas!
<DataTemplate x:Key="dGridStringValueTemplate">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Path=Value}"/>
</DataTemplate>
<DataTemplate x:Key="dGridStringValueTemplateEditing">
<TextBox TextAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" BorderThickness="1" Text="{Binding Path=Value, UpdateSourceTrigger=LostFocus}"/>
</DataTemplate>
Ahora quiero centrar automáticamente el TextBox cuando DataGridCell obtiene el foco. El usuario debe poder editar el contenido de TextBox sin hacer doble clic en la celda.
Encontré este artículo:
Sugerencias y trucos de DataGrid: Edición de un solo clic donde puedo obtener el DataGridCell actual, pero ¿cómo puedo acceder al contenido para darle al Textbox el foco para editar el contenido?
Este es mi estilo:
<Style x:Key="CellEditing" TargetType="{x:Type DataGridCell}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="myDataGridMain_PreviewMouseLeftButtonDown"></EventSetter>
</Style>
Este es mi controlador de eventos:
private void myDataGridMain_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DataGridCell cell = sender as DataGridCell; // cell ist not null
DataGridTemplateColumn col = cell.Column as DataGridTemplateColumn; //col is not null
DataTemplate template = col.CellTemplate; //this is null
}
¿Cómo puedo obtener el cuadro de texto con ese controlador de eventos?
Esto parece funcionar:
<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>
Lo logré, no es la mejor solución, pero funciona ... Cuando Cell obtiene el foco, lo configuro en el modo de edición.
private void myDataGridMain_OnFocus(object sender, RoutedEventArgs e)
{
DataGridCell cell = sender as DataGridCell;
if (cell != null)
cell.IsEditing = true;
//var test = FindVisualChild<TextBlock>(cell);
}
En Keydown busco el niño visual y le doy el foco.
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();
}
}
}
}
Encuentra 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;
}
la respuesta simple para eso crea un nuevo control derivado del control de la cuadrícula de datos
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);
}
}