| |
VB.NET - Ein- und UmsteigerWPF: TabItem Drag&Drop und RenderTransform | | | Autor: Maas | Datum: 27.03.10 13:02 |
| Hi Leute,
ich versuche gerade mir ein TabControl zu basteln, wo ich die TabItems per Drag&Drop beliebig verschieben kann. Das klappt auch wunderbar. Jetzt will ich, dass schon während des Ziehens der TabItem sich in seine zukünftige Position einfügt. Das ist auch kein Problem mit der Ausnahme, dass ich mit der Transformation nicht klar komme und der Item immer hin und her springt, wenn ich die Position wechsle.
Ich denke mal, dass ich die Variable mStartPosition falsch setze. Sinn ist es, wenn ich über den linken oder rechten Tab rüber gehe, dass sich mein Tab den ich mit der Maus festhalte, dazwischen einfügt und danach der D&D Vorgang sofort neu begonnen wird. Für den User sieht es so aus, als wenn er den Tab immer in der Hand hält und der Tab sich zwischen den alten Tabs neuen Platz schafft.
Ich hoffe ihr könnt mir helfen!
Danke im Voraus.
Maas
P.S.: Code folgt danach | |
Re: WPF: TabItem Drag&Drop und RenderTransform | | | Autor: Maas | Datum: 27.03.10 13:03 |
| MyTabControl:
Public Class MyTabControl
Inherits TabControl
Private mIsMoving As Boolean = False
Private mMovingTabItem, mLastTab As TabItem
Private mStartPoint As Point
Private mOldIndex As Integer = -1
Private Sub MyBase_PreviewMouseDown(ByVal sender As Object, ByVal e As _
MouseEventArgs) Handles MyBase.PreviewMouseLeftButtonDown
Dim ti = TryCast(e.Source, TabItem)
If ti IsNot Nothing AndAlso e.LeftButton = MouseButtonState.Pressed Then
AddHandler Me.MouseMove, AddressOf MyBase_MouseMove
AddHandler Me.MouseLeftButtonUp, AddressOf _
MyBase_PreviewMouseLeftButtonUp
mStartPoint = e.GetPosition(Me)
mMovingTabItem = ti
mLastTab = mMovingTabItem
End If
End Sub
Private Sub MyBase_MouseMove(ByVal sender As Object, ByVal e As _
MouseEventArgs)
Dim actualPoint As Point = e.GetPosition(Me)
If mIsMoving = False Then
If Math.Abs(actualPoint.X - mStartPoint.X) > 5 Then
Me.Cursor = Cursors.Hand
mMovingTabItem.IsHitTestVisible = False
mMovingTabItem.RenderTransformOrigin = New Point(0.5, 0.5)
mMovingTabItem.RenderTransform = New TranslateTransform(0, 0)
Panel.SetZIndex(mMovingTabItem, 1)
mIsMoving = True
Me.CaptureMouse()
End If
Else
Dim tabMouseOver As TabItem = FindTabItem(New Point(actualPoint.X, _
mLastTab.ActualHeight / 2))
Me.Cursor = Cursors.Hand
Dim p As Point = e.GetPosition(mLastTab)
Dim perc As Double
Dim targetIndex As Integer
perc = p.X / mLastTab.ActualWidth
If perc < 0.5 Then
targetIndex = Me.Items.IndexOf(mLastTab)
Else
targetIndex = Me.Items.IndexOf(mLastTab) + 1
End If
If tabMouseOver IsNot Nothing Then
If mOldIndex <> targetIndex Then
mOldIndex = targetIndex
'Ohne Folgendes ist es kein Problem
SetTabItemIndex(e.GetPosition(mLastTab))
mStartPoint = actualPoint
'Anscheinend der falsche StartPoint
End If
mLastTab = tabMouseOver
End If
mMovingTabItem.Opacity = 0.5
Dim xform As TranslateTransform = TryCast( _
mMovingTabItem.RenderTransform, TranslateTransform)
If xform IsNot Nothing Then xform.X = actualPoint.X - mStartPoint.X
End If
End Sub
Private Sub MyBase_PreviewMouseLeftButtonUp(ByVal sender As Object, ByVal e _
As MouseButtonEventArgs)
RemoveHandler Me.MouseMove, AddressOf MyBase_MouseMove
RemoveHandler Me.MouseLeftButtonUp, AddressOf _
MyBase_PreviewMouseLeftButtonUp
Me.ReleaseMouseCapture()
If mIsMoving Then
Me.Cursor = Cursors.Arrow
mIsMoving = False
mMovingTabItem.IsHitTestVisible = True
mMovingTabItem.RenderTransform = Nothing
Panel.SetZIndex(mMovingTabItem, 0)
SetTabItemIndex(e.GetPosition(mLastTab))
End If
mOldIndex = -1
mLastTab = Nothing
mMovingTabItem = Nothing
End Sub
Private Sub SetTabItemIndex(ByVal p As Point)
If mLastTab IsNot Nothing Then
Dim perc, oldIndex As Double
Dim targetIndex As Integer
perc = p.X / mLastTab.ActualWidth
If perc < 0.5 Then
targetIndex = Me.Items.IndexOf(mLastTab)
Else
targetIndex = Me.Items.IndexOf(mLastTab) + 1
End If
oldIndex = Items.IndexOf(mMovingTabItem)
If oldIndex < targetIndex Then targetIndex -= 1
Me.Items.Remove(mMovingTabItem)
Me.Items.Insert(targetIndex, mMovingTabItem)
mMovingTabItem.Opacity = 1
mMovingTabItem.Focus()
End If
End Sub
Private Function FindTabItem(ByVal pt As Point) As TabItem
Dim fe As FrameworkElement = TryCast(InputHitTest(pt), FrameworkElement)
While fe IsNot Nothing AndAlso Not TypeOf fe Is TabItem
fe = TryCast(VisualTreeHelper.GetParent(fe), FrameworkElement)
End While
Return TryCast(fe, TabItem)
End Function
End Class | |
Re: Lösung | | | Autor: Maas | Datum: 29.03.10 13:31 |
| Ich hatte den falschen Ansatz. Anstatt den TabItem jedesmal zu setzen und seine Transformation zu ändern, hat jetzt jeder TabItem eine Transform bis zum loslassen des moving tab.
Das Ganze funktioniert für verschieden große Tabs und auch alle TabStripPlacements.
Public Class MyTabControl
Inherits TabControl
Private mIsMoving As Boolean = False
Private mMovingTabItem, mLastTab As TabItem
Private mStartPoint As Point
Private mOldIndex As Integer = -1
Public ReadOnly Property HorizontalOrientation() As Boolean
Get
Return Me.TabStripPlacement = Dock.Top Or Me.TabStripPlacement = _
Dock.Bottom
End Get
End Property
Private Sub MyBase_PreviewMouseDown(ByVal sender As Object, ByVal e As _
MouseEventArgs) Handles MyBase.PreviewMouseLeftButtonDown
Dim ti = TryCast(e.Source, TabItem)
If ti IsNot Nothing AndAlso e.LeftButton = MouseButtonState.Pressed Then
AddHandler Me.MouseMove, AddressOf MyBase_MouseMove
AddHandler Me.MouseLeftButtonUp, AddressOf _
MyBase_PreviewMouseLeftButtonUp
mStartPoint = e.GetPosition(Me)
mMovingTabItem = ti
mLastTab = mMovingTabItem
End If
End Sub
Private Sub MyBase_PreviewMouseLeftButtonUp(ByVal sender As Object, ByVal e _
As MouseButtonEventArgs)
RemoveHandler Me.MouseMove, AddressOf MyBase_MouseMove
RemoveHandler Me.MouseLeftButtonUp, AddressOf _
MyBase_PreviewMouseLeftButtonUp
Me.ReleaseMouseCapture()
If mIsMoving Then
Dim p As Point = e.GetPosition(mLastTab)
Dim perc, oldIndex As Double
Dim targetIndex As Integer
If Me.HorizontalOrientation Then : perc = p.X / mLastTab.ActualWidth
Else : perc = p.Y / mLastTab.ActualHeight
End If
If perc < 0.5 Then : targetIndex = Me.Items.IndexOf(mLastTab)
Else : targetIndex = Me.Items.IndexOf(mLastTab) + 1
End If
oldIndex = Items.IndexOf(mMovingTabItem)
If oldIndex < targetIndex Then targetIndex -= 1
Me.Items.Remove(mMovingTabItem)
Me.Items.Insert(targetIndex, mMovingTabItem)
Me.Cursor = Cursors.Arrow
For Each tab As TabItem In Me.Items
tab.RenderTransform = Nothing
Next
mMovingTabItem.IsHitTestVisible = True
mMovingTabItem.Opacity = 1
Panel.SetZIndex(mMovingTabItem, 0)
mMovingTabItem.Focus()
End If
mIsMoving = False
mOldIndex = -1
mLastTab = Nothing
mMovingTabItem = Nothing
End Sub
'geht noch weiter ... Maas
Beitrag wurde zuletzt am 29.03.10 um 13:32:45 editiert. | |
Re: Lösung | | | Autor: Maas | Datum: 29.03.10 13:33 |
| Private Sub MyBase_MouseMove(ByVal sender As Object, ByVal e As _
MouseEventArgs)
Dim actualPoint As Point = e.GetPosition(Me)
If mIsMoving = False Then
Dim actualValue, startValue As Double
If Me.HorizontalOrientation Then
actualValue = actualPoint.X
startValue = mStartPoint.X
Else
actualValue = actualPoint.Y
startValue = mStartPoint.Y
End If
If Math.Abs(actualValue - startValue) > 5 Then
Me.Cursor = Cursors.Hand
For Each tab As TabItem In Me.Items
tab.RenderTransformOrigin = New Point(0.5, 0.5)
tab.RenderTransform = New TranslateTransform(0, 0)
Next
mMovingTabItem.IsHitTestVisible = False
Panel.SetZIndex(mMovingTabItem, 1)
mIsMoving = True
Me.CaptureMouse()
End If
Else
Me.Cursor = Cursors.Hand
Dim hitPoint As New Point
If Me.HorizontalOrientation Then
hitPoint.X = actualPoint.X
hitPoint.Y = mStartPoint.Y
Else
hitPoint.X = mStartPoint.X
hitPoint.Y = actualPoint.Y
End If
Dim fe As FrameworkElement = TryCast(InputHitTest(hitPoint), _
FrameworkElement)
While fe IsNot Nothing AndAlso Not TypeOf fe Is TabItem
fe = TryCast(VisualTreeHelper.GetParent(fe), FrameworkElement)
End While
Dim tabMouseOver As TabItem = TryCast(fe, TabItem)
Dim p As Point = e.GetPosition(mLastTab)
Dim perc As Double
Dim targetIndex As Integer
If Me.HorizontalOrientation Then : perc = p.X / mLastTab.ActualWidth
Else : perc = p.Y / mLastTab.ActualHeight
End If
If perc < 0.5 Then : targetIndex = Me.Items.IndexOf(mLastTab)
Else : targetIndex = Me.Items.IndexOf(mLastTab) + 1
End If
mMovingTabItem.Opacity = 0.5
Dim xform As TranslateTransform = TryCast( _
mMovingTabItem.RenderTransform, TranslateTransform)
If xform IsNot Nothing Then
If Me.HorizontalOrientation Then
xform.X = actualPoint.X - mStartPoint.X
Else
xform.Y = actualPoint.Y - mStartPoint.Y
End If
End If
If tabMouseOver IsNot Nothing Then
If mOldIndex <> targetIndex Then
mOldIndex = targetIndex
Dim myIndex As Integer = Me.Items.IndexOf(mMovingTabItem)
For i As Integer = 0 To Me.Items.Count - 1
Dim item As TabItem = TryCast(Me.Items(i), TabItem)
If item IsNot Nothing AndAlso item IsNot mMovingTabItem _
Then
Dim tabform As TranslateTransform = TryCast( _
item.RenderTransform, TranslateTransform)
If tabform IsNot Nothing Then
If targetIndex < myIndex AndAlso i >= _
targetIndex And i < myIndex Then
If Me.HorizontalOrientation Then : _
tabform.X = mMovingTabItem.ActualWidth
Else : tabform.Y = _
mMovingTabItem.ActualHeight
End If
ElseIf myIndex < targetIndex AndAlso i > _
myIndex And i < targetIndex Then
If Me.HorizontalOrientation Then : _
tabform.X = -mMovingTabItem.ActualWidth
Else : tabform.Y = _
-mMovingTabItem.ActualHeight
End If
Else
If Me.HorizontalOrientation Then : _
tabform.X = 0
Else : tabform.Y = 0
End If
End If
End If
End If
Next
End If
mLastTab = tabMouseOver
End If
End If
End Sub
End Class Maas | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
sevISDN 1.0
Überwachung aller eingehender Anrufe!
Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Weitere InfosTipp des Monats sevGraph (VB/VBA)
Grafische Auswertungen
Präsentieren Sie Ihre Daten mit wenig Aufwand in grafischer Form. sevGraph unterstützt hierbei Balken-, Linien- und Stapel-Diagramme (Stacked Bars), sowie 2D- und 3D-Tortendiagramme und arbeitet vollständig datenbankunabhängig! Weitere Infos
|