remove event app c# .net wpf events xaml

c# - event - Edición con un solo clic en WPF DataGrid



subscribe event handler c# (8)

Quiero que el usuario pueda poner la celda en el modo de edición y resaltar la fila en la que está contenida la celda con un solo clic. Por defecto, esto es doble clic. ¿Cómo anulo o implemento esto? He buscado en google, y la respuesta Codeplex no funciona para mí.

Soy bastante nuevo en WPF y la codificación en general, por lo que una respuesta simple es mejor.


Así es como resolví este problema:

<DataGrid DataGridCell.Selected="DataGrid_GotFocus" ItemsSource="{Binding Source={StaticResource itemView}}"> <DataGrid.Columns> <DataGridTextColumn Header="Nom" Binding="{Binding Path=Name}"/> <DataGridTextColumn Header="Age" Binding="{Binding Path=Age}"/> </DataGrid.Columns> </DataGrid>

Este DataGrid está vinculado a un CollectionViewSource (que contiene objetos Person simulados).

La magia sucede allí: DataGridCell.Selected = "DataGrid_GotFocus" .

Simplemente engancho el evento seleccionado de la celda DataGrid y llamo a BeginEdit () en el DataGrid.

Aquí está el código detrás del controlador de eventos:

private void DataGrid_GotFocus(object sender, RoutedEventArgs e) { // Lookup for the source to be DataGridCell if (e.OriginalSource.GetType() == typeof(DataGridCell)) { // Starts the Edit on the row; DataGrid grd = (DataGrid)sender; grd.BeginEdit(e); } }

{disfrutar}


De: http://wpf.codeplex.com/wikipage?title=Single-Click%20Editing

XAML:

<!-- SINGLE CLICK EDITING --> <Style TargetType="{x:Type dg:DataGridCell}"> <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown"></EventSetter> </Style>

CÓDIGO DETRÁS:

// // SINGLE CLICK EDITING // private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { DataGridCell cell = sender as DataGridCell; if (cell != null && !cell.IsEditing && !cell.IsReadOnly) { if (!cell.IsFocused) { cell.Focus(); } DataGrid dataGrid = FindVisualParent<DataGrid>(cell); if (dataGrid != null) { if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow) { if (!cell.IsSelected) cell.IsSelected = true; } else { DataGridRow row = FindVisualParent<DataGridRow>(cell); if (row != null && !row.IsSelected) { row.IsSelected = true; } } } } } static T FindVisualParent<T>(UIElement element) where T : UIElement { UIElement parent = element; while (parent != null) { T correctlyTyped = parent as T; if (correctlyTyped != null) { return correctlyTyped; } parent = VisualTreeHelper.GetParent(parent) as UIElement; } return null; }


Hay dos problemas con la respuesta de user2134678. Uno es muy leve y no tiene efecto funcional. El otro es bastante significativo.

El primer problema es que GotFocus se está llamando en realidad contra DataGrid, no DataGridCell en la práctica. El calificador DataGridCell en el XAML es redundante.

El principal problema que encontré con la respuesta es que el comportamiento de la tecla Enter está roto. Enter debería moverlo a la celda siguiente debajo de la celda actual en el comportamiento normal de DataGrid. Sin embargo, lo que sucede realmente detrás de las escenas es que el evento GotFocus se llamará dos veces. Una vez sobre la célula actual, perdiendo el foco, y una vez que la nueva célula gana el foco. Pero siempre que se llame a BeginEdit en esa primera celda, la siguiente celda nunca se activará. El resultado es que tiene edición con un solo clic, pero cualquiera que no haga clic literalmente en la cuadrícula tendrá inconvenientes, y un diseñador de interfaz de usuario no debe suponer que todos los usuarios están usando mouses. (Los usuarios de teclado pueden sortearlo usando Tab, pero eso todavía significa que están saltando por aros que no deberían).

¿Entonces la solución a este problema? Maneje el evento KeyDown para la celda y si la clave es la tecla Intro, configure un indicador que impida que BeginEdit se active en la primera celda. Ahora la tecla Enter se comporta como debería.

Para comenzar, agregue el siguiente Estilo a su DataGrid:

<DataGrid.Resources> <Style TargetType="{x:Type DataGridCell}" x:Key="SingleClickEditingCellStyle"> <EventSetter Event="KeyDown" Handler="DataGridCell_KeyDown" /> </Style> </DataGrid.Resources>

Aplique ese estilo a la propiedad "CellStyle" cuyas columnas desea habilitar con un solo clic.

Luego, en el código que se encuentra detrás tienes lo siguiente en tu controlador de GotFocus (ten en cuenta que estoy usando VB aquí porque eso es lo que nuestro cliente de "solicitud de cuadrícula de datos con un clic" quería como lenguaje de desarrollo):

Private _endEditing As Boolean = False Private Sub DataGrid_GotFocus(ByVal sender As Object, ByVal e As RoutedEventArgs) If Me._endEditing Then Me._endEditing = False Return End If Dim cell = TryCast(e.OriginalSource, DataGridCell) If cell Is Nothing Then Return End If If cell.IsReadOnly Then Return End If DirectCast(sender, DataGrid).BeginEdit(e) . . .

Luego, agrega su controlador para el evento KeyDown:

Private Sub DataGridCell_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) If e.Key = Key.Enter Then Me._endEditing = True End If End Sub

Ahora tiene un DataGrid que no ha cambiado ningún comportamiento fundamental de la implementación lista para usar y, sin embargo, admite la edición con un solo clic.


La respuesta de Micael Bergeron fue un buen comienzo para mí para encontrar una solución que funcione para mí. Para permitir la edición con un solo clic también para Cells en la misma fila, eso ya está en modo de edición, tuve que ajustarlo un poco. Usar SelectionUnit Cell no fue una opción para mí.

En lugar de utilizar el Evento DataGridCell.Selected que solo se activa por primera vez en la celda de una fila, utilicé el evento DataGridCell.GotFocus.

<DataGrid DataGridCell.GotFocus="DataGrid_CellGotFocus" />

Si lo haces, tendrás siempre la celda correcta enfocada y en el modo de edición, pero no se enfocará ningún control en la celda, esto lo resolví así

private void DataGrid_CellGotFocus(object sender, RoutedEventArgs e) { // Lookup for the source to be DataGridCell if (e.OriginalSource.GetType() == typeof(DataGridCell)) { // Starts the Edit on the row; DataGrid grd = (DataGrid)sender; grd.BeginEdit(e); Control control = GetFirstChildByType<Control>(e.OriginalSource as DataGridCell); if (control != null) { control.Focus(); } } } private T GetFirstChildByType<T>(DependencyObject prop) where T : DependencyObject { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(prop); i++) { DependencyObject child = VisualTreeHelper.GetChild((prop), i) as DependencyObject; if (child == null) continue; T castedProp = child as T; if (castedProp != null) return castedProp; castedProp = GetFirstChildByType<T>(child); if (castedProp != null) return castedProp; } return null; }


La solución de http://wpf.codeplex.com/wikipage?title=Single-Click%20Editing funcionó muy bien, pero la habilité para cada DataGrid que utilizaba un estilo definido en ResourceDictionary. Para usar manejadores en diccionarios de recursos, debe agregar un archivo de código subyacente. Así es como lo haces:

Este es un Diccionario de recursos DataGridStyles.xaml :

<ResourceDictionary x:Class="YourNamespace.DataGridStyles" x:ClassModifier="public" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="DataGrid"> <!-- Your DataGrid style definition goes here --> <!-- Cell style --> <Setter Property="CellStyle"> <Setter.Value> <Style TargetType="DataGridCell"> <!-- Your DataGrid Cell style definition goes here --> <!-- Single Click Editing --> <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" /> </Style> </Setter.Value> </Setter> </Style> </ResourceDictionary>

Tenga en cuenta el atributo x: Class en el elemento raíz. Crea un archivo de clase. En este ejemplo, sería DataGridStyles.xaml.cs . Ponga este código adentro:

using System.Windows.Controls; using System.Windows; using System.Windows.Input; namespace YourNamespace { partial class DataGridStyles : ResourceDictionary { public DataGridStyles() { InitializeComponent(); } // The code from the myermian''s answer goes here. }


Lo resolví agregando un disparador que establece la propiedad IsEditing de DataGridCell en True cuando el mouse está sobre él. Solucionó la mayoría de mis problemas. Funciona con comboboxes también.

<Style TargetType="DataGridCell"> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="IsEditing" Value="True" /> </Trigger> </Style.Triggers> </Style>


Prefiero esta manera en base a la sugerencia de Dušan Knežević. haces clic en eso)

<DataGrid.Resources> <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"> <Style.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="True" /> <Condition Property="IsReadOnly" Value="False" /> </MultiTrigger.Conditions> <MultiTrigger.Setters> <Setter Property="IsEditing" Value="True" /> </MultiTrigger.Setters> </MultiTrigger> </Style.Triggers> </Style> </DataGrid.Resources>


<DataGridComboBoxColumn.CellStyle> <Style TargetType="DataGridCell"> <Setter Property="cal:Message.Attach" Value="[Event MouseLeftButtonUp] = [Action ReachThisMethod($source)]"/> </Style> </DataGridComboBoxColumn.CellStyle>

public void ReachThisMethod(object sender) { ((System.Windows.Controls.DataGridCell)(sender)).IsEditing = true; }