Drag and Drop Windows Form - c#

private void calendarPlanner1_ItemClick(object sender, WeekPlannerItemEventArgs e)
{
DoDragDrop(calendarPlanner1.SelectedItem, DragDropEffects.Move);
}
private void calendarPlanner1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void calendarPlanner1_DragDrop(object sender, DragEventArgs e)
{
SRRepair repairDrag = new SRRepair();
var rows = calendarPlanner1.Rows;
var row = rows.ElementAt(calendarPlanner1.SelectedRowIndex);
row.Items.Add((WeekPlannerItem)e.Data.GetData(typeof(WeekPlannerItem)));
repairDrag = assignedRepairsList[assignedItemCollection.IndexOf(calendarPlanner1.SelectedItem)];
repairDrag.AssignedToUser = engineerList[calendarPlanner1.SelectedRowIndex];
repairDrag.Update();
}
The code above is what I have so far for drag and drop operation. It works ok until the third (drag drop) method. Basically what im trying to achieve is to drag an item between the names. I could get the index where I drag the item from using 'calendar.SelectedRowIndex' but the problem is getting the index of the destination or where i want to drag it to. Allows me to drag items but when i let go of the left button in the mouse it goes back where it came from. The calendar is an open source and i found it from codeproject and i am using and modifying it to add it in an existing desktop application.
Is there anyway or an event I could use to get the position of the mouse as soon I release the left button in the mouse?

I think, beside the drag and drop operation, you need to track your mouse move(or mouse enter) too, for getting the index of one element, drag'n'drop itself would not help(it get's the very first point), just track and identify the target by mouse move.
or simply, add mouse enter event for the object(controls) you want targeted by the drop, choose the target position via mouse enter, and complete the oration via drop, and it's better to remove mouse enter event when the drop operation completed, and add it by drop enter again.
hope I got your question true

I'm pretty sure in a desktop application you can get the mouse position without having to rely on passed mouseevent arguments.
control.mouseposition - http://msdn.microsoft.com/en-us/library/system.windows.forms.control.mouseposition.aspx
you should just be able to get the 'point' value through 'control'.mouseposition. where the control is likely the form you're working with.
Edit
As stated in the reference, the control.mouseposition method is identical to this.cursor.position.
cursor.position - http://msdn.microsoft.com/en-us/library/system.windows.forms.cursor.position.aspx
Additionally, you're going to want to locate the controls (plural), which are located at (or have ClientRectangle bounds that encompass) the cursor location point you capture..
control.GetChildAtPoint(Point).. which you may have to do recursively..
GetChildAtPoint - http://msdn.microsoft.com/en-us/library/ms158404.aspx

Related

Change the Panning button in Mapsui Control

I'm using Mapsui as a mapping control in a C# application.
By default, panning is initiated by dragging using the left mouse button.
I want to change this to the middle mouse button.
Does anyone know how to do this?
Mapsui has an object called PanMode, you can create an instance as follows, however, I believe it is just an enum for centering the map when panning:
Mapsui.UI.PanMode panMode = new PanMode();
EDIT:
Based on what 'pauldendulk's' answer (thank you for your support) I think I need to do something like this:
First, catch the middle button click and relay it to the mapsui left button method. Unfortuantly MapControlMouseLeftButtonDown() is a private method so this will not work.
MyMapControl.MouseDown += MapControlOnMouseButtonDown;
private void MapControlOnMouseButtonDown(object sender, MouseButtonEventArgs e)
{
if(e.ChangedButton == MouseButton.Middle)
{
Mapsui.UI.Wpf.MapControl.MapControlMouseLeftButtonDown(sender, e);
}
}
Secondly I need to stop the origional left button click from firing.
MyMapControl.MouseLeftButtonDown += null;
Again, this is not correct syntax as it throws an exception (cannot be null).
Does anyone know how to solve these issues?
Mapsui was not designed with this in mind. Perhaps it is possible if you assign an event handler to WPFs mouse down event, set the viewport in there. Also, you need to suppress the regular mouse event. Perhaps this is possible by setting the MouseLeftButtonDown event handler to null.
PanMode is not relevant. It is meant to limit the area where users can pan/zoom.

ListView click event not triggered when clicking on empty areas

I have a ListView control on my form. I have set its display mode to LargeImageList. I need to handle the items inside this control. So I have written code for its click event. But I see now that this event is not triggered when I click in an empty area inside it.
How can I make my ListView aware of the clicks on its area regardless.
To capture mouse clicks on the "white space" around the ListView items, you will need to use the MouseDown/MouseUp events.
This will also capture clicks to the items as well.
I've used the Global Mouse Hook for similar issues. You can use it to detect Mouse Clicks anywhere on the screen, then just check the click was within the listview control bounds.
Grab the code from Global Mouse Key Hook
IKeyboardMouseEvents m_GolbalHook = Hook.GlobalEvents();
m_GolbalHook.MouseClick += m_GolbalHook_MouseClick;
private void m_GolbalHook_MouseClick(object sender, MouseEventArgs e)
{
if (listView.Bounds.Contains(e.Location)) && (e.Button == System.Windows.Forms.MouseButtons.Left))
{
//Do Stuff
}
}

How to realize drag and drop pin like in windows 8 maps application

In windows 8(.1)'s maps application, it allows adding a pin by clicking and dragging a pin. When I click on the pin in the below bar, a new pin will be created and could be moved by mouse without releasing the mouse clicking. I am trying to realize the same manipulation but I don't know how.
I have tried to move a custom pin between two grids, but when the mouse moved from first grid to the second one, the focus on pin is lost, then the event OnMouseMove can't be entered.
I use C#/XAML and BingMap API.
Any help will be appreciate.
Finally, I found a solution, using UIElement.CapturePointer() would help to change to the MapView after clicked add a new pin. Like below. Hope that will help any one with the same problem.
private void PinPointerPressed(object sender, PointerRoutedEventArgs e)
{
if (BottomAppBar != null) BottomAppBar.IsOpen = false;
MapView.CapturePointer(e.Pointer);
...
}
Then, all registered pointer events of MapView could be triggered

WPF handle drag and drop as well as left click

I'm having some troubles getting DragDrop.DoDragDrop to work along nicely with a left click event.
My control has several links which can either be dragged around or left clicked to visit.
I currently subscribe to the preview mouse move event which is where i launch the drag and drop event if the left mouse button is pressed.
In another call back i handle the mouse left button down and up event to check for a click. Is there anyway to check if DragDrop actually had a drag drop event take place?
See this link drag drop in wpf explained end to end and scroll down a little to the section "Detecting Drag & Drop"
Code inserted here encase the blog goes missing...
From [http://msdn2.microsoft.com/en-us/library/aa289508(vs.71).aspx] Here is the sequence of events in a typical drag-and-drop operation:
Dragging is initiated by calling the DoDragDrop method for the source control.
The DoDragDrop method takes two parameters:
data, specifying the data to pass allowedEffects, specifying which operations (copying and/or moving) are allowed
A new DataObject object is automatically created.
This in turn raises the GiveFeedback event. In most cases you do not need to worry about the GiveFeedback event, but if you wanted to display a custom mouse pointer during the drag, this is where you would add your code.
Any control with its AllowDrop property set to True is a potential drop target. The AllowDrop property can be set in the Properties window at design time, or programmatically in the Form_Load event.
As the mouse passes over each control, the DragEnter event for that control is raised. The GetDataPresent method is used to make sure that the format of the data is appropriate to the target control, and the Effect property is used to display the appropriate mouse pointer.
If the user releases the mouse button over a valid drop target, the DragDrop event is raised. Code in the DragDrop event handler extracts the data from the DataObject object and displays it in the target control.
Detecting Drag & Drop
Before the DoDragDrop is called, we must detect a mouse Drag operation on the source... A mouse drag is usually a MouseLeftButtonDown + a MouseMove (before MouseLeftButton goes up).
So, our drag & drop source control needs to subscribe to these two events:
void Window1_Loaded(object sender, RoutedEventArgs e)
{
this.DragSource.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(DragSource_PreviewMouseLeftButtonDown);
this.DragSource.PreviewMouseMove += new MouseEventHandler(DragSource_PreviewMouseMove);
}
To prevent from starting a false drag & drop operation where the user accidentally drags, you can use
SystemParameters.MinimumHorizontalDragDistance and SystemParameters.MinimumVerticalDragDistance
One way to do this is on MouseLeftButtonDown, record the starting position and onMouseMove check if the mouse has moved far enough..
void DragSource_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && !IsDragging)
{
Point position = e.GetPosition(null);
if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
{
StartDrag(e);
}
}
}
void DragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(null);
}
Its a Drag .. now what?
The data! You need to find out what is under the mouse when dragging.
I will omit take the easy way out and assume that whoever is triggering the MouseMove is what I want to drag .. so look at MouseEventArgs.OriginalSource.. [or you could do some 2D HitTesting using VisualTreeHelper .. In Part3 of this write up will try to walk you through hit testing the listbox -which is the other common scenario I encounter-.
Once you have the object to drag, you will need to package what you are a sending into a DataObject that describes the data you are passing around.
DataObject is a wrapper to push generic data (identified with extensible formats) into drag/drop.. As long as both the source and destination understand the format, you will be set. As such, DataObject has a couple interesting methods:
SetData ( Type format, object data ) /// format is the "format" of the day you are passing ( e.g. Formats.Text, Formats.Image, etc.. ) you can pass any custom types.
GetDataPresent ( Type format ) /// is what the drop target will use to inquire and extract the data .. if it is a type it can handle, it will call GetData () and handle it ..
Not much interesting stuff here.. In the sample I just hard-coded my data to be of type string... this makes it easier to paste into external containers (for example Word, which you can use to test this part of the write-up). I do have to stress that drag & dropping should be about the data ...
Providing visual feedback during the drag & drop operation..
Before we call DoDragDrop () we have a few 'choices' to make around the feedback we want to provide and the 'scope' of the d&d.
Do we want a custom cursor to display while we are doing the Drag operation ? If we want a cursor, what should it be?
How far do we want to drag? within the app or across windows apps?
Simplest scenario: No custom cursor and we want it to drag across apps:
If you don't want a fancy cursor, you are done!! You can call DoDragDrop directly ...
private void StartDrag(MouseEventArgs e)
{
IsDragging = true;
DataObject data = new DataObject(System.Windows.DataFormats.Text.ToString(), "abcd");
DragDropEffects de = DragDrop.DoDragDrop(this.DragSource, data, DragDropEffects.Move);
IsDragging = false;
}
Note: this code allows you to drag & drop across processes, it uses the default operating system feedback ( e.g. + for copy)..
there are Drag Over/ Enter / Leave Attached events
you can subscribe methods to these (or one) events on your dragged UIElement and see if the Dragging occurs .

tree view selected item

i have tree node in my app that was created by dynamically.when right click what ever node i want to get node text that was clicked.i use that value for my futher processing .i have tried using selected node property and it not work some times.
thanks in advance
Code:
public void CmsAppList_RightClicked(object sender, MouseEventArgs e)
{
AddUser _addUser = new AddUser(this.Text); // i want to get that value to this constructor
_addUser.ShowDialog();
}
This is a known issue with most of the list controls, to work around this add an event handler to treeview's MouseDown event and set the selected node on right click, as follows. My treeview name is treeView1 just change accordingly.
private void treeView1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
treeView1.SelectedNode = treeView1.GetNodeAt(e.Location);
}
Now selectednode should always reflect the node you clicked last.
Edit (To correct This is known issue and saying This is by design and right)
I've been thinking about updating this answer, becuase I realized what I said about this being known issue is wrong on multiple list controls.
Let's say it is known issue and we fix it then right click and left click have similar behavior except that right click does everything(that left click does) and then opens up context menu. This sounds fine till we carefully look at context menu(right click) nature, lets assume you select 15 files and you click (left) on 16th file the selection is lost :) so you select 15 files and the right click the context menu and operations are applicable to all the 15 files selected.
This is the reason right click shouldn't change the selection in any view (in listbox or treeview or explorer widnow). If it does then multiselect and control+select features would break, and ultimately special meaning for right click being context specific actions would be lost. That is the reason the right click wouldn't select the clicked node and that is right. The code provided above is for for specific purpose of enabling right click selection. And consider the UX impact with this kind of work around or aberrant behavior.

Categories