在WPF DataGrid中进行单击编辑

15 浏览
0 Comments

在WPF DataGrid中进行单击编辑

我希望用户能够通过单击将单元格置于编辑模式,并突出显示包含该单元格的行。默认情况下,这需要双击。

我该如何覆盖或实现这个功能?

0
0 Comments

问题的出现原因:在WPF的DataGrid中,想要实现单击就可以编辑的效果,但是使用上述的XAML和CODE-BEHIND代码时,会出现一些问题。首先,当有ComboBox存在时,由于点击ComboBox的弹出菜单,会导致cell.Focus()方法失效;其次,当点击DataGrid以外的区域时,也会出现问题。

解决方法:添加一个判断,判断鼠标事件的原始来源是否在DataGrid内部,如果不在,则不进行后续的操作。可以通过使用FindVisualParent方法来找到鼠标事件的原始来源是否是DataGrid的子元素。

整理成的文章如下:

在WPF的DataGrid中,我们希望实现单击即可编辑的效果。网上有一份代码,可以实现这一功能。下面给出了这份代码的XAML和CODE-BEHIND部分:

XAML代码如下:

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

CODE-BEHIND代码如下:

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

然而,在某些情况下,这段代码并不能正常工作,而且相比Micael Bergerons的解决方案更加复杂。对于我来说,这几乎是一个解决方案。但是我需要添加一个“PreviewMouseLeftButtonUp”事件处理程序,并在其中放置完全相同的代码。

此外,当存在ComboBox时,这段代码也无法正常工作。因为点击ComboBox的弹出菜单会导致cell.Focus()方法失效。最简单的解决方法是在代码中添加一个判断,判断鼠标事件的原始来源是否在DataGrid内部。如果不在,则不进行后续的操作。可以通过使用FindVisualParent方法来找到鼠标事件的原始来源是否是DataGrid的子元素。

0
0 Comments

在WPF DataGrid中进行单击编辑的问题是这样出现的:在默认情况下,DataGridCell只有在第一次单击时才会触发Selected事件,而不是每次单击都触发。因此,需要通过其他方式来实现单击编辑。

解决这个问题的方法是使用DataGridCell的GotFocus事件来代替Selected事件。通过订阅这个事件,我们可以确保每次单击都会选中正确的单元格并进入编辑模式。需要注意的是,这种方法会使单元格内的控件失去焦点,因此需要额外处理。

具体的解决方案如下:

1. 在DataGrid中添加GotFocus事件的处理程序:


2. 在事件处理程序中,检查事件的OriginalSource类型是否为DataGridCell,并开始编辑行:

private void DataGrid_CellGotFocus(object sender, RoutedEventArgs e)
{
    if (e.OriginalSource.GetType() == typeof(DataGridCell))
    {
        DataGrid grd = (DataGrid)sender;
        grd.BeginEdit(e);
    }
}

3. 为了确保单元格内的控件获得焦点,可以使用以下方法获取DataGridCell的第一个子控件:

private T GetFirstChildByType(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(child);
        if (castedProp != null)
            return castedProp;
    }
    return null;
}

通过这个方法,我们可以将焦点设置到单元格内的控件上:

Control control = GetFirstChildByType(e.OriginalSource as DataGridCell);
if (control != null)
{
    control.Focus();
}

这样就能够实现在单击DataGridCell时进行编辑的功能。

需要注意的是,对于复选框(checkboxes)来说,这种方法可能无法正常工作,仍然需要双击才能编辑。这可能是因为复选框的默认行为不同,需要额外的处理才能实现单击编辑。这个问题可能需要进一步的研究和调试。

通过使用GotFocus事件和BeginEdit方法,可以实现在WPF DataGrid中进行单击编辑的功能。这个解决方案相对于默认的行为更易于使用和处理。

0
0 Comments

单击编辑在WPF DataGrid中的实现方法

在WPF中,实现单击编辑(Single click edit)功能是一项常见的需求。默认情况下,DataGrid需要双击单元格才能进入编辑模式,但是有时候我们希望通过单击单元格就能直接进入编辑模式。下面是一个解决该问题的方法。

首先,我们需要在XAML代码中定义一个DataGrid,并将其绑定到一个CollectionViewSource,如下所示:


    
        
        
    

在上述代码中,DataGrid的Selected事件被绑定到了一个名为DataGridCell_Selected的事件处理方法。当单击DataGrid的单元格时,这个事件会被触发。

接下来,我们需要在代码中实现DataGridCell_Selected方法,如下所示:

private void DataGridCell_Selected(object sender, RoutedEventArgs e)
{
    // 判断事件源是否为DataGridCell
    if (e.OriginalSource.GetType() == typeof(DataGridCell))
    {
        // 开始编辑行
        DataGrid grd = (DataGrid)sender;
        grd.BeginEdit(e);
    }
}

在上述代码中,我们首先判断事件源是否为DataGridCell,如果是,则调用DataGrid的BeginEdit方法开始编辑行。

需要注意的是,为了解决已选中行的问题,我们需要将DataGrid的SelectionUnit属性设置为Cell。

此外,如果想要在调用grd.BeginEdit(e)后让单元格中的TextBox获得焦点,可以尝试调用FindName方法来获取TextBox,但是这种方法可能会返回null。可能需要在DataGrid的GotFocus事件中添加处理逻辑。

需要注意的是,尽管这种方法可以实现单击编辑功能,但是在复杂的DataGrid中可能会导致一些问题,例如验证、添加新行等。因此,建议在项目中谨慎使用此方法,最好还是使用默认的DataGrid编辑行为。

,通过在DataGrid中绑定Selected事件,并在事件处理方法中调用BeginEdit方法,可以实现单击编辑功能。但是需要注意可能会带来其他问题,因此需要谨慎使用。

0