How to override WPF DataGrid behavior to implement drag and drop in an external application?

I have a DataGrid WPF with the following definition.

<DataGrid Name="DataGridFoo" AutoGenerateColumns="False" ItemsSource="{Binding GridData}" IsReadOnly="True" SelectionMode="Extended" SelectionUnit="CellOrRowHeader"> 

This allows me to select the "area" of cells. DataGrid is tied to the observed collection. XAML column definitions contain several columns, some of which look like this:

 <DataGridTextColumn Binding="{Binding InvoiceID}" Header="Invoice ID" Visibility="Hidden" Width="Auto"/> <DataGridTextColumn Binding="{Binding InvoiceNumber}" Header="Invoice Number" Visibility="Visible" Width="Auto"/> <DataGridTextColumn Binding="{Binding InvoiceDate, StringFormat=\{0:MM/dd/yy\}}" Header="Invoice Date" Visibility="Visible" Width="Auto"/> 

I also have a right-click context menu defined for a DataGrid:

 <DataGrid.ContextMenu> <ContextMenu FontSize="16" Background="#FFE6E9EC"> <MenuItem Header="Contact" Click="Contact_Click" /> <Separator /> <MenuItem Header="Copy" Command="Copy" /> </ContextMenu> </DataGrid.ContextMenu> 

I would like to be able to click, drag and delete a copy of selected cells into an external application. I thought to use a combination of pressing the Alt key and the Left mouse button to start the DragDrop operation.

For example, consider the "irregular" cell selection in a DataGrid:

enter image description here

I do not understand how to do this, and you have a few questions regarding this:

1) What events do I redefine so that left-clicking does not affect the selected cells?

2) . How to determine whether the left mouse button is clicked in the selected cell area? How to process a piece of data?

3) Once I have identified above, what will be the next step? Copy data to clipboard for use in external drop?

4) What events (if any) do I need to override in the DataGrid for this to work?

thanks

+5
source share
2 answers

The main events for drag and drop are: events for drag and drop

Specially DragLeave and Drop do what you want. Then you need to manage (delete / add) the GridData property from your virtual machine to search and move values. I highly recommend a third party, like Telerik, do this.

0
source

Here is your complete answer, which I consider.

  private void dataGridMaster_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if(Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift) & e.ChangedButton == MouseButton.Left) { DataGrid grid = e.Source as DataGrid; DataGridCell cell = GetParent<DataGridCell>(e.OriginalSource as DependencyObject); if(grid != null && cell != null && cell.IsSelected) { e.Handled = true; StartDragAndDrop(grid); } } } private T GetParent<T>(DependencyObject d) where T:class { while (d != null && !(d is T)) { d = VisualTreeHelper.GetParent(d); } return d as T; } private void StartDragAndDrop(DataGrid grid) { StringBuilder sb = new StringBuilder(); DataRow row = null; foreach(DataGridCellInfo ci in grid.SelectedCells) { DataRowView drv = ci.Item as DataRowView; string column = ci.Column.Header as string; if(drv != null && column != null) { if(drv.Row != row && row != null) { sb.Length--; sb.AppendLine(); row = drv.Row; } else if(row == null) { row = drv.Row; } sb.Append(drv[column].ToString() + "\t"); } } if (sb.Length > 0) { sb.Length--; sb.AppendLine(); } DragDrop.DoDragDrop(grid, sb.ToString(), DragDropEffects.Copy); } 

Here you need the shift key to be pressed to signal a drag. This is necessary to eliminate the ambiguity of the click and drag that are used in the DataGrid to select cells. You can use some other mechanism, such as a context menu item.

The clipboard is the key to any drag and drop operation. What you are doing is placing data on the clipboard in various formats that the drop target recognizes. This example uses only plain text. But you can create rich text or HTML or any number of other formats.

The external application that you drop must be registered as a target point. You cannot force another application to respond to a crash ... it must listen to it. Thus, this example will work with Word and Excel. He will not work with Notepad.

I believe that all 4 elements are satisfied:

  • Override mouse preview event.
  • The original source of the mouse event comes from a data grid cell. If a cell is selected, you are within the block of selected cells.
  • For the selected cells, collect data from the bindings and organize them into a grid. Use plain text as the baseline, but maybe add other formats as well. Use the DragDrop class to actually perform drag and drop.
  • Cancel the preview of the mouse down.
0
source

Source: https://habr.com/ru/post/1266338/


All Articles