I'm trying to show some movable controls in silverlight. I've a grid, and dynamically I've to add some controls(I'm now trying with Thumb). And user can move those controls within the grid(in the space specified for the grid). I'm not saying about the Drag and Drop controls. Actually the controls are to move as a user press mouse left button on it and starts to drag it.
Please help. Thanks in advance.
What you describe is drag & drop only. You need to implement this.
handle the left mouse click, mouse move & left mouse up events for each of the controls you want to allow to be moved.
in the left mouse click event handler:
set a flag "drag_on" to True
in the mouse move event handler
check if "drag_on" is true, if false, return.
if drag_on is true, then set the control position (x, y) same as the mouse position.
you will get the mouse position from the parameter of the event handler
in the mouse up event, set drag_on to false. Also set the control position to that of mouse position.
Note:
you will need to transform the mouse position to the grid.
Get Absolute Position of element within the window in wpf
instead of setting the control position to the mouse position, you can also try setting the mouse position as the center of the control (homework for you).
Related
How can I get the current position of the mouse while dragging over an element with AllowDrop = false? I need the current mouse position because I want my adorner to follow my mouse while dragging.
The DragOver event doesn't work since it only fires when dragging above an element with AllowDrop = true.
EDIT:
Some Context: I have an ItemsControl and want to drag & drop the items to reorder them. Reordering works, however my adorner doesn't follow the mouse.
The questions says it all.
How can I move a control, say a PictureBox between multiple panels, or betwween a panel and a flow layout panel.
I'm aware I can drag and drop controls between multiple panels and such, however this is does not make the control visually movable between the containers. The mouse only changes to a diferent cursor and after you drag to the other control and release the mouse button the control appears on the other container. I require the control to be visually movable.
Can someone provide a simple example, so I can extract the idea to apply to my situation.
NOTE: Runtime of course.
Assuming you need it runtime:
You can save the control as bitmap using Control.SaveToBitmap method
Create cursor from image.
Set the current cursor which we created from control.
Once drag and drop completed reset the cursor.
Let's take a simple example of dragging a button around.
Suppose you have two types of container controls:
1) an X-Y layout
2) a flow layout (assume left to right)
When you click to drag the button, record the x-offset and y-offset from the click to the top left corner of the control. As well, record the index of the control within the Controls collection.
As the mouse moves, first check if the mouse has changed container controls.
If so, then remove the button from its current parent and add it to the new parent.
If the button is added to a flow control, then you need to calculate the new index. To do this, calculate the distance from the mouse to the closest edge of a bounding box of all other controls. Then if the mouse is left of the center of that control, insert to that control's index minus 1, otherwise insert to the right of that control (index + 1).
If the button is added to an X-Y layout, then the index doesn't matter that much. You can simple just set the button's location relative to the mouse plus the x-offset, and y-offset.
As the mouse is dragging, you will need to force the controls to refresh. I think calling Invalidate() on the container control should be sufficient.
This should give you the basic idea that you could use to start coding something.
I have a panel (panel2) inside another panel (panel1). I want to get mouse position of panel1, but when I move my mouse over panel2, the following code stops working.
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
label1.Text = "Offset: " + e.X + " x " + e.Y;
}
How can I get it to read the mouse arguments, even if the mouse is over panel2? Thanks!
EDIT: panel2 is located at center x=100, y=100 of panel1. if I move my mouse on panel2 left top corner it gives me coordinates for example 1x1, where I need to location on panel1 like 101x101
EDIT 2: I'm not trying to drag it, just read the coordinates of original panel (panel1) so I can calculate the offset for zooming the panel2. So I only need mousemove, nothing else. Thanks
If you only need to do this while a mouse button is being held down (for example, because you are tracking a drag and drop operation or a selection) then you can do the following:
In your MouseDown handler, call this.Capture = true;
Now your MouseMove handler will receive mouse move messages even when the mouse is over another control.
In your MouseUp handler, call this.Capture = false; - Note: If you forget to do this, your other controls in the same process will not receive any mouse messages.
Other than that, it's very tricky to get MouseMove messages from other controls without adding mouse handlers to those other controls.
The main thing about this.Capture is that you need a good time to set it to true and another good time to set it back to false. Generally, that's done in MouseDown and MouseUp as I described.
However, you could also convert the coords from Panel2-relative to Panel1-relative like so:
Convert from Panel2 coords to screen coords:
Point screenCoords = panel2.PointToScreen(mouseCoordInPanel2);
Then convert from screen coords to Panel1-relative coords:
Point mouseCoordInPanel1 = panel1.PointToClient(screenCoords);
To do this you would have to have a MouseMove handler in Panel2 where you did this conversion, and Panel2 would need a reference to Panel1 in order to call panel1.PointToClient()
You must also assign to the event of the other panel.
can't you put the event handler in panel2, then use the left/top properties of panel1 and panel2 to offset the mouse position within panel2 to get your desired location in panel1?
I also think that assigning an event to the second panel would be the best thing. When the mouse is on Panel 1, the coordinates would be provided directly; when it is on Panel 2, they would be converted by accounting for the relative positions between both panels (pretty straightforward: variation in X/Y positions; values which do not need to be hardcoded but updated at runtime).
I would like for the Width attribute to dynamically expand until it reaches 150, and after this, user should be able to expand it further via drag (MaxWidth won't allow this).
Width="150*"
has similar functionality, but in the opposite direction(minimum width and expand as needed). I want to have "expand as needed" and maximum expansion width.
Is there any way this can be done using XAML?
Put a line on the edge that you want the user to be able to drag. Set the Cursor property to "SizeWE" on that line so that the user knows he can drag it. From that line, handle the mouse down, mouse move, and mouse up events. In the MouseDown call CaptureMouse() from the line control and save the mouse position. On mouse move, get the new mouse position, calculate the change from the mouse down position, and increase the width of the control that you were constraining to 150 by the amount of the mouse move in the right direction and then reset the original mouse position to the current mouse position. On MouseUp, call ReleaseMouse() from the line control.
Hope this helps.
You can programmatically set the width depending on the size of the item. Bind the width to a GridLength and then you can let the user control it, or control it yourself up to 150
private GridLength _marquee1Width = new GridLength(150, GridUnitType.Pixel);
You can set this to GridUnitType.Pixel, GridUnitType.Auto, or GridUnitType.Star
There are some LibraryBarItems in a LibraryBar control, when I drag horizontally, all the LibraryBarItems move.
But I need to disable this drag event, this means that when I drag the LibraryBar horizontally, nothing happens.
p.s. Actually I want to implement the drop event in horizontal direction rather than in Vertical direction.
I'd suggest adding a transparent visual item over the top of the control to capture input and only allow it through if want it to get through.