RELATEED CONSULTING
相关咨询
选择下列产品马上在线沟通
服务时间:9:30-18:00
你可能遇到了下面的问题
关闭右侧工具栏
Dragging and Dropping DataGrid Columns
  • 作者:zhaozj
  • 发表时间:2020-12-23 11:02
  • 来源:未知

Download the ColumnDragDataGrid.msi file

Introduction

A few months ago, when I was getting started at Microsoft, my manager walked into my office, and detailed a project on which I would be spending the next two weeks. I was to conjure up an application that would be used to aggregate metrics for content strategists at MSDN. One of the feature requests was a DataGrid-like control that would allow users to arrange columns in their preferred order before exporting the data to a Microsoft Excel spreadsheet. His last words prior to departing my office were, "Make it an interesting user experience."

I knew that in order to be able to rearrange DataGrid columns, I had to manipulate the DataGrid's DataGridColumnStyle property to reflect the new column ordering, but that wasn't exactly enthralling. I wanted a visual representation of the whole dragging operation. I started out playing around with some System.Drawing functionality, and got to a point where I was able to drag shapes across the screen. I decided that I needed to kick it up a notch. Instead of just dragging a bland and uninspiring rectangle painted atop the DataGrid drawing surface, I could make it appear as if the user was dragging the column. I dug down to the roots of the native GDI library and after several hours of experimenting, figured out what I needed to do in order to achieve this trickery.

Figure 1. The dragging operation

Getting Started

The first thing I needed to do was figure out how I was going to take a screenshot of the column that was about to be dragged. I knew exactly what I needed and wanted to do, but didn't know how to do it. After discovering that the classes residing under the System.Drawing namespace didn't provide me with the functionality that I needed to perform screen captures, I looked into the native GDI library and found that the BitBlt function was exactly what I was looking for.

The next step was to write a managed wrapper around this function. The first thing I'll cover in this article is how I implemented the ScreenImage class.

The ScreenImage Class

In order to make invocations across the interoperation boundary, we need to declare the unmanaged functions and indicate which libraries they come from so the JIT compiler knows where to find them during runtime. Once this has been done, all we have to do is invoke them just as we do with managed method invocations, as seen in the code block below.

public sealed class ScreenImage { [DllImport("gdi32.dll")] private static extern bool BitBlt( IntPtr handlerToDestinationDeviceContext, int x, int y, int nWidth, int nHeight, IntPtr handlerToSourceDeviceContext, int xSrc, int ySrc, int opCode); [DllImport("user32.dll")] private static extern IntPtr GetWindowDC( IntPtr windowHandle ); [DllImport("user32.dll")] private static extern int ReleaseDC( IntPtr windowHandle, IntPtr dc ); private static int SRCCOPY = 0x00CC0020; public static Image GetScreenshot( IntPtr windowHandle, Point location, Size size ) { ... } }