Hallo,
ich habe für meinen TreeView Drag&Drop implementiert, um die Knoten zu sortieren.
Die DoDragDrop()-Methode rufe ich im MouseDown-Eventhandler auf.
Funktioniert auch super.
Das Problem tritt erst auf, wenn ich Knoten des TreeVies auf- oder zuklappe (Expand/Collapse). In diesem Falle lande ich im gleichen Eventhandler. Die nachfolgende DragDrop-Eventbehandlung hat dann unangenehme Nebeneffekte.
Wie kann ich erkennen, dass hier nicht einfach MouseDown, sondern Expand/Collapse stattfindet? Ich habe es bereits mittels der BeforeExpand/BeforeCollape-Ereignisse versucht, leider werden diese aber erst nach dem MouseDown geworfen.
Danke, Christel
Es ist schlimm, eine Ausnahme zu sein, aber noch schlimmer, keine zu sein.
Hallo Christel,
Warum benutzt du das MouseDown-Event und nicht die DragDrop, DragEnter, DragLeave und DragOver Events?
MfG
Rabban
Hallo Christel,
genau dafür gibt es dich die Events: DragDrop, DragEnter, DragLeave und DragOver.
Weshalb also per Click-Event das "Draggen" starten?
Im DragOver
kann man entscheiden, ob überhaupt ein Droppen erlaubt sein soll und ein entsprechendes Icon anzeigen (e.Effect = DragDropEffects.Move;).
Im DragDrop
dann behandeln, wenn die Node losgelassen wurde.
PS: Zu spät, dafür aber mehr Infos 😉
DragDrop, und DragEnter verwende ich bereits.
Im MouseDown rufe ich DoDragDrop() auf.
Im DragEnter entscheide ich, ob Drop erlaubt ist.
Im DragDrop führe ich die Sortierung durch.
Es sit mir klar, dass das DoDragDrop() im MouseDouwn das Problem ist.
Aber wohin damit?
Ins DragLeave?
Werde ich mal nachlesen.
Danke, Christel
Es ist schlimm, eine Ausnahme zu sein, aber noch schlimmer, keine zu sein.
Hallo Christel,
du kannst mittels HitTest() und Abfrage der Location überpüfen, wo der Mauszeiger steht, ob (bzw. bevor) du DoDragDrop() aufrufst.
P.S. Rabban und trib: diese Events werden aber erst ausgeführt, wenn man auch irgendwo vorher DoDragDrop() aufgerufen hat, und das macht man passenderweise im OnMouseDown.
Stimmt, die Drag... Ereignisse kommen nach dem DoDragDrop()-Aufruf.
Der MouseDown-Ereignishandler ist also doch die richtige Stelle.
Die Mouseposition auszuwerten hatte ich auch schon in Erwägung gezogen. Ich müsste also rekursiv die Verschachtelungstiefe des Knotens bestimmen, daraus die zugehörige Expand/Collapse-Clickposition berechnen und mit der aktuellen Position vergleichen?
Kann ich so probieren.
Danke, Christel
Es ist schlimm, eine Ausnahme zu sein, aber noch schlimmer, keine zu sein.
Ich dachte eher daran direkt zu vergleichen:
var info = treeView.Hittest(e.X, e.Y);
if (!info.Location.HasFlag(TreeViewHitTestLocations.PlusMinus))
{
DoDragDrop(...);
}
Also nur das Draggen zu starten, wenn man nicht auf das Plus- oder Minus-Icon geklickt hat.
P.S. Mittels info.Node erhältst du auch gleich den zugehörigen Knoten, den du dann der DoDragDrop()-Methode als Parameter übergeben kannst (sofern != null).
Coole Sache, funzt super.
Ich danke Dir, Christel
Es ist schlimm, eine Ausnahme zu sein, aber noch schlimmer, keine zu sein.
P.S. Rabban und trib: diese Events werden aber erst ausgeführt, wenn man auch irgendwo vorher DoDragDrop() aufgerufen hat, und das macht man passenderweise im OnMouseDown.
Dafür würde ich dann das ItemDrag-Event nutzen. Dafür isses da 😃
MouseClick nutze ich nur um z.B. Cut, Copy & Paste als ToolStripMenue anzuzeigen und dynamisch die MenuItems anzuzeigen. Ggf. noch um Zusatzinformationen unter dem TreeView einzublenden.
ItemDrag-Event ... wieder was gelernt, Christel
Es ist schlimm, eine Ausnahme zu sein, aber noch schlimmer, keine zu sein.
Drag startet man am sinnvollsten erst dann, wenn die "gedrückte Maus" ein paar Pixel bewegt wird. Dann hat man kein Problem mit einem einfachen Klick, bei dem man normalerweise keine Bewegung macht.
Also beim MouseDown den Klickpunkt merken. Im MouseMove prüfen wie weit der Cursor vom Klickpunkt weg ist und dann erst DragDrop starten. Im MouseUp den Klickpunkt löschen, damit ein folgender MouseMove nicht mehr rechnet.
Hallo allerseits,
ich habe dafür folgende Konstruktion, die auf die SystemParameters.MinimumHorizontalDragDistance und SystemParameters.MinimumVerticalDragDistance zurückgreift:
void OnMouseDown(object sender, MouseButtonEventArgs e)
{
dragSource = null;
dragSourceData = null;
if (e.ChangedButton == MouseButton.Left)
{
dragSource = sender as FrameworkElement;
mouseClickPosition = e.GetPosition(dragSource);
if (dragSource != null)
{
dragSourceData = dragSource.DataContext as IViewModel;
}
}
}
void OnMouseMove(object sender, MouseEventArgs e)
{
// Can Drag?
if (dragSourceData == null)
return;
if (e.LeftButton == MouseButtonState.Pressed)
{
Point mousePosition = e.GetPosition(dragSource);
if ((Math.Abs(mousePosition.X - mouseClickPosition.X) > SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(mousePosition.Y - mouseClickPosition.Y) > SystemParameters.MinimumVerticalDragDistance))
{
DataObject dragData = new DataObject(DataFormatName, dragSourceData);
// Start dragging
DragDropEffects finalDropEffect = DragDrop.DoDragDrop(dragSource, dragData, DragDropEffects.Move | DragDropEffects.Copy);
// Reset
dragSource = null;
dragSourceData = null;
}
}
}
Christian
Weeks of programming can save you hours of planning