I have a ListBox that slides its ScrollViewer horizontally by dragging with the left mouse button pressed.
private ScrollViewer scrollViewer;
private Point scrollMousePoint = new Point();
private double horizontalOffset = 1;
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Border border = (Border)VisualTreeHelper.GetChild(myListBox, 0);
scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
// This works
}
private void myListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
scrollMousePoint = e.GetPosition(scrollViewer);
horizontalOffset = scrollViewer.HorizontalOffset;
scrollViewer.CaptureMouse();
// This works
}
private void myListBox_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (scrollViewer.IsMouseCaptured)
scrollViewer.ScrollToHorizontalOffset(horizontalOffset + (scrollMousePoint.X - e.GetPosition(scrollViewer).X));
// This works
}
private void myListBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
scrollViewer.ReleaseMouseCapture();
if (scrollMousePoint == Mouse.GetPosition(scrollViewer))
{
// Click
// Here I want to get and select the ListBoxItem that was pressed.
}
}
I want to get and select the ListBoxItem that was clicked.
To determine if it is a click without movement, I compare if the position saved in the PreviewMouseLeftButtonDown and in PreviewMouseLeftButtonUp events are the same.
Here you go:
private void myListBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
scrollViewer.ReleaseMouseCapture();
if (scrollMousePoint == Mouse.GetPosition(scrollViewer))
{
ListBox listBox = sender as ListBox;
if (listBox != null)
{
var element = VisualTreeHelper.HitTest(listBox, scrollMousePoint).VisualHit;
if (element.GetType() != typeof(ScrollViewer))
{
while (element.GetType() != typeof(ListBoxItem))
element = VisualTreeHelper.GetParent(element);
(element as ListBoxItem).IsSelected = true;
}
}
}
}
Related
I have a Listview with Drag and Drop codes working well.
However, after i add groups to it, the Drag and Drop codes are run, but the outcome is not what the codes used to behave.
Dropped items were only added to the tail of its group.
Why? and how to get it work properly with groups?
The Drag and Drop procedures are given herebelow:
private void lvQ_DragDrop(object sender, DragEventArgs e)
{
int targetIndex = lvQ.InsertionMark.Index;
if (targetIndex == -1)
return;
if (lvQ.InsertionMark.AppearsAfterItem)
targetIndex++;
ListViewItem draggedItem = (ListViewItem)e.Data.GetData(typeof(ListViewItem));
if (targetIndex == 0 && lvQ.Items.OfType<ListViewItem>().FirstOrDefault()?.SubItems[1].Text == "FF")
{
lvQ.InsertionMark.Index = -1;
}
else
{
lvQ.BeginUpdate();
lvQ.Items.Insert(targetIndex, (ListViewItem)draggedItem.Clone());
lvQ.Items.Remove(draggedItem);
lvQ.EndUpdate();
ShowTXFrameStr();
}
}
private void lvQ_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.AllowedEffect;
}
private void lvQ_DragLeave(object sender, EventArgs e)
{
lvQ.InsertionMark.Index = -1;
}
private void lvQ_DragOver(object sender, DragEventArgs e)
{
Point ptScreen = new(e.X, e.Y);
Point pt = lvQ.PointToClient(ptScreen);
int targetIndex = lvQ.InsertionMark.NearestIndex(pt);
if (targetIndex > -1)
{
Rectangle itemBounds = lvQ.GetItemRect(targetIndex);
lvQ.InsertionMark.AppearsAfterItem = pt.Y > itemBounds.Top + (itemBounds.Height / 2);
}
lvQ.InsertionMark.Index = targetIndex;
}
private void lvQ_ItemDrag(object sender, ItemDragEventArgs e)
{
lvQ.DoDragDrop(e.Item, DragDropEffects.Move);
}
I'm trying to drag a rectangle element called "Rec" using the mouse. I can drag it to the location I want and the rectangle stays there, but when I try to drag it again it returns to the first location and the dragging starts from there. I want to drag it from where I left it the last time. I just don't get where the problem is.
I have one Canvas only and all my elements are inside it, the Canvas is called the "maincanvas". I use the following very simple events to for dragging.
Point originalPosition = new Point(0, 0);
private void Rec_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
Point CurrPosition = Mouse.GetPosition(MainCanvas);
Canvas.SetLeft(e.Source as UIElement, -( originalPosition.X - CurrPosition.X));
Canvas.SetTop(e.Source as UIElement, -(originalPosition.Y - CurrPosition.Y));
}
private void Rec_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
UIElement a = e.Source as UIElement;
a.CaptureMouse();
Rec.MouseMove += Rec_MouseMove;
originalPosition = Mouse.GetPosition(MainCanvas);
}
private void Rec_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Rec.MouseMove -= Rec_MouseMove;
UIElement a = e.Source as UIElement;
a.ReleaseMouseCapture();
originalPosition = new Point(0, 0);
}
I hope you guys could help me.
You should handle the mouse events on the Canvas like this:
<Canvas MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove">
...
</Canvas>
In the mouse down handler you would get the element that should be dragged by the MouseButtonEventArgs's OriginalSource property:
private UIElement draggedElement;
private Point lastMousePos;
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource != sender)
{
IInputElement canvas = (IInputElement)sender;
canvas.CaptureMouse();
draggedElement = e.OriginalSource as UIElement;
lastMousePos = e.GetPosition(canvas);
}
}
private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
((IInputElement)sender).ReleaseMouseCapture();
draggedElement = null;
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (draggedElement != null)
{
var p = e.GetPosition((IInputElement)sender);
var dx = p.X - lastMousePos.X;
var dy = p.Y - lastMousePos.Y;
lastMousePos = p;
Canvas.SetLeft(draggedElement, Canvas.GetLeft(draggedElement) + dx);
Canvas.SetTop(draggedElement, Canvas.GetTop(draggedElement) + dy);
}
}
If one of my buttons is selected and the mouse wheel is activated then its size should change according to the mouse wheel action.
If the mouse wheel goes up the size of my button should increase by 2.
If the mouse wheel goes down the size of my button should decrease by 2.
I'm trying something like this:
private void Form1_Load(object sender, EventArgs e)
{
foreach (Control c in this.Controls)
{
btn = c as Button;
{
if (btn == null)
continue;
c.MouseWheel += c_MouseWheel;
}
}
}
private void c_MouseWheel(object sender, MouseEventArgs e)
{
TabControl tabControl = sender as TabControl;
if (tabControl != null)
{
if (e.Delta < 0)
{
tabControl.Size = new Size(-2, -2);
}
else
{
tabControl.Size = new Size(+2, +2);
}
Unfortunately my code does not work.
This is now solved:
private void Form1_Load(object sender, EventArgs e)
{
foreach (Control c in this.Controls)
{
btn = c as Button;
{
if (btn == null)
continue;
c.MouseWheel += c_MouseWheel;
}
}
}
private void c_MouseWheel(object sender, MouseEventArgs e)
{
ss = sender as Button;
TabControl tabControl = sender as TabControl;
int y = ss.Size.Width;
int x = ss.Size.Height;
if (e.Delta < 0)
{
ss.Size = new Size(y+2, x+2);
}
else
{
ss.Size = new Size(y-2, x-2);
}
I have been using code that others online have supplied but for some reason it won't let me drag items from the datagridview to the textbox. I highlight a row in the dataGridView and try to drag it to the textbox but nothing happens. I have also enabled the drop property for the textBox but still no difference. Here's the code that I am using:
private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
DataGridView.HitTestInfo info = dataGridView1.HitTest(e.X, e.Y);
if (info.RowIndex >= 0)
{
if (info.RowIndex >= 0 && info.ColumnIndex >= 0)
{
string text = (String)
dataGridView1.Rows[info.RowIndex].Cells[info.ColumnIndex].Value;
if (text != null)
dataGridView1.DoDragDrop(text, 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));
}
}
private void textBox1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
Here is a small sample that i have done to give you an idea on how to do this... works perfectly for me. I used WinForms here. If WPF, there may be some more events you will need to register to in order for the drag+drop to register...
Note that you will want to add more code here and there to perform what you really want to do when you drag an item from one control to the other.
public partial class Form1 : Form
{
private Rectangle dragBoxFromMouseDown;
private int rowIndexFromMouseDown;
private int rowIndexOfItemUnderMouseToDrop;
private DataGridViewRow draggedrow;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
List<StringValue> Items = new List<StringValue>() { new StringValue("1"), new StringValue("2"), new StringValue("3"), new StringValue("4"), new StringValue("5"), new StringValue("6") };
this.dataGridView1.DataSource = Items;
}
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
// If the mouse moves outside the rectangle, start the drag.
if (dragBoxFromMouseDown != Rectangle.Empty &&
!dragBoxFromMouseDown.Contains(e.X, e.Y))
{
// Proceed with the drag and drop, passing in the list item.
DragDropEffects dropEffect = dataGridView1.DoDragDrop(
dataGridView1.Rows[rowIndexFromMouseDown],
DragDropEffects.Move);
}
}
}
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
// Get the index of the item the mouse is below.
rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;
if (rowIndexFromMouseDown != -1)
{
// Remember the point where the mouse down occurred.
// The DragSize indicates the size that the mouse can move
// before a drag event should be started.
Size dragSize = SystemInformation.DragSize;
// Create a rectangle using the DragSize, with the mouse position being
// at the center of the rectangle.
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
e.Y - (dragSize.Height / 2)),
dragSize);
this.draggedrow = this.dataGridView1.CurrentRow;
}
else
// Reset the rectangle if the mouse is not over an item in the ListBox.
dragBoxFromMouseDown = Rectangle.Empty;
}
private void dataGridView1_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void textBox1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void textBox1_DragDrop(object sender, DragEventArgs e)
{
this.textBox1.Text = (string)this.draggedrow.Cells["Value"].Value;
}
}
public class StringValue
{
public StringValue(string s)
{
_value = s;
}
public string Value { get { return _value; } set { _value = value; } }
string _value;
}
can't you use DataGridViewCellMouseEventArgs e instead of hittest for getting row index in dataGridView1_CellMouseDown. below is your code modified hope this helps
private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (e.RowIndex >= 0)
{
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
{
string text = (String)
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if (text != null)
dataGridView1.DoDragDrop(text, 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));
}
}
private void textBox1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
Having trouble with something here which I'm hoping is actually simple.
I have a custom UserControl in WPF which allows me to display an image. When the program is running a user can add this UserControl as many times as they like to a canvas. In effect a simple image viewer where they can add and move images about.
I would like to be able to right click these images open a contextMenu and then choose send backward of bring forward and the images would then change z order depending which menu choice was clicked.
I have the user control set up with the contextMenu so I just need to know the code for changing the z order of this userControl...
Any help is much appreciated :)
namespace StoryboardTool
{
/// <summary>
/// Interaction logic for CustomImage.xaml
/// </summary>
public partial class CustomImage : UserControl
{
private Point mouseClick;
private double canvasLeft;
private double canvasTop;
public CustomImage()
{
InitializeComponent();
cusImageControl.SetValue(Canvas.LeftProperty, 0.0);
cusImageControl.SetValue(Canvas.TopProperty, 0.0);
}
public void chooseImage()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Choose Image to Add";
if (ofd.ShowDialog() == true)
{
BitmapImage bImage = new BitmapImage();
bImage.BeginInit();
bImage.UriSource = new Uri(ofd.FileName);
bImage.EndInit();
image.Width = bImage.Width;
image.Height = bImage.Height;
image.Source = bImage;
image.Stretch = Stretch.Fill;
}
}
private void cusImageControl_LostMouseCapture(object sender, MouseEventArgs e)
{
((CustomImage)sender).ReleaseMouseCapture();
}
private void cusImageControl_MouseUp(object sender, MouseButtonEventArgs e)
{
((CustomImage)sender).ReleaseMouseCapture();
cusImageControl.Cursor = Cursors.Arrow;
}
private void cusImageControl_MouseMove(object sender, MouseEventArgs e)
{
if ((((CustomImage)sender).IsMouseCaptured) && (cusImageControl.Cursor == Cursors.SizeAll))
{
Point mouseCurrent = e.GetPosition(null);
double Left = mouseCurrent.X - mouseClick.X;
double Top = mouseCurrent.Y - mouseClick.Y;
mouseClick = e.GetPosition(null);
((CustomImage)sender).SetValue(Canvas.LeftProperty, canvasLeft + Left);
((CustomImage)sender).SetValue(Canvas.TopProperty, canvasTop + Top);
canvasLeft = Canvas.GetLeft(((CustomImage)sender));
canvasTop = Canvas.GetTop(((CustomImage)sender));
}
else if ((((CustomImage)sender).IsMouseCaptured) && (cusImageControl.Cursor == Cursors.SizeNWSE))
{
/*Point mouseCurrent = e.GetPosition(null);
cusImageControl.Height = cusImageControl.canvasTop + mouseClick.Y;
cusImageControl.Width = cusImageControl.canvasLeft + mouseClick.X;
mouseClick = e.GetPosition(null);*/
}
}
private void cusImageControl_MouseDown(object sender, MouseButtonEventArgs e)
{
mouseClick = e.GetPosition(null);
canvasLeft = Canvas.GetLeft(((CustomImage)sender));
canvasTop = Canvas.GetTop(((CustomImage)sender));
((CustomImage)sender).CaptureMouse();
}
private void ContextMenuBringForward_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Bring Forward");
}
private void ContextMenuSendBackward_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Send Backward");
}
private void ContextMenuMove_Click(object sender, RoutedEventArgs e)
{
cusImageControl.Cursor = Cursors.SizeAll;
}
private void ContextMenuResize_Click(object sender, RoutedEventArgs e)
{
cusImageControl.Cursor = Cursors.SizeNWSE;
}
}
}
See Panel attached property Canvas.SetZIndex. Change z-Index of all elements to 0, and z-Index of your right-clicked control to 1.
void mouseUp(object sender, MouseButtonEventArgs e)
{
foreach (var child in yourCanvas.Children) Canvas.SetZIndex(child, 0);
Canvas.SetZIndex((UIElement)sender, 1);
}
The following code works where selected is defined as my UserControl and set in the mouseDown event.
private void ContextMenuSendBackward_Click(object sender, RoutedEventArgs e)
{
Canvas parent = (Canvas)LogicalTreeHelper.GetParent(this);
foreach (var child in parent.Children)
{
Canvas.SetZIndex((UIElement)child, 0);
}
Canvas.SetZIndex(selected, 1);
}
Thanks to voo for all his help.