vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
SEPA-Dateien erstellen inkl. IBAN-, BLZ-/Kontonummernprüfung  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Ein- und Umsteiger
WPF: 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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel