在WPF DataGrid中select像Excel一样的矩形

这个问题类似于Excel中的Wpf itemscontrol中的拖动select ,但我想在DataGrid中,而不是一个ListBox。
我正在尝试使WPF DataGrid中的select矩形看起来像Excel一样,包括较低RHangular处的小黑色方块,并且没有每个单独选定单元格的边框。 任何人都可以在WPF DataGrid中有一个这样的工作示例?

在这里输入图像说明

首先,您必须使用本答案中描述的方法隐藏聚焦单元格上的边框:

<DataGrid.CellStyle> <Style TargetType="DataGridCell"> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> </Style> </DataGrid.CellStyle> 

然后,您需要使用DataGridOnSelectedCellsChanged事件来添加/删除将绘制select矩形的装饰器。 对于填充手柄,您可以使用一个Thumb来处理拖放的东西:

  void DataGrid_OnSelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e) { var datagrid = (System.Windows.Controls.DataGrid)sender; AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(datagrid); if (datagrid.SelectedCells.Any()) { DataGridCellInfo firstCellInfo = datagrid.SelectedCells.First(); FrameworkElement firstElt = firstCellInfo.Column.GetCellContent(firstCellInfo.Item); DataGridCellInfo lastCellInfo = datagrid.SelectedCells.Last(); FrameworkElement lastElt = lastCellInfo.Column.GetCellContent(lastCellInfo.Item); if (firstElt != null && lastElt != null) { var firstcell = (DataGridCell)firstElt.Parent; var lastCell = (DataGridCell) lastElt.Parent; Point topLeft = datagrid.PointFromScreen(firstcell.PointToScreen(new Point(0, 0))); Point bottomRight = datagrid.PointFromScreen(lastCell.PointToScreen(new Point(lastCell.ActualWidth, lastCell.ActualHeight))); var rect = new Rect(topLeft, bottomRight); if (fillHandleAdorner == null) { fillHandleAdorner = new FillHandleAdorner(datagrid, rect); adornerLayer.Add(fillHandleAdorner); } else fillHandleAdorner.Rect = rect; } } else { adornerLayer.Remove(fillHandleAdorner); fillHandleAdorner = null; } } 

FillHandleAdorner类的代码:

 using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; namespace DataGrid { internal class FillHandleAdorner : Adorner { const int SIZE = 5; Rect rect; readonly Thumb thumb; readonly VisualCollection visualChildren; Point mousePosition; System.Windows.Controls.DataGrid dataGrid; public Rect Rect { get { return rect; } set { rect = value; UpdateThumbPos(rect); mousePosition = rect.BottomRight; InvalidateVisual(); } } public FillHandleAdorner(UIElement adornedElement, Rect rect) : base(adornedElement) { dataGrid = (System.Windows.Controls.DataGrid)adornedElement; Rect = rect; visualChildren = new VisualCollection(this); var border = new FrameworkElementFactory(typeof(Border)); border.SetValue(Border.BackgroundProperty, Brushes.Black); thumb = new Thumb { Cursor = Cursors.Cross, Background = new SolidColorBrush(Colors.Black), Height = SIZE, Template = new ControlTemplate(typeof(Thumb)) { VisualTree = border }, Width = SIZE }; visualChildren.Add(thumb); UpdateThumbPos(rect); thumb.DragDelta += thumb_DragDelta; } void UpdateThumbPos(Rect rect) { if (thumb == null) return; mousePosition = rect.BottomRight; mousePosition.Offset(-SIZE/2 - 1, -SIZE/2 - 1); thumb.Arrange(new Rect(mousePosition, new Size(SIZE, SIZE))); } void thumb_DragDelta(object sender, DragDeltaEventArgs e) { mousePosition.Offset(e.HorizontalChange, e.VerticalChange); IInputElement inputElt = dataGrid.InputHitTest(mousePosition); var tb = inputElt as TextBlock; if (tb == null) return; Point bottomRight = dataGrid.PointFromScreen(tb.PointToScreen(new Point(tb.ActualWidth + 1, tb.ActualHeight + 1))); Rect = new Rect(rect.TopLeft, bottomRight); } protected override int VisualChildrenCount { get { return visualChildren.Count; } } protected override Visual GetVisualChild(int index) { return visualChildren[index]; } protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); var blackSolidBrush = new SolidColorBrush(Colors.Black); var pen = new Pen(blackSolidBrush, 3); pen.Freeze(); double halfPenWidth = pen.Thickness / 2; Rect rangeBorderRect = rect; rangeBorderRect.Offset(-1, -1); GuidelineSet guidelines = new GuidelineSet(); guidelines.GuidelinesX.Add(rangeBorderRect.Left + halfPenWidth); guidelines.GuidelinesX.Add(rangeBorderRect.Right + halfPenWidth); guidelines.GuidelinesY.Add(rangeBorderRect.Top + halfPenWidth); guidelines.GuidelinesY.Add(rangeBorderRect.Bottom + halfPenWidth); Point p1 = rangeBorderRect.BottomRight; p1.Offset(0, -4); guidelines.GuidelinesY.Add(p1.Y + halfPenWidth); Point p2 = rangeBorderRect.BottomRight; p2.Offset(-4, 0); guidelines.GuidelinesX.Add(p2.X + halfPenWidth); drawingContext.PushGuidelineSet(guidelines); var geometry = new StreamGeometry(); using (StreamGeometryContext ctx = geometry.Open()) { ctx.BeginFigure(p1, true, false); ctx.LineTo(rangeBorderRect.TopRight, true, false); ctx.LineTo(rangeBorderRect.TopLeft, true, false); ctx.LineTo(rangeBorderRect.BottomLeft, true, false); ctx.LineTo(p2, true, false); } geometry.Freeze(); drawingContext.DrawGeometry(null, pen, geometry); drawingContext.Pop(); } } } 

代码不完整,因为它是一个尚未开始的项目,但它应该可以帮助你开始。