Winform Drag Drop copy or move depending on destination - winforms

I would like to implement Drag and Drop between 3 Datagridview dgv1, dgv2 and dgv3.
When DragDrop is performed between dgv1 and dgv2, it would be a move action. Elements in source dgv are deleted and added to destination dgv.
When dragging from dgv1 or dgv2 to dgv3, it would be a copy only. In the reverse direction when dgv3 is source, elements will not be added to dgv1 or dgv2. They would have already existed in either dgv1 or dgv2.
Currently the removal of source element is in source's MouseDown event. How could I manipulate the action depending on the destination dgv ?
private void _columnGrid_MouseDown(object sender, MouseEventArgs e)
{
if (e.Clicks == 1)
{
int rowIndex = _columnGrid.HitTest(e.X, e.Y).RowIndex;
if (rowIndex < 0)
return;
DragDropEffects dde1 = DoDragDrop(_columnGrid.Rows[rowIndex].DataBoundItem as ItemFormula, DragDropEffects.All);
if (dde1 == DragDropEffects.All)
{
_columnGrid.Rows.RemoveAt(rowIndex);
}
}
}
For the first part of the question, when dgv3 is destination, I can achieve by setting DragDropEffect to Copy in dgv3.
private void _lineGrid_DragOver(object sender, DragEventArgs e)
{
//copy only
e.Effect = DragDropEffects.Copy;
}
How about the second part, when I want to drag and drop from dgv3 back to either dgv1 or dgv2?
Thanks in advance.

Related

how to assign hot key for datagridview combobox column?

i have grid view have combobox column ["column2"]
if (keyData == (Keys.F11))
{
for (int i = 0; i < dataGridView1.RowCount - 1; i++)
{
//here i want to change index automatically using hot key (keyboard short cut )
}
return true;
You can't directly assign ShortcutKey to a individual cell. Handle the KeyPress event of DataGridView for key combinations. In the event handler, put the below code
void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyData == (Keys.Alt | Keys.E))
{
dataGridView1.Rows[RowIndex].Cells[ColumnIndex].Selected = true;
dataGridView1.CurrentCell = dataGridView1.Rows[RowIndex].Cells[ColumnIndex];
dataGridView1.BeginEdit(false);
}
}
if any cell is already in edit mode then the editing control would get the KeyPress events not the DataGridView. If you want to overcome that you have to subclass the existing DataGridView control and override its ProcessCmdKey function. See the answer to this SO question for that.
To change the selected index of the editing combo, subscribe the EditingControlShowing event and in the event handler change the combobox index.
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
ComboBox control = e.Control as ComboBox;
if (control !=null)
{
// set the selected index of the combo here.
}
}

Winforms DataGridView SQL compact CRUD example

I have a very simple table with two string columns marked unique. Can anyone tell me how to wire up the datagridview to allow the most basic crud operations. I intend to use only the grid and no additional controls. This means having a link column for the delete operation.
I have tried a million iterations of having data tables, binding sources, data adapters, command builders..
Many thanks.
void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
}
private void bindingSource_PositionChanged(object sender, EventArgs e)
{
// if the user moves to a new row, check if the
// last row was changed
BindingSource thisBindingSource =
(BindingSource)sender;
DataRow ThisDataRow =
((DataRowView)thisBindingSource.Current).Row;
if (ThisDataRow == _lastDataRow)
{
// we need to avoid to write a datarow to the
// database when it is still processed. Otherwise
// we get a problem with the event handling of
//the DataTable.
throw new InvalidOperationException("It seems the" +
" PositionChanged event was fired twice for" +
" the same row");
}
UpdateRowToDatabase();
// track the current row for next
// PositionChanged event
_lastDataRow = ThisDataRow;
}
private void UpdateRowToDatabase()
{
if (_lastDataRow != null)
{
if (_lastDataRow.RowState == DataRowState.Modified
|| _lastDataRow.RowState == DataRowState.Added
|| _lastDataRow.RowState == DataRowState.Deleted)
{
DataRow[] rows = new DataRow[1];
rows[0] = _lastDataRow;
_dataAdapter.Update(rows);
}
}
}
void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
Debug.WriteLine(string.Format("Click Col: {0} Row:{1}", e.ColumnIndex, e.RowIndex));
if (!_edit && e.ColumnIndex == 0)
{
if (e.RowIndex < _dataTable.Rows.Count)
{
DataRow[] rows = new DataRow[1];
rows[0] = _dataTable.Rows[e.RowIndex];
_bindingSource.RemoveCurrent();
_dataAdapter.Update(rows);
}
}
}
See the ResultSetGrid class in the CodePlex project here: http://sqlcetoolbox.codeplex.com/SourceControl/changeset/view/77500#1210725

How do I go about implementing drag delta on shapes

How do I go about implementing the drag delta on a Shape, I have the following code:
void Connector_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (e.ClickCount == 1)
{
this.Focus();
this.CaptureMouse();
this.RaiseEvent(new DragStartedEventArgs(0,0));
initMousePoint = e.GetPosition(this);
}
e.Handled = true;
}
void Shape2_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
currMousePoint = e.GetPosition(this);
if (this.IsMouseCaptured)
{
this.RaiseEvent(new DragDeltaEventArgs(0,0);
}
}
void Shape2_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.ReleaseMouseCapture();
}
Now for the DragDeltaEvent args do I need to compute the drag in the mousemove and pass it to the event, also is this the right way to raise the event. If this works, then I should only subscribe to the drag delta event and use it as a thumb? Note, I do not want to template the thumb with the shape, providing this answer won't help me.
note the chagnes, about the getting the position of the mouse, this I don't think works, because it gets the position relative to the element, not the containing panel, so I don't think i will be able to find the drag distance this way.
I solved it using:
currMousePoint = e.GetPosition(this);
double dragHorizontal = currMousePoint.X - initMousePoint.X;
double dragVertical = currMousePoint.Y - initMousePoint.Y;
//Set the new canvas top and left proeprties here.

WPF ListView - How to copy individual cells

I have code where I can take a look at the SelectedItem and then output ToString() to get the record into the clipboard.
How can I detect what cell the user is right clicking on in order to copy just that cell in the SelectedItem?
For example, if I have Borrower Information and the user right-clicks on last name, I would like to give the ability to just copy last name to clipboard.
Thank you!
UPDATE:
Here is the code that I used as suggested by Josh, it worked great:
private void BorrowerInfoCopyClicked(object sender, RoutedEventArgs e)
{
BorrowerViewModel vm = this.DataContext as BorrowerViewModel;
if (vm != null)
{
Clipboard.SetData(DataFormats.Text, vm.CurrentTextBlockText);
}
}
private void AddressCopyClicked(object sender, RoutedEventArgs e)
{
BorrowerViewModel vm = this.DataContext as BorrowerViewModel;
if (vm != null)
{
Clipboard.SetData(DataFormats.Text, vm.CurrentTextBlockText);
}
}
private void lstViews_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
BorrowerViewModel vm = this.DataContext as BorrowerViewModel;
if (vm != null)
{
if (e.OriginalSource is TextBlock)
{
TextBlock txtBlock = e.OriginalSource as TextBlock;
vm.CurrentTextBlockText = txtBlock.Text;
}
}
}
I've done this by handling the PreviewMouseRightButtonDown event on the ListView and checking if e.OriginalSource is a TextBlock. If so, copy the txtBlk.Text to the clipboard. This code could either be in the code-behind of the View that contains the ListView, or as a behavior you attach to the ListView. If you need to use a context menu to perform the Copy operation, have a TextBlock field that you use to store a reference to the TextBlock, and in your method that responds to a MenuItem's click (or Command execution) reference the TextBlock there instead.

How to view drag & drop element in WPF?

I have a ListBox and a DockPanel. List box contains items that are supposed to be dragged onto the dock panel. I've implemented that by following this link.
There are a couple of things I do not understand though:
While dragging, all I see is a cursor. I'd like to literary see the list item I am
dragging to move around with my cursor. How do I do that?
Is the DragDropEffect property only for the different cursor design or it has a
higher purpose? :)
How do I make list item disappear from the ListBox once it is dropped onto the
DockPanel?
I'd like to enforce some animation on the items that I drag, like glow once it is
dropped. Which trigger/setter should I use for that?
Here's my code for basic dragging and dropping:
Code-behind for the ListBox part
private Point startPosition;
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
startPosition = e.GetPosition(null);
}
private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point currentPosition;
Vector offset;
ListBox listBox;
ListBoxItem item;
Match match;
DataObject dragData;
currentPosition = e.GetPosition(null);
offset = startPosition - currentPosition;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(offset.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(offset.Y) > SystemParameters.MinimumVerticalDragDistance))
{
// Get the data binded to ListBoxItem object, which is "match"
listBox = sender as ListBox;
item = FindAnchestor<ListBoxItem>((DependencyObject)e.OriginalSource);
match = (Match)listBox.ItemContainerGenerator.ItemFromContainer(item);
dragData = new DataObject("match", match);
DragDrop.DoDragDrop(item, dragData, DragDropEffects.Move);
}
}
Code-behind for the DockPanel part
private void DockPanel_DragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent("match") ||
sender == e.Source)
{
e.Effects = DragDropEffects.None;
}
}
private void DockPanel_Drop(object sender, DragEventArgs e)
{
Match match;
DockPanel matchSlot;
ContentPresenter contentPresenter;
Binding binding;
if (e.Data.GetDataPresent("match"))
{
match = e.Data.GetData("match") as Match;
matchSlot = sender as DockPanel;
contentPresenter = new ContentPresenter();
contentPresenter.ContentTemplate = this.FindResource("MatchTemplate") as DataTemplate;
binding = new Binding();
binding.Source = match;
contentPresenter.SetBinding(ContentPresenter.ContentProperty, binding);
matchSlot.Children.Clear();
matchSlot.Children.Add(contentPresenter);
}
}
Thanks for all the help.
Ok, after a while I found some answers and discovered a few things on my own.
As for the DragDropEffect enum, it should be used for two reasons:
To distinguish if the item is moved or copied in the code. It serves like a flag and should be used most commonly like this:
if (e.DragDropEffect == DragDropEffect.Move)
{
...
}
else ...
To decorate the mouse cursor based on the enum value. This way it tells the user if he or she is moving or copying the item.
As for the drag and drop visualization here's a link to the post containing the reference which is an excellent starting point for drag and drop to build on: WPF Drag & Drop: How to literally drag an element?

Resources