C# Listview Drag and Drop Rows - c#

I'm trying to implement a C# drag and drop row-reorder with a listview which would then update an SQL database with the current order of the rows. I've come across some snippets of code on the internet (one from this website which implemented a 'var' class) but none seem to be working with my needs. I don't need help updating the database as I have a good idea how I'd do this, but can't seem to get the row reordering to work correctly, any input would be appreciated.
-thanks
m&a

Ensure that AllowDragDrop is set to true.
Implement handlers for at least these 3 events
private void myList_ItemDrag(object sender, ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Link);
}
private void myList_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Link;
}
private void myList_DragDrop(object sender, DragEventArgs e)
{
// do whatever you need to reorder the list.
}
Getting the index of the row you dropped onto may look something like:
Point cp = myList.PointToClient(new Point(e.X, e.Y));
ListViewItem dragToItem = myList.GetItemAt(cp.X, cp.Y);
int dropIndex = dragToItem.Index;

I know this isn't ListView specific, but I have sample code for implementing row drag and drop out of / into a DataGridView. Some of it is obviously control specific, other code is actually pretty generic (such as deciding when its a drag):
http://adamhouldsworth.blogspot.com/2010/01/datagridview-multiple-row-drag-drop.html
Completely forgot the fact that ListView already allows drag-dropping!
I can also add some theory - when the drop occurs on your control, you will need to hit test on those coordinates (likely a method called HitTest) on the ListView to see what row was hit, this is the basis for where to insert the row being dragged.
Unrelated - is that var class perhaps the new var keyword in C#?

Related

WPF Datagrid focus and highlighting last row

I would like to highlight my lastly new create row in my Data grid, I have reference this page http://social.technet.microsoft.com/wiki/contents/articles/21202.wpf-programmatically-selecting-and-focusing-a-row-or-cell-in-a-datagrid.aspx to get some idea.
According to the reference link above datagrid first have to visualise . The reason of the last row is not focus and high light, might be cause by this reason.
Following is my code structure
private void CommitRow(object sender, DataGridRowEditEndingEventArgs e )
{
//FIRE WHEN ROW IS DONE EDIT
/*
STORING DATA TO DATABASE
*/
SelectRowByIndex(Datagrid, Datagrid.Items.Count - 1); //I refer from msdn blog
}
I tried to put the code SelectRowByIndex into a button , it will highlight the last row. Therefore I believe the code will only work when the grid is show up on UI.
My question is how to highlight the last row before interface is show up? or is that any other method allow me to focusing and high light the new create row?
You are correct, it cannot be highlighted, because it isn't rendered yet.
But you can use the dispatcher to your advantage there.
private void CommitRow(object sender, DataGridRowEditEndingEventArgs e )
{
//FIRE WHEN ROW IS DONE EDIT
/*
STORING DATA TO DATABASE
*/
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
SelectRowByIndex(Datagrid, Datagrid.Items.Count - 1);
}));
}
This should do the trick. It calls the Dispatcher to do it with a priority thats just after rendering. Visually this should happen instantly.

RowLoaded event - can't modify cell content

During development with Devexpress, we've encountered the use of a InstantFeedbackSource. Using the Row_Loaded, we would like to adjust values of certain rows. Yet the CellContent isn't changed.
Testsolution:
GetQueryable-Method of my datasource:
private void linqInstantFeedbackSource1_GetQueryable_1(object sender, GetQueryableEventArgs e)
{
e.QueryableSource = _testObjects.AsQueryable();
gridView2.RefreshData();
gridControl2.RefreshDataSource();
}
My Row-loaded event
private void gridView2_RowLoaded(object sender, DevExpress.XtraGrid.Views.Base.RowEventArgs e)
gridView2.SetRowCellValue(e.RowHandle, gridView2.Columns["RandomGuid4"], "lalalala");
}
Information:
gridView2.Columns["RandomGuid4"] is not null and refers to the correct-column.
e.RowHandle Refers to the correct Linenumber
Goal:
I want to achieve the following behavior:
At runtime i want to fill the gird with records. When adding the rows i want to check the row for certain values. When a certain value occurs then several another cells should be filled with combobox, hyperlinks,...
The advised way by devexpress is the event CustomCellEdit. But that event is highly unreliable. We're experiencing issues (exceptions from within the control). I've submitted several tickets so far but no response. So we're searching an alternative.
Could someone point out what i'm exactly missing/doing wrong here?
Thank you for your time.
Note: I've tried the use of RefreshData in my RowLoaded-Event but it doesn't appear to be working.

Limit drag and drop to within a single control

I've looked and looked and can't find an answer.
I have a TreeView. It has Drag and Drop to allow moving of Nodes within the tree.
I want to limit the drag and drop to only work within that one control, within a single instance of the application (the application itself can run more than one instance).
I've tried the following:
private void SubFolderTreeView_DragEnter(object sender, DragEventArgs e)
{
TreeView source = sender as TreeView; // also tried = (TreeView) sender;
if (source == this.SubFolderTreeView && e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
e.Effect = DragDropEffects.Move; // Okay, set the visual effect
else
e.Effect = DragDropEffects.None; // Unknown data, ignore it
}
Unfortunately, a second instance of the same application will still be able to drag from its TreeView to the first TreeView: (source == this.SubFolderTreeView) is true
I have not tested if a totally different treeview could drag to mine, though I doubt it, but the above behaviour is already a fail.
I tried some other things - comparing the form or the control's handle also didn't work
bool isSameForm = ((MyForm) source.TopLevelControl == this); // still true
bool isSameHandle = (((Control)source).Handle == ((Control)this.SubFolderTreeView).Handle); // still true
The only other things I can think of, off the top of my head, is a random number stored in the TreeView or Form (probably won't work), and checking the absolute screen position of the control (not the best method).
I could of course stick a mutex in the application and so only allow one instance to run, but I'd rather not.
Can anyone suggest a good way of doing this?
To flesh out Hans Passant's solution (which worked perfectly, thanks Hans) for future reference and other searchers into this problem, I used the code:
// prevents dragging from other instances of this form - thanks to Hans Passant
private bool DragDropFromThisForm = false;
private void SubFolderTreeView_ItemDrag(object sender, ItemDragEventArgs e)
{
// Initiate drag/drop
DragDropFromThisForm = true;
DoDragDrop(e.Item, DragDropEffects.Move);
DragDropFromThisForm = false;
}
private void SubFolderTreeView_DragEnter(object sender, DragEventArgs e)
{
MyForm form = (MyForm) (sender as TreeView).TopLevelControl;
if (form.DragDropFromThisForm && e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
e.Effect = DragDropEffects.Move; // Okay, set the visual effect
else
e.Effect = DragDropEffects.None; // Unknown data, ignore it
}
It may well be that DJ Kraze's answer would also work, and perhaps be a tad more elegant, but Hans' solution is lightweight and effective.
I'm not really following the restrictions, seems like flawed logic with the information you've given (all identical instances, but only one can have drag and drop - what??), but some suggestions:
Have a property that determines whether nodes can 'drag and drop' and only set it in the one instance.
Only subscribe to the event on the one instance that you want to be able to 'drag and drop' on.
Create a separate TreeView class that supports dragging and dropping, and instantiate the base TreeView everywhere else.

drag and drop winform controls

I want to drag and drop a control (label for example) in a winform application. I saw some examples on dragging and dropping text, but this is not what I want. I want to enable the user to move a control around. Can anyone direct me to some resources or examples? Thanks.
you should look at examples on how to make draggable controls.
There are some answers here in SO as well.
See this Move controls when Drag and drop on panel in C#
this is a complete example on how to host the Form Designer:
Tailor Your Application by Building a Custom Forms Designer with .NET
I did something similar in Delphi long time ago, will search the source code, convert it into .NET C# and make a wiki page on that matter, as it is becoming such popular question recently :)
As far as i understand, where you wish to drop a control is called a container, infact any control can act as a container. So first that container, you need to enable the drop property as well as the drag property of the controls which you need to drag.
Then write events (Candrag, candrop, controladded, etc.) for each control where in which, some logic to hold the objects and display them as you may want.
Say, ill take an example where in which, you wish to drag imagetext from combombox into a picturebox and then make the picturebox analyze the text and fine related file name in a directory and load that image into its if its present.
So here, when you start dragging the text from combombox, you have to write some logic in event candrag. Then once you drop, you have to write logic to understand what kinda object was added and get the text related to it (kinda deciphering) in the control where you drop other control.
Sorry, i have no code to give you now, but i hope you got the idea how its done. May be this article can help you? http://vicky4147.wordpress.com/2007/02/04/a-simple-drag-drop-in-winforms/
bool draging = false;
int curPosX, curPosY;
private void label2_MouseDown(object sender, MouseEventArgs e)
{
draging = true;
curPosX = Cursor.Position.X;
curPosY = Cursor.Position.Y;
}
private void label2_MouseMove(object sender, MouseEventArgs e)
{
if (draging)
{
label2.Left += Cursor.Position.X - curPosX;
curPosX = Cursor.Position.X;
label2.Top += Cursor.Position.Y - curPosY;
curPosY = Cursor.Position.Y;
}
}
private void label2_MouseUp(object sender, MouseEventArgs e)
{
draging = false;
}

C# windows form 2 gridviews with synced scroll

I am developing an application in which two datagridviews are being populated from different data sources. I would like to have a single vertical scroll-bar that will make both gridviews work at the same time (scroll up and down together)
can anyone tell me how or direct me to a good tutorial.
If you have dgv1 and dgv2, you can create something like
dgv1.Scroll += new System.Windows.Forms.ScrollEventHandler(dgv1_Scroll);
Then, in dgv1_Scroll method, you can use FirstDisplayedScrollingRowIndex property:
dgv2.FirstDisplayedScrollingRowIndex = dgv1.FirstDisplayedScrollingRowIndex
Of course, if dgv's have different ammount of rows, you need to avoid IndexOutOfRange exception by checking each dgv rows count.
Use HorizontalScrollingOffset (or VerticalScrollingOffset).
this.dataGridViewDataSample.HorizontalScrollingOffset
I believe you can set up an event-like scenario, where whenever scrollbar A's "value" changes, change scrollbar B to the appropriate value as well.
(Note that value is a property of a scroll bar, I do not mean the value of the data inside the container.)
Please see the following msdn article regarding that property of a scroll bar for better reference:
http://msdn.microsoft.com/en-us/library/system.windows.forms.scrollbar.value.aspx
And the class itself --
http://msdn.microsoft.com/en-us/library/system.windows.forms.scrollbar.aspx
You could put the DataGridViews in Panels and use this:
public Form1()
{
InitializeComponent();
panel1.Scroll += new ScrollEventHandler(panel1_Scroll);
}
void panel1_Scroll(object sender, ScrollEventArgs e)
{
panel2.AutoScrollPosition = new Point(0,e.NewValue);
}
Unfortunately it does not seem that DataGridView has this property.
http://www.xs4all.nl/~wrb/Articles_2010/Article_DataGridViewScroll_01.htm
This link shows exactly what I needed and worked fine for me. The only problem I have now is that the datagrids does not have same rows in it. So even when one finishes (no more to scroll) the other must be able to continue.
Any suggestions?
take a look at this. i wanted to sync two listviews when i scroll any of them. u can achieve this using custom controls. code works like a charm.
_dataGridViewInput.Scroll += new ScrollEventHandler(_dataGridViewInput_Scroll);
_dataGridViewOutput.Scroll += new ScrollEventHandler(_dataGridViewOutput_Scroll);
void _dataGridViewInput_Scroll(object sender, ScrollEventArgs e)
{
this._dataGridViewOutput.FirstDisplayedScrollingRowIndex = this._dataGridViewInput.FirstDisplayedScrollingRowIndex;
}
void _dataGridViewOutput_Scroll(object sender, ScrollEventArgs e)
{
this._dataGridViewInput.FirstDisplayedScrollingRowIndex = this._dataGridViewOutput.FirstDisplayedScrollingRowIndex;
}

Categories

Resources