I am trying to do a drag and drop in DataGrid View.
I have my DataGrid is defined inside a user control and the user control is hosted inside a tabcontrol
Now i am handling the following events
PreviewMouseLeftButtonDown="OnPreviewMouseLeftButtonDown"
PreviewMouseMove="OnPreviewMouseMove"
the handlers are defined as follows;
private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point mousePos = e.GetPosition(null);
Vector diff = startPoint - mousePos;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
// .......doing drag/drop work here.......
}
}
private void OnPreviewMouseMove(object sender, MouseEventArgs e)
{
startPoint = e.MouseDevice.GetPosition(null);
}
where startPoint is the internal variable of type Point
However always the vector diff inside OnPreviewMouseLeftButtonDown function is always zero.
to my surprise the same logic works inside a triewview control but not inside a the datagrid?
any help would be much appreciated
You always get a MouseMove event immediately before the LeftButtonDown event, so startPoint will always be the same as mousePos with your current code.
Swapping your handlers should fix it (code in PreviewLeftButtonDown should be in PreviewMouseMove, and startPoint should be set in PreviewLeftButtonDown).
Related
Just wanted to know if its possible to do it like winform? Where i can add a button to where i last click. I tried googling but dont think i found anything similar. Will the grid for WPF be an issue where i can place my button freely on click?
Idea is to click on the coordinate and then press the button to add an image/button.
Below is what i did so far, havent added the button function yet, just wanted to know if its possible to do it as i have done so for winform before.
public MainWindow()
{
InitializeComponent();
MainWindow.xCoord = -1;
MainWindow.yCoord = -1;
}
private void AddEvent_Click(object sender, EventArgs e)
{
if (MainWindow.xCoord < 0 || MainWindow.yCoord < 0)
{
MessageBox.Show("Please select a coordinate");
return;
}
}
public void MainWindow_Mouseup(object sender, MouseEventArgs e)
{
Point p = e.GetPosition(this);
textBox1.Text = "x-" + p.X + "y- " + p.Y;
MainWindow.xCoord = (int)p.X;
MainWindow.yCoord = (int)p.Y;
}
Yes you can do it, and you would need to use a Canvas to draw the button. This can be contained inside the Grid, but AFAIK the Canvas is the only way to have a sort of "Draw" function with UI Controls.
You will want to capture the MouseUp event within the Canvas and then add your button at the location you can retrieve in the Handler.
XAML:
<Grid>
<Canvas x:Name="ButtonCanvas" MouseUp="ButtonCanvas_MouseUp"/>
</Grid>
Code Behind:
private void ButtonCanvas_MouseUp(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(ButtonCanvas);
textBox1.Text = "x-" + p.X + "y- " + p.Y;
MainWindow.xCoord = (int)p.X;
MainWindow.yCoord = (int)p.Y;
}
Then just have a function that will create and add a Button at these coordinates (I will assume you have some sort of "Add Button to Canvas" Button):
private void AddButtonToCoord_Click(object sender, EventArgs e)
{
var button = new Button();
//--change button properties if you want--
//add to canvas
Canvas.Childen.Add(button);
//set Control coordinates within the canvas
Canvas.SetLeft(button, MainWindow.xCoord);
Canvas.SetTop(button, MainWindow.yCoord);
}
You can get fancier for your needs, like if you want the center of the button to be at the Coordinates, or if you want to prevent the Button from being drawn outside the canvas (like if the user click the very bottom right corner). But this should be enough to get a minimum working example.
How in GMapControl it is correct to handle pressing and moving Google maps using the mouse?
GMapControl gMap = new GMapControl();
gMap.MouseDown += GMap_MouseDown;
private void GMap_MouseDown(object sender, MouseEventArgs e)
{
gMap.MouseMove += GMap_MouseMove;
}
private void GMap_MouseMove(object sender, MouseEventArgs e)
{
base.OnMouseMove(e);
//gMap.Position = new PointLatLng(X, Y);
}
You don't need any code to move the map. The default is for the RIGHT mouse button to move the map, which I found rather awkward. To change to the LEFT mouse, use code like this in the Load() event of your Form:
gMap.DragButton = MouseButtons.Left;
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.
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?
I'd like to track the position of the Mouse cursor, in screen coordinates, anywhere on the screen. So even if the mouse cursor moves outside the bounds of the window, is there a way to get the position of the mouse cursor?
What I'm doing is trying to get a popup to follow the mouse cursor, even if it moves off the main window.
Here is a code snippet of what I've tried (and hasn't worked):
private void OnLoaded(object sender, RoutedEventArgs e)
{
bool gotcapture = this.CaptureMouse();
Mouse.AddLostMouseCaptureHandler(this, this.OnMouseLostCapture);
}
Point mouse_position_relative = Mouse.GetPosition(this);
Point mouse_screen_position = popup.PointToScreen(mouse_position_relative);
private void OnMouseLostCapture(object sender, MouseEventArgs e)
{
bool gotcapture = this.CaptureMouse();
this.textblock.Text = "lost capture.";
}
What exactly was your problem?
Wait! There is a way to position a Popup relative to the screen. see PlacementMode.AbsolutePoint
This showed little happy face flying around:
private Popup _popup;
public Window1()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
_popup = new Popup
{
Child = new TextBlock {Text = "=))", Background = Brushes.White},
Placement = PlacementMode.AbsolutePoint,
StaysOpen = true,
IsOpen = true
};
MouseMove += MouseMoveMethod;
CaptureMouse();
}
private void MouseMoveMethod(object sender, MouseEventArgs e)
{
var relativePosition = e.GetPosition(this);
var point= PointToScreen(relativePosition);
_popup.HorizontalOffset = point.X;
_popup.VerticalOffset = point.Y;
}
Never mind, I realized there is no way to position a Popup relative to the screen, only relative to the Visual which contains it.
There are a number of ways to get the screen coordinates of the mouse position outside of a WPF Window. Unfortunately, you'll need to add references to use either of them, but it is possible. You can find examples of them both in #FredrikHedblad's answer to the How do I get the current mouse screen coordinates in WPF? question. Coincidentally, that question was answered a few days before you asked this question and gave up within 21 minutes of asking.