Drag/Drop Label onto FlowLayoutPanel - c#

Im trying to drag a label from a FlowLayoutPanel to another FlowLayoutPanel.Im able to drag but it wont drop the label?
My Code
private void flp_DragEnter(object sender, DragEventArgs e)
{
if ((e.AllowedEffect & DragDropEffects.Link) != 0
&& e.Data.GetDataPresent(typeof(string)))
e.Effect = DragDropEffects.Link;
}
private void flp_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(Label)))
{
FlowLayoutPanel destination = (FlowLayoutPanel)sender;
Control control = (Control)e.Data.GetData(typeof(Label));
destination.Controls.Add(control);
return;
}
}
private void lbl_MouseDown(object sender, MouseEventArgs e)
{
DoDragDrop((sender as Label).Text, DragDropEffects.Link);
}

You can set the Name of the controls as drag data, and then when dropping, find the control by name and remove it from its parent controls collection and add it to target panel controls collection. To do so:
Set AllowDrop property for each control that is target of drop. The target controls in your example can be both FlowLayoutPanel controls.
Handle MouseDown event for each control that drag starts with it and in the handler call DoDragDrop event of that control and set the data that you want to drag. The moving controls in your example are labels and the data here can be Name of control.
Handle DragEnetr event of each target of drag and set e.Effect to determine if drop is allowed or not. Here is the place that you can check if drop is allowed. For example you can check if the data is string and the string is the name of a control.
Hanlde DragDrop and use GetData method of e.Data to get the data and perform the actions when drop. The action here is removing the control from its current parent and add it to the new parent.
Code:
Using the below code, if you assign control_MouseDown to MouseDown events of all labels and assign panel_DragEnter to DragEnter event of both flow layout panels and also assign panel_DragDrop to DragDrop event of both flow layout panels, you can move labels between both flow layout panels, also you can re order labels in a panel:
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
this.DoDragDrop(control.Name, DragDropEffects.Move);
}
private void panel_DragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(string)))
return;
var name = e.Data.GetData(typeof(string)) as string;
var control = this.Controls.Find(name, true).FirstOrDefault();
if (control != null)
{
e.Effect = DragDropEffects.Move;
}
}
private void panel_DragDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(string)))
return;
var name = e.Data.GetData(typeof(string)) as string;
var control = this.Controls.Find(name, true).FirstOrDefault();
if (control != null)
{
control.Parent.Controls.Remove(control);
var panel = sender as FlowLayoutPanel;
((FlowLayoutPanel)sender).Controls.Add(control);
}
}

Related

c# Mouse events through child control

I have a custom user control that contains a chart element that takes up 80% of the space.
When this is placed in a form, i can click the area not occupied by the chart and the click/mousedown/mouseup events work. But yet when i click in the chart area the mouse events aren't passed through and therefore not triggered.
Is there a global way of doing this without having at add the event function for each control on the form?
void Drag_MouseDown(object sender, MouseEventArgs e)
{
activeControl = sender as UserControl;
previousLocation = e.Location;
Cursor = Cursors.SizeAll;
}
void Drag_MouseMove(object sender, MouseEventArgs e)
{
if (activeControl == null || activeControl != sender)
return;
var location = activeControl.Location;
location.Offset(e.Location.X - previousLocation.X, e.Location.Y - previousLocation.Y);
activeControl.Location = location;
}
void Drag_MouseUp(object sender, MouseEventArgs e)
{
activeControl = null;
Cursor = Cursors.Default;
}
These are at the moment having to be manually set to both the custom usercontrol and the chart
It seems like chart overrides your mouse events. So, you can try to add event listeners to chart as well.
PS: We can assign same method to different listeners.

DragEnter and DragDrop events not FIRING in treeview

I need to do drag and drop using treeview in c#.For that i heard 3 events are the most common
1.itemDrag
2.DragDrop and 3.DragEnter.
whereas here itemDrag event is firing for me while dragging from a treeview ,but rest both the events are not firing for me.Tried many solutions and now came here for an solution
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
string[] strItem = e.Item.ToString().Split(':');
DoDragDrop(strItem[1], DragDropEffects.Copy | DragDropEffects.Move); }
the above method fires ,
private void treeView1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
the bove dragEnter event is not firing ,similarly the dragDrop event is also not firing.Why it's so??
Am dragging from the treeview and need to paste in PowerPoint or Word. (ie) treeview is something like an AddIn for Office Tools.
Regards,
Arshad
Allow Drop AND..
Ok, assuming you have all of your events being declared/created in the Form_Load... e.i.
:
tlAssemblies.DragDrop +=tlAssemblies_DragDrop;
tlAssemblies.MouseDown +=tlAssemblies_MouseDown;
tlAssemblies.MouseMove +=tlAssemblies_MouseMove;
tlAssemblies.DragEnter +=tlAssemblies_DragEnter;
tlAssemblies.DragOver += tlAssemblies_DragOver;
The drag Event is for when you fire the drag event inside your treeView which is why it is working. The dragEnter is when you enter the boundaries of a different* control.
i.e you want to drag from treeview 1 into treeview2.
If you are not trying to drag the item into a different control dragEnter is wrong.
Here is a drag drop event sample :
private void tlAssemblies_DragDrop(object sender, DragEventArgs e)
{
if (sender == null)
return;
Point p = tlAssemblies.PointToClient(new Point(e.X, e.Y));
TreeListNode dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode;
TreeListNode targetNode = tlAssemblies.CalcHitInfo(p).Node;
if (targetNode == null)
{
return;
}
}
Not sure if it is possible but you may want to change the dragEnter code you have and simply use it in the drag event i.e.
e.Effect = DragDropEffects.Move;
If you are not leaving the same control you are dragging both to and fro, might as well show the drag movement.
Another thing you could do is on the treeView_MouseMove Event.
private void tlAssemblies_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && downHitInfo != null)
{
Size dragSize = SystemInformation.DragSize;
Rectangle dragRect = new Rectangle(new Point(downHitInfo.HitPoint.X - dragSize.Width / 2,
downHitInfo.HitPoint.Y - dragSize.Height / 2), dragSize);
if (!dragRect.Contains(new Point(e.X, e.Y)))
{
DataRow row = viewProduct.GetDataRow(downHitInfo.RowHandle);
if(row != null)
tlAssemblies.DoDragDrop(row, DragDropEffects.Move);
//viewProduct.GridControl.DoDragDrop(row, DragDropEffects.All);
downHitInfo = null;
DevExpress.Utils.DXMouseEventArgs.GetMouseArgs(e).Handled = true;
}
}
}
From your provided code, I cannot see that you have implemented the DragDrop event nor have set the AllowDrop property on the controls involved, which is needed along with the two other events in order to perform a drag and drop.
Here is sample snatched directly from MSDN, which uses two treeviews to move nodes in between. Add a couple of treeviews, add some root and child nodes, and wire up these events. Remember the AllowDrop property.
I have added a couple of Debug.WriteLine() to help with the debugging while testing this. Can be hard to do with breakpoints ;-)
NOTE: For brewity I have not supplied the event wiring code, nor the code for creating sample nodes. If needed this can be found in the referenced article. Otherwise add those using the property window.
Sample code:
private void treeView_ItemDrag(object sender, ItemDragEventArgs e)
{
Debug.WriteLine("ItemDrag fired!");
DoDragDrop(e.Item, DragDropEffects.Move);
}
private void treeView_DragEnter(object sender, DragEventArgs e)
{
Debug.WriteLine("TreeView DragEnter fired!");
e.Effect = DragDropEffects.Move;
}
private void treeView_DragDrop(object sender, DragEventArgs e)
{
Debug.WriteLine("TreeView DragDrop fired!");
TreeNode NewNode;
if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
{
Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
TreeNode DestinationNode = ((TreeView)sender).GetNodeAt(pt);
NewNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
if (DestinationNode.TreeView != NewNode.TreeView)
{
DestinationNode.Nodes.Add((TreeNode)NewNode.Clone());
DestinationNode.Expand();
//Remove Original Node
NewNode.Remove();
}
}
}

Enhanced features with Drag and Drop from Treeview to Textbox in WinForms

I have the following code that successfully drags and drops a treeview node to a textbox in a WFA:
private void _MyTreeView_ItemDrag(object sender, ItemDragEventArgs e)
{
DoDragDrop(e.Item.ToString(), DragDropEffects.Copy);
}
private void textBox1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
private void textBox1_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(System.String)))
{
textBox1.Text += (System.String)e.Data.GetData(typeof(System.String));
}
}
but I wanted to be able to do a few other things with the drag and drop.
(1) If the node I'm dragging to the textbox has a Text property value of 'MyTreeNode', then the value that appears in the textbox is 'TreeNode: MyTreeNode' and not 'MyTreeNode' i.e. it adds 'TreeNode: ' at the start. How can I fix this?
(2) Is there someway I can prevent all TreeNodes at the root level from being dragged and dropped?
(3) With the code I have above, when I drag and drop a treenode the treenode text is appended to the end of the text that is already in the textbox. Am I able to add a 'drop cursor'(i dont know what you would call it) and have the treenode dropped at the position its actually dropped i.e. the position of the cursor?
The TreeNode.ToString() method doesn't do what you hope it does, you'll have to use the TreeNode.Text property explicitly. Combining 1) and 2):
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e) {
var node = (TreeNode)e.Item;
if (node.Level > 0) {
DoDragDrop(node.Text, DragDropEffects.Copy);
}
}
Your DragEnter event handler is too permissive, you allow anything to be dragged to the TextBox. But you only can handle a string, so check for that:
private void textBox1_DragEnter(object sender, DragEventArgs e) {
if (e.Data.GetDataPresent(typeof(string))) e.Effect = DragDropEffects.Copy;
}
And you avoid the concatenation by using a simple assignment instead of +=
private void textBox1_DragDrop(object sender, DragEventArgs e) {
textBox1.Text = (string)e.Data.GetData(typeof(string));
}
Do consider a Label instead of a TextBox if the user should not edit the text himself.

Control hover color

Sorry, this is kinda beginner question but I'm not getting through.
I have a Windows Forms Applicaton with 4 panel controls on it. Now I want that the panels change their background when the user hovers with the mouse. I have tried following:
private void Panel1_MouseIn(object sender, EventArgs e)
{
panel1.BackColor = Color.Red;
}
private void Panel1_MouseOut(object sender, EventArgs e)
{
panel1.BackColor = Color.Blue;
}
That is working fine, but because I have 4 panels and not one I would have to add 6 more functions like this... The I tried to make one single function for all of them but event sender does not have an accessible BackColor property.
Is there a way to make one single MouseIn function for all panels?
If yes, how?
YOu should cast it:
private void Panel_MouseIn(object sender, EventArgs e)
{
Panel pan = sender as Panel;
pan.BackColor = Color.Red;
}
And use this one function for all 4 panels as event handler
You can cast your sender-object to a Panel like
Panel panel = (Panel)sender;
if(panel != null)
// Set the BackColor
You should first cast the sender object to Panel :
Panel panel = sender as Panel;
if (panel == null)
return;
panel.BackColor = Blue;
You could define an EventHandler for MouseIn and MouseOut and then
private void Panel1_MouseIn(object sender, EventArgs e)
{
Panel p = sender as Panel;
if(p == panel1){
//set color
}
else if(p == panel2){
//set color
}
...
}
The same for MouseOut
Inside mouse in and function remove all the code you have placed and write the one simple line of code below
And try it it will work
((Control)sender).BackColor = Color.Red;

MouseEnter & MouseLeave objectname

I want to add MouseOver and MouseLeave events to dynamical created panels in a flowLayoutPanel.
I added all panels in a list named "panels" and they are accessible with "panels[index]".
Now I want to dynamical add a MouseOver and MouseLeave event to each panel.
I thought it could be possible to get the panelname the Mouse is over and use just one method for each event and identify the panel the mouse is over with its panelname (panel.Name) but I found nothing in "sender".
Is there a way to do this?
My code:
//Method
private void PanelsMouseEnter(object sender, EventArgs e)
{
var panel = sender as Control;
foreach (Control control in this.fLpKoerper.Controls)
{
if (control.Name == panel.Name)
{
foreach (Panel panels in panelsKoerper)
{
if (panels.Name == panel.Name)
panels.BackColor = Color.DarkGray;
}
}
}
}
//Event
panelsKoerper[y].MouseEnter += PanelsMouseEnter;
var panel = sender as Control;
var thePanelName = panel.Name;
I believe you can generate one mouseover event for a control, copy that event method name and then paste it into another controls mouseover event box and that should work
So you would have this event
private void label1_MouseHover(object sender, EventArgs e)
{
//Code...
}
and then you could put 'label1_MouseHover' in any controls mouseover event

Categories

Resources