在WPF DataGrid中单击编辑

我希望用户能够将单元格置于编辑模式,并单击单击来突出显示单元格所在的行。 默认情况下,这是双击。 我如何重写或实现这个? 我search了谷歌,codeplex答案不适合我。

我对WPF和编码一般都很陌生,所以一个简单的答案是更好的。

以下是我如何解决这个问题:

<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> 

这个DataGrid绑定到一个CollectionViewSource(包含dummy Person对象)。

奇迹发生在那里: DataGridCell.Selected =“DataGrid_GotFocus”

我简单地钩住DataGrid单元格的选定事件,并在DataGrid上调用BeginEdit()。

这里是事件处理程序的代码:

  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); } } 

{请享用}

Micael Bergeron的回答对我来说是一个很好的开始,为我find一个解决scheme。 要允许单击也编辑同一行中已经在编辑模式的单元格,我不得不调整一下。 使用SelectionUnit单元对我来说是不可选的。

而不是使用DataGridCell.Selected事件,这是第一次单击行的单元格被触发,我使用DataGridCell.GotFocus事件。

 <DataGrid DataGridCell.GotFocus="DataGrid_CellGotFocus" /> 

如果你这样做,你将始终有正确的细胞聚焦和编辑模式,但没有在细胞的控制将集中,我解决这个问题

 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; } 

来自: 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> 

后台代码:

 // // 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; } 

来自http://wpf.codeplex.com/wikipage?title=Single-Click%20Editing的解决scheme非常适合我,但是我使用ResourceDictionary中定义的样式为每个DataGrid启用了它。; 要在资源字典中使用处理程序,您需要向其添加代码隐藏文件。 以下是你如何做到这一点:

这是一个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> 

请注意根元素中的x:Class属性。 创build一个类文件。 在这个例子中,它将是DataGridStyles.xaml.cs 。 把这个代码放在里面:

 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. } 

我更喜欢这种方式根据DušanKnežević的build议。 你点击一个就是它))

 <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> 

user2134678的答案有两个问题。 一个是非常小的,没有function的影响。 另一个是相当重要的。

第一个问题是GotFocus实际上是针对DataGrid而不是DataGridCell的。 XAML中的DataGridCell限定符是多余的。

我发现答案的主要问题是input键行为被破坏。 input应该移动到正常DataGrid行为中当前单元格下的下一个单元格。 但是,幕后实际发生的事情是GotFocus事件将被调用两次。 一旦当前细胞失去重点,并一度在新的细胞获得重点。 但只要BeginEdit在第一个单元格上被调用,下一个单元格就不会被激活。 结果是你有一键编辑,但是任何不是真正点击网格的人都会感到不便,而且用户界面devise者不应该假定所有的用户都在使用鼠标。 (键盘用户可以通过使用Tab来解决这个问题,但这仍然意味着他们正在跳过他们不需要的环节。)

那么解决这个问题呢? 处理单元格的事件KeyDown,如果Key是Enter键,设置一个标志,停止BeginEdit在第一个单元格上触发。 现在,Enter键的行为应该如此。

首先,将以下样式添加到您的DataGrid中:

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

将该样式应用于“CellStyle”属性的要启用一次单击的列。

然后在后面的代码中,在GotFocus处理程序中有以下内容(请注意,我在这里使用VB是因为这是我们的“一键式数据网格请求”客户端想要的开发语言):

 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) . . . 

然后你添加你的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 

现在你有一个DataGrid,它并没有改变开箱即用的实现的基本行为,而是支持单击编辑。

我通过添加一个触发器来解决这个问题,当鼠标hover时,将DataGridCell的IsEditing属性设置为True。 它解决了我的大部分问题。 它也适用于combobox。

 <Style TargetType="DataGridCell"> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="IsEditing" Value="True" /> </Trigger> </Style.Triggers> </Style> 
  <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; }