Click to See Complete Forum and Search --> : How to detect where a DragDrop operation was intitiaited?
BigEd781
December 21st, 2008, 01:57 AM
Here is my situation:
__ ____
/ \ | |
| | | |
\ __ / |___ |
Custom ListView
Control
There are six positions on the custom control (wheel) which can be filled by dragging an item from the list. You can drag these objects in any way, i.e., list to wheel, wheel to wheel, list to list, wheel to list. When an object is dragged from the wheel to the list it should be removed from the wheel and it's position value in the list updated (as it is whenever an object is moved around).
The problem is, a drag drop operation is initiated OnMouseDown. So, when you click an item in the list that is currently in the wheel, it is removed from the wheel and its position set to 0 in the list. The objects being dragged around are the same, so I cannot differentiate by the type. I have some things that would work, but I think they are kind of ugly (like packing this information with the object being dragged around).
If there was an event that was fired when a DragDrop operation ended (regardless of whether it was successful or not) that could be used to set a flag, but I don't know of an event like that.
JonnyPoet
December 21st, 2008, 03:21 AM
If there was an event that was fired when a DragDrop operation ended (regardless of whether it was successful or not) that could be used to set a flag, but I don't know of an event like that.The event you are looking for is simple the mouse up event IMHO every dragging dropping action ends when you stop to keep your fingers on left mouse button down.
In case of unsuccessfu action your element stay in its position if you have dragged it with success it will be added to the list of the item
But IMHO a flag is useless. You simple need a list for the wheel which not only keeps the fact that the item is in the wheel, you need to have it in a Dictionary<int,itemClass> where the integer represents the position in the wheel. Adding to the wheel needs to get the 'object sender ' of the DragDrop event to retrive information where it was dropped, (Hopefully you only use one delegate for the wheel items ) so you can store the item in a correct slot of the dictionary. Leaving the wheel removes the item from the dictionary.
BigEd781
December 21st, 2008, 03:50 AM
The later part of your post is almost exactly as I already have it, so that is reassuring, but there is still a problem. It is valid to drag an item from the filter to the list, but the list has no way of knowing where that item came from as the object is the same (the data object being passed around is a struct).
The real problem is that it is already in the list. A flag, while perhaps not the best solution, could be set when I start the DragDrop from the list and would be toggled when the DragDrop operation ends. That assumes that there is a way of knowing when that happens.
JonnyPoet
December 21st, 2008, 05:37 AM
....The real problem is that it is already in the list. A flag, while perhaps not the best solution, could be set when I start the DragDrop from the list and would be toggled when the DragDrop operation ends. That assumes that there is a way of knowing when that happens.So obviously I didn't fully understand your problem: Do you have one or two lists or do you have a list at each position where the item is? You cant figure out the actual position of the item or you cannot figure out where to delete the item ? What exactly is it ?
toraj58
December 21st, 2008, 05:57 AM
try this code: i made a new class DragedItem with two properties then i copy the selecteditem string to its value and name of the control to the tag property then when DragDrop event was fired i can read tag and find out which control was the source od drag.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace DragDrop
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
DragedItem dObj = new DragedItem();
dObj.Value = listBox1.SelectedItem.ToString();
dObj.Tag = listBox1.Name;
listBox1.DoDragDrop(dObj, DragDropEffects.Move);
}
private void listBox2_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(DragedItem)))
{
e.Effect = DragDropEffects.Move;
}
}
private void listBox2_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(DragedItem)))
{
DragedItem itemToDrop = (DragedItem)e.Data.GetData(typeof(DragedItem));
listBox2.Items.Add(itemToDrop.Value);
label1.Text = itemToDrop.Tag;
}
}
}
public class DragedItem : Object
{
private string _tag;
private string _value;
public string Tag
{
set {_tag = value;}
get {return _tag;}
}
public string Value
{
set { _value = value; }
get { return _value; }
}
}
}
TheCPUWizard
December 21st, 2008, 11:56 AM
Typically the object should inherently "know" where it lives (ie have a parent). Other approaches make things very difficult to implement.
What happens if the user clicks on multiple items (possible originating in different containers, then does a drop???
BigEd781
December 21st, 2008, 04:02 PM
@Toraj: Thanks, that was one of my idea, but I didn't like the custom control knowing about the list, but perhaps I am going overboard as that will definitely work.
@CPU:Multi-select is set to false, so they can only drop one item at a time. The object being dragged is a custom type, so the containers will only allow a drop if the type matches. The data being dragged around is a struct, so it does not inherently know of a parent object. I could make a property, but that seems ugly to me.
Basically, when an item is dragged to the list, the parent of the parent of the list and custom control gets an event notification. In that event, I check to see if the item is in the wheel. If it is, I remove it. The problem is that I don't know if it was dragged from the wheel or the list. I need some way of knowing this in the list in the DragEnter event. If I know it was dragged from the list I can set the DragDropEffect to 'None'.
As a junior programmer with no degree, I sometimes get overly concerned with design decisions. I don't want to check in w.t.f code, but I couldn't think of anything other than the the solutoion that Toraj suggested (a wrapper for the dragged object). What do you guys think about going that route?
TheCPUWizard
December 21st, 2008, 04:06 PM
Once again, having a Parent property would solve all of your issue.
BigEd781
December 21st, 2008, 04:13 PM
I know, I just edited my last post. It would have to be set manually when the struct is created and it doesn't seem to fit with the rest of the data structure, but yes, it would work. Again, sometimes I get too hung up on design purity when something just needs to get done (and I am sure that my idea or design purity is sometimes off the mark ;))
TheCPUWizard
December 21st, 2008, 04:17 PM
I know, I just edited my last post. It would have to be set manually when the struct is created and it doesn't seem to fit with the rest of the data structure, but yes, it would work. Again, sometimes I get too hung up on design purity when something just needs to get done (and I am sure that my idea or design purity is sometimes off the mark ;))
IF the classes are not inherent to this patttern, then toraj58's approach can be appropriate.
You always use a wrapper and dereference the appropriate parts.
BigEd781
December 21st, 2008, 04:20 PM
OK, I think that is the way I will go then. If you guys (who have infinitely more experience than I) don't think that is bad, neither do I. Thanks for the help everyone.
JonnyPoet
December 21st, 2008, 05:40 PM
[quote=BigEd781;1794600...solutoion that Toraj suggested (a wrapper for the dragged object). What do you guys think about going that route?[/quote]Have you looked to MSDN they have a full example there about drag and drop. They work with indexes. Look at this one (full MS example code ) :wave:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.dodragdrop.aspx
toraj58
December 22nd, 2008, 07:55 AM
thanks jonny; also the point to handle QueryContinueDrag event from MSDN was helpful.
TheCPUWizard
December 22nd, 2008, 09:21 AM
Have you looked to MSDN they have a full example there about drag and drop. They work with indexes. Look at this one (full MS example code ) :wave:
One thing to remember when looking at "Samples", is that they are intended for illustrative purposes, and typically have the minimum amount of code necessaery to demonstrate specific functionallity.
In 99% of the cases, they are NOT indicitive of "Best Preactices" and are not "Production Quality" code. It is VERY VERY rare that you can copy/paste from a reference sample into a "real" program and have anything approaching a robust architecture and design.
JonnyPoet
December 22nd, 2008, 10:10 AM
...
In 99% of the cases, they are NOT indicitive of "Best Preactices" and are not "Production Quality" code. It is VERY VERY rare that you can copy/paste from a reference sample into a "real" program and have anything approaching a robust architecture and design.This is especially true for this example as it doesn't proper work in an MDI enviroment because of the code in QueryContinueDrag, which for example gives unexpected results when the form, where to both listboxes are on, is an MDI child.
BigEd781
December 22nd, 2008, 11:25 AM
That example did show me some new techniques when handling DragDrop operations, so thanks! I ended up going with the object wrapper. It works nicely and actually helped me to find a bit of code that needed refactoring.
JonnyPoet
December 22nd, 2008, 01:27 PM
That example did show me some new techniques when handling DragDrop operations, so thanks! I ended up going with the object wrapper. It works nicely and actually helped me to find a bit of code that needed refactoring.Congrats
toraj58
December 23rd, 2008, 07:19 AM
@TheCPUWizard: it is obvious that sample code and code snippets are not the best solution that can be apply to any problem as a final solution.
in addition that they are disigned for illustrative purpose and demostrating power of the language they also will give information to the programmer in parts that he/ she has not mentioned to it or missed it.
final solution will be a combination of experience, looking to more than one code sample, good data stucture desing (base on application needs), good analyze, asking people and investigating best practices.
without all of them the final solution may works but it is not optimized and the best way of doing things.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.