实施“拖动并填充” WPF DataGrid中的功能 [英] Implement "drag and fill" functionality in WPF datagrid

查看:89
本文介绍了实施“拖动并填充” WPF DataGrid中的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在开发一个利用数据网格的应用程序。网格的大多数功能都是相当标准的东西-样式单元格,单元内编辑,排序等。但是,一项要求是提供拖放功能,例如Excel。在这里,您可以在一行中选择一个或多个单元格,然后在它们周围绘制一个粗边框。边框的右下角有一个小正方形,当您向下拖动该边框时,Excel会将选定的单元格值复制到下面的行中。

We are developing an app that utilises a data grid. Most of the grid's functionality will be fairly standard stuff - styling cells, in-cell editing, sorting, etc. However one requirement is to provide "drag and fill" functionality, like Excel. This is where you select one or more cells inside a row, which then get a thick border drawn around them. The border has a small square on its bottom-right corner, and when you drag this down Excel copies the selected cell values to the rows below.

这听起来像令人恐惧尝试使用.Net WPF数据网格实现的东西(也没有商业数据网格组件提供此功能)。有没有人开发过类似的功能,或建议实现此功能的可能方法?普通旧副本

This sounds like a frightening thing to try and implement using the .Net WPF data grid (and no commercial data grid component provides this feature either). Has anyone developed a similar feature, or suggest possible approaches to accomplishing this? Plain old copy & paste is not an option!

推荐答案

以下是在数据网格中围绕所选单元格绘制粗线的一些技巧:

Here are some tips to draw a thick line around your selected cells in a datagrid:


  • 订阅datagrid的SelectedCellsChanged事件。

  • 在事件处理程序中,获取数据网格的装饰层,如果所选单元格的数量> 0并且还没有(缓存的)装饰层,则向其添加自定义装饰。通过装饰器的构造函数传递数据网格。如果所选单元格的数量== 0并且缓存的adornerlayer!= null,请从装饰器层中删除装饰器。在事件处理程序的末尾,调用adornerLayer.Update(datagrid)

  • 使用以下CustomAdorner类:

  • Subscribe to the datagrid's SelectedCellsChanged event.
  • In the event handler, get the adorner layer of the datagrid and add a custom adorner to it if the number of selected cells > 0 and if there is no (cached) adornerlayer yet. Pass the datagrid via the adorner's constructor. If the number of selected cells == 0 and the cached adornerlayer != null, remove the adorner from the adorner layer. At the end of the event handler, call adornerLayer.Update(datagrid)
  • Use the following CustomAdorner class:

public class DataGridSelectionAdorner : Adorner {
    private readonly DataGrid datagrid;
    private readonly SolidColorBrush backgroundBrush = new SolidColorBrush(Color.FromArgb(30, 0, 0, 0));
    readonly Pen pen = new Pen(new SolidColorBrush(Colors.Black), 1);
    private readonly Dictionary<DataGridCellInfo, int[]> cellInfoToTableRowAndColumn = new Dictionary<DataGridCellInfo, int[]>();

    public DataGridSelectionAdorner(UIElement adornedElement)
        : base(adornedElement) {
        datagrid = (DataGrid)adornedElement;
        pen.DashStyle = new DashStyle(new[] { 3.0, 3.0 }, 0);
        IsHitTestVisible = false;
    }

    protected override void OnRender(DrawingContext drawingContext) {
        ItemContainerGenerator generator = datagrid.ItemContainerGenerator;
        IEnumerable<int> rows =
                datagrid.SelectedCells.Select(c =>
                    generator.IndexFromContainer(
                        generator.ContainerFromItem(c.Item)
                    )
                );
        IEnumerable<int> columns = datagrid.SelectedCells.Select(
            c => c.Column.DisplayIndex
        );
        int minRow = rows.Min();
        int maxRow = rows.Max();
        int minColumn = columns.Min();
        int maxColumn = columns.Max();

        foreach (var cell in datagrid.SelectedCells) {
            int row = generator.IndexFromContainer(generator.ContainerFromItem(cell.Item));
            int column = cell.Column.DisplayIndex;
            cellInfoToTableRowAndColumn[cell] = new[] { row, column };
        }

        var topLeft = cellInfoToTableRowAndColumn.First(c => c.Value[0] == minRow && c.Value[1] == minColumn).Key;
        var bottomRight = cellInfoToTableRowAndColumn.First(c => c.Value[0] == maxRow && c.Value[1] == maxColumn).Key;

        var topLeftCell = GetDataGridCell(topLeft);
        var bottomRightCell = GetDataGridCell(bottomRight);

        const double marginX = 4.5;
        const double marginY = 3.5;
        Point topLeftPoint = topLeftCell.TranslatePoint(new Point(marginX, marginY), datagrid);
        Point bottomRightPoint = bottomRightCell.TranslatePoint(
            new Point(bottomRightCell.RenderSize.Width - marginX, bottomRightCell.RenderSize.Height - marginY),
            datagrid
        );

        drawingContext.DrawRectangle(backgroundBrush, pen, new Rect(topLeftPoint, bottomRightPoint));
    }

    private static DataGridCell GetDataGridCell(DataGridCellInfo cellInfo) {
        var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
        if (cellContent != null)
            return (DataGridCell)cellContent.Parent;
        return null;
    }
}


这篇关于实施“拖动并填充” WPF DataGrid中的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆