| |
VB.NET - FortgeschritteneOwnerDraw Treeview | | | Autor: Manfred X | Datum: 27.05.14 16:03 |
| Ich habe das Video nicht angeschaut, erkenne aber das Problem.
Beim Click auf den Button "btn" werden die gecheckten Nodes gelistet,
aber bei schneller Click-Wiederholung klappt beim Treeview die
Koordination zwischen der Anzeige des Node-Check und zurückgegebenen
Check-Eigenschaft des Node nicht.
Workaround: Eventuell die Knoten selbst zeichen
Public Class frmCheckedNodes
Dim WithEvents trv As New TreeView With _
{.Parent = Me, .Width = 200, .CheckBoxes = True, _
.DrawMode = TreeViewDrawMode.OwnerDrawAll}
Dim CheckedNodes As New List(Of String)
Dim bs As New BindingSource With {.DataSource = CheckedNodes}
Dim lbo As New ListBox With _
{.Parent = Me, .Left = 210, .Top = 40, .DataSource = bs}
Dim WithEvents btn As New Button With _
{.Parent = Me, .Left = 210, .Text = "Checked Nodes"}
Private Sub frmCheckedNodes_Load(sender As System.Object, _
e As System.EventArgs) Handles MyBase.Load
FillTree()
End Sub
Private Sub btn_Click(sender As Object, _
e As System.EventArgs) Handles btn.Click
CheckedNodes.Clear()
ListCheckedNodes(trv, CheckedNodes)
bs.ResetBindings(False)
End Sub
Private Sub HandleMouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles trv.MouseDown
Dim info As TreeViewHitTestInfo = trv.HitTest(e.X, e.Y)
If (info IsNot Nothing) Then
info.Node.Checked = Not info.Node.Checked
End If
End Sub
Private Sub trv_DrawNode(sender As Object, _
e As System.Windows.Forms.DrawTreeNodeEventArgs) Handles trv.DrawNode
Dim f As Font = e.Node.NodeFont
If f Is Nothing Then f = trv.Font
Dim c As Color = Color.Black
If e.Node.Checked Then c = Color.Red
Using br As New SolidBrush(c)
e.Graphics.DrawString(e.Node.Text, f, br, e.Node.Bounds.Location)
End Using
End Sub
Private Sub FillTree()
For i As Integer = 0 To 5
Dim sn As TreeNode = trv.Nodes.Add(CStr(i), CStr(i))
For k As Integer = 0 To 5
sn.Nodes.Add(CStr(i) + CStr(k), CStr(i) & CStr(k))
Next k
Next i
End Sub
Private Sub ListCheckedNodes(ByVal trv As TreeView, _
ByVal lst As List(Of String))
For Each node As TreeNode In trv.Nodes
If node.Checked Then
lst.Add(node.FullPath)
End If
For Each sn As TreeNode In node.Nodes
CheckedNodesRecursive(sn, lst)
Next sn
Next
End Sub
Private Sub CheckedNodesRecursive(ByVal tn As TreeNode, _
ByVal lst As List(Of String))
If tn.Checked Then
lst.Add(tn.FullPath)
End If
For Each sn As TreeNode In tn.Nodes
CheckedNodesRecursive(sn, lst)
Next
End Sub
End Class
Beitrag wurde zuletzt am 27.05.14 um 16:05:39 editiert. | |
VB.net Treeview mit Checkboxes - Wie prüfe ich ob TopNode gecheckt wurde | | | Autor: Jenpet | Datum: 26.05.14 16:56 |
| Ich habe ein Problem mit vb.net.
Ich kann nicht prüfen, ob der TopNode gechecked wurde, wenn nur der TopNode gecheckt wurde und kein unterordner.
http://www.fotos-hochladen.net/uploads/treeview50sjahpg14.png
Ich habe schon mehrere Beispiele im Internet ausprobiert, aber überall tritt das gleiche Problem bei mir auf.
VB.net behauptet immer Checked = False, obwohl die Checkbox angekreuzt ist (das Bild habe ich beim Debuggen gemacht):
http://www.fotos-hochladen.net/uploads/checkedgujbfzr42w.png
Ich habe mit der Funktion versucht zu prüfen welche Checkboxen angekreuzt sind, um diese später in einen anderen Ordner zu kopieren.
Private Sub PrintRecursive(ByVal n As TreeNode)
Dim aNode As TreeNode
For Each aNode In n.Nodes
If aNode.Checked Then
proveChecked = True
listPath.Add(aNode.FullPath)
filesCount += My.Computer.FileSystem.GetFiles( _
aNode.FullPath).Count
End If
PrintRecursive(aNode)
Next
End Sub
' Call the procedure using the top nodes of the treeview.
Private Sub CallRecursive(ByVal aTreeView As TreeView)
'If aTreeView.TopNode.Checked Then
' proveChecked = True
' listPath.Add(aTreeView.TopNode.FullPath)
'End If
Dim n As TreeNode
For Each n In aTreeView.Nodes
PrintRecursive(n)
Next
End Sub In der unteren Funktion im auskommentierten Bereich habe ich versucht die TopNode zu überprüfen.
Hatte hier auch schon jemand einmal das Problem, dass eine Checkbox gechecked war und das trotzdem nicht erkannt wurde? Mache ich evtl. etwas falsch in der Funktion und man kann es gar nicht auf diese Art prüfen?
| |
Alles in Ordnung ???? | | | Autor: Manfred X | Datum: 26.05.14 18:52 |
| TreeView1.Nodes.Add("Key", "Text")
TreeView1.Nodes.Item("Key").Checked = True
If TreeView1.Nodes.Item("Key").Checked Then
MsgBox("Alles in Ordnung")
End If In Deinem Code wird die oberste Knotenebene nicht geprüft.
Beitrag wurde zuletzt am 26.05.14 um 18:54:24 editiert. | |
Re: VB.net Treeview mit Checkboxes - Wie prüfe ich ob TopNode gecheckt wurde | | | Autor: Manfred X | Datum: 26.05.14 19:54 |
| Vielleicht so etwas ...
(Sollen untergeordnete Knoten geprüft werden, wenn der
übergeordnete Knoten nicht gechecked worden ist?)
Dim listpath As New List(Of String)
' Call the procedure using the top nodes of the treeview.
Private Sub CallRecursive(ByVal aTreeView As TreeView)
For Each node As TreeNode In aTreeView.Nodes
If node.Checked Then
listpath.Add(node.FullPath)
End If
Dim n As TreeNode
For Each n In node.Nodes
PrintRecursive(n)
Next n
Next
End Sub
Private Sub PrintRecursive(ByVal n As TreeNode)
If n.Checked Then
listpath.Add(n.FullPath)
End If
Dim aNode As TreeNode
For Each aNode In n.Nodes
PrintRecursive(aNode)
Next
End Sub | |
Re: VB.net Treeview mit Checkboxes - Wie prüfe ich ob TopNode gecheckt wurde | | | Autor: Jenpet | Datum: 27.05.14 09:08 |
| Danke für den Code, werde ich gleich mal ausprobieren!
Ja untergeordnete Knoten sollen auch geprüft werden. Es soll auch möglich sein nur unterordner zu Kopieren. Wenn ich z.B. nur den letzten Knoten checke, soll der ganze Pfad aufgebaut werden im neuen Ordner, aber die Files sollen nur aus den Ordnern kopiert werden, die gecheckt wurden.
Das Funktioniert schon alles, nur wenn ich die TopNode checke hat es bis jetzt nicht geklappt, dann hat mein Programm so reagiert als hätte ich nichts gecheckt und hat einfach den kompletten Pfad kopiert.
| |
Re: VB.net Treeview mit Checkboxes - Wie prüfe ich ob TopNode gecheckt wurde | | | Autor: Jenpet | Datum: 27.05.14 11:32 |
| Als ich Manfreds Code gerade ausprobiert habe und es einmal ging und dann wieder nicht, ist mir aufgefallen, dass das Problem gar nicht am Code liegt, sondern an der Treeview.
Ich habe davon ein Video gemacht:
http://www.vidup.de/v/618Bh/
(das Passwort lautet vb.net)
Wenn man mehrmals schnell auf den Knoten Test2 klickt und so nur dieser gecheckt ist und alle anderen nicht, erkennt VB.net das nicht als checked an.
Im Video wird das dann so gehandhabt, als ob ich nichts angeklickt hätte und der komplette Ordner wird kopiert.
Beim 2. mal im Video ab Sekunde 7 klicke ich einmal auf den Knoten Test2 und entferne die hinteren gecheckten Knoten in dem ich den nächsten Knoten Test3 wegklicke. Hier wird dann wirklich nur alles was sich in Test2 befindet kopiert, so wie es auch sein sollte.
Ich habe versucht dieses Event zu verhindern, in dem ich einfach beim Doppelklick sage, entferne alle checks.
Private Sub TreeView1_DoubleClick(sender As Object, e As System.EventArgs) _
Handles TreeView1.DoubleClick
'Me.TreeView1.SelectedNode.Checked = True
UncheckAllNodes(TreeView1.Nodes, False)
End Sub Und da das Treenode auch selektiert wird, sage ich entferne alle Selektierungen.
Private Sub TreeView1_AfterSelect(ByVal sender As Object, _
ByVal e As TreeViewEventArgs) _
Handles TreeView1.AfterSelect
'If e.Node.Nodes.Count = 0 Then
' AllSubDirectories(e.Node)
'End If
TreeView1.SelectedNode = Nothing
End Sub Trotzdem tritt das Problem immer noch auf und ich will verhindern, dass ein Benutzer per Mehrfachklick den Knoten checkt und dann alles kopiert wird, statt nur dem Ordner der wiklich kopiert werden soll.
Da das für mich die 2 Events waren, mit denen ich das fehlerhafte Checken ausführe, habe ich es damit probiert. Könnten es evtl. noch andere Events sein die Schuld daran sind, dass der Knoten gecheckt ist, obwohl er für VB.net nicht gecheckt ist? | |
Re: VB.net Treeview mit Checkboxes - Wie prüfe ich ob TopNode gecheckt wurde | | | Autor: Jenpet | Datum: 28.05.14 09:15 |
| Danke für den Tipp, die Checks per Button selbst auszuwählen würde zu lange dauern.
Die Ordner die kopiert werden müssen, sind viele GB groß und von den 100 Ordnern werden im Schnitt 5-15 nicht gebraucht beim kopieren, je nachdem bei wem man das durchführt.
Eigentlich wäre die Lösung die ich erstellt habe genau so wie wir es brauchen, wenn dieses Koordinationsproblem zwischen Anzeige und den Eigenschaften gibt. Gleich der erste den ich mein Programm hab testen lassen, bei dem ist sofort dieses Problem aufgetreten.
Aber danke für die Tipps.
| |
Zeichenschule: CheckedTreeview | | | Autor: Manfred X | Datum: 28.05.14 11:05 |
| Probier mal diese Ableitung des Treeview.
Imports System.Windows.Forms
Public Class CheckedTreeView
Inherits TreeView
Public Sub New()
MyBase.DrawMode = TreeViewDrawMode.OwnerDrawAll
MyBase.CheckBoxes = True
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
Dim info As TreeViewHitTestInfo = Me.HitTest(e.X, e.Y)
If info IsNot Nothing AndAlso info.Node IsNot Nothing Then
If e.X < info.Node.Bounds.X + info.Node.Bounds.Width + 4 Then
'Click auf die Checkbox Checked oder unchecked
info.Node.Checked = Not info.Node.Checked
Else
'Click auf den Node-text collapsed oder expand
If info.Node.IsExpanded Then
info.Node.Collapse()
Else
info.Node.Expand()
End If
End If
End If
End Sub
Protected Overrides Sub OnDrawNode _
(e As System.Windows.Forms.DrawTreeNodeEventArgs)
MyBase.OnDrawNode(e)
With e.Node
Dim f As Font = .NodeFont
If f Is Nothing Then f = Me.Font
Dim c As Color = .ForeColor
If .Checked Then c = Color.Red
If c.A = 0 Then c = Me.ForeColor 'Knotenfarbe nicht definiert
Using brfore As New SolidBrush(c), _
brback As New SolidBrush(.BackColor), _
p As New Pen(c, 1), _
brTreeBack As New SolidBrush(Me.BackColor)
With .Bounds
'Treeview Knotenhintergrund zeichnen
Dim nodespacerect As New Rectangle _
(Me.Left, .Y, Me.Width, .Height)
e.Graphics.FillRectangle(brTreeBack, nodespacerect)
'Checkbox für Knoten zeichnen
Dim box As New Rectangle _
(.X + 2, .Y + 2, .Height - 4, .Height - 4)
e.Graphics.DrawRectangle(p, box)
If e.Node.Checked Then
'Checkbox markieren
e.Graphics.DrawLine _
(p, .X, .Y, .X + .Height, .Y + .Height)
e.Graphics.DrawLine _
(p, .X + .Height, .Y, .X, .Y + .Height)
End If
'Text ausgeben (incl. Expand/Collapse-Zeichen)
If e.Node.Nodes.Count = 0 Then
e.Graphics.DrawString _
(e.Node.Text, f, brfore, .X + .Height + 4, .Y)
Else
'Unterknoten: kollabiert oder expandiert?
Dim cs As String
If e.Node.IsExpanded Then cs = "(-) " Else cs = "(+) "
e.Graphics.DrawString _
(cs & e.Node.Text, f, brfore, .X + .Height + 4, .Y)
End If
'ggf. Verbindungslinie zum übergeordneten Knoten zeichnen
If e.Node.Parent IsNot Nothing Then
Dim start As Integer = _
e.Node.Parent.Bounds.X + Fix(.Height \ 2)
e.Graphics.DrawLine _
(p, New Point(start, .Y + .Height \ 2), _
New Point(.X - 4, .Y + .Height \ 2))
e.Graphics.DrawLine _
(p, New Point(start, .Y + .Height), _
New Point(start, e.Node.Parent.Bounds.Y + _
e.Node.Parent.Bounds.Height))
End If
End With
End Using
End With
End Sub
''' <summary>Modus, in dem Nodes gezeichnet werden (OwnerDrawAll)</summary>
Public Shadows ReadOnly Property Drawmode() As TreeViewDrawMode
Get
Return MyBase.DrawMode
End Get
End Property
''' <summary>zu jedem Knoten wird ein Kontrolkästchen angezeigt</summary>
Public Shadows ReadOnly Property Checkboxes() As Boolean
Get
Return MyBase.CheckBoxes
End Get
End Property
End Class
Beitrag wurde zuletzt am 28.05.14 um 11:10:48 editiert. | |
Re: VB.net Treeview mit Checkboxes - Wie prüfe ich ob TopNode gecheckt wurde | | | Autor: Jenpet | Datum: 28.05.14 15:29 |
| Sorry für die Frage, aber ich hab seit sicher 3-4 Jahren nix mehr mit Vererbungen gemacht und damals war das noch mit C++.
Ich hab die Klasse CheckedTreeView erstellt und ein Objekt davon in meiner Form1.VB erstellt.
Benutze ich jetzt jedesmal das Objekt der Klasse CheckedTreeView statt meinem orginal TreeView1 Objekt oder benutze ich nur im Load-Bereich das CheckedTreeView Objekt, um das alles zu zeichnen?
Und falls ich jedesmal das neue Objekt benutze, rufe ich es in den Events auf oder funktioniert das so nicht?
Wahrscheinlich ist das eher eine Frage für den Anfängerbereich, aber da hänge ich gerade etwas fest | |
Es geht voran .... | | | Autor: Manfred X | Datum: 28.05.14 15:42 |
| Imports System.Windows.Forms
Public Class CheckedTreeView
Inherits TreeView
Public Sub New()
MyBase.DrawMode = TreeViewDrawMode.OwnerDrawAll
MyBase.CheckBoxes = True
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
Dim info As TreeViewHitTestInfo = Me.HitTest(e.X, e.Y)
If info IsNot Nothing AndAlso info.Node IsNot Nothing Then
With info.Node
If e.X > .Bounds.X - 2 And _
e.X < .Bounds.X + .Bounds.Height + 4 Then
'Click auf die Checkbox: Checked oder unchecked
.Checked = Not .Checked
Else
'Click auf den Node-text: collapsed oder expand
If .IsExpanded Then
.Collapse()
Else
.Expand()
End If
End If
End With
End If
End Sub
Protected Overrides Sub OnDrawNode _
(e As System.Windows.Forms.DrawTreeNodeEventArgs)
MyBase.OnDrawNode(e)
Dim checkedcolor As Color = Color.Red
If e.Node.Bounds.Y = 0 And _
Not Me.Nodes(0) Is e.Node Then Exit Sub 'Bug abfangen
With e.Node
Dim f As Font = .NodeFont
If f Is Nothing Then f = Me.Font
Dim c As Color = .ForeColor
If .Checked Then c = checkedcolor
If c.A = 0 Then c = Me.ForeColor 'Knotenfarbe nicht definiert
Using brfore As New SolidBrush(c), _
brback As New SolidBrush(.BackColor), _
p As New Pen(c, 1), _
brTreeBack As New SolidBrush(Me.BackColor)
With .Bounds
'Checkbox für Knoten zeichnen
Dim box As New Rectangle _
(.X + 2, .Y + 2, .Height - 4, .Height - 4)
e.Graphics.DrawRectangle(p, box)
If e.Node.Checked Then
'Checkbox markieren
e.Graphics.DrawLine _
(p, .X, .Y, .X + .Height, .Y + .Height)
e.Graphics.DrawLine _
(p, .X + .Height, .Y, .X, .Y + .Height)
End If
'Text ausgeben (incl. Expand/Collapse-Zeichen)
Dim cs As String
If e.Node.Nodes.Count = 0 Then
cs = ""
Else
'Unterknoten: kollabiert oder expandiert?
If e.Node.IsExpanded Then cs = "(-) " Else cs = "(+) "
End If
e.Graphics.DrawString _
(cs & e.Node.Text, f, brfore, .X + .Height + 4, .Y)
'ggf. Verbindungslinien zu übergeordneten Knoten
Dim n As TreeNode = e.Node
Dim vertical As Boolean = True
While n.Parent IsNot Nothing
Dim start As Integer = _
n.Parent.Bounds.X + .Height \ 2
If vertical Then
e.Graphics.DrawLine _
(p, New Point(start, .Y + .Height \ 2), _
New Point(.X - 4, .Y + .Height \ 2))
vertical = False
End If
e.Graphics.DrawLine(p, _
New Point(start, .Y + .Height), _
New Point(start, _
n.Parent.Bounds.Y + n.Parent.Bounds.Height))
n = n.Parent
End While
End With
End Using
End With
End Sub
''' <summary>Modus, in dem das Control gezeichnet wird (OwnerDrawAll)</summary>
Public Shadows Property Drawmode() As TreeViewDrawMode
Set(value As TreeViewDrawMode)
'
End Set
Get
Return MyBase.DrawMode
End Get
End Property
''' <summary>zu jedem Knoten wird ein Kontrolkästchen angezeigt</summary>
Public Shadows Property Checkboxes() As Boolean
Set(value As Boolean)
'
End Set
Get
Return MyBase.CheckBoxes
End Get
End Property
End Class Klasse in das Projekt aufnehmen und Projekt übersetzen.
Danach findet sich in der Toolbox, Abschnitt <Projektname>,
ein neues Steuerelement.
Zu benutzen wie von Treeview gewohnt -
Scrollable-Eigenschaft auf false setzen, ggf. Scrollen
durch ein Scroll-Control durchführen,
per "Invalidate" das Neuzeichnen des TreeView verwalten.
Beitrag wurde zuletzt am 28.05.14 um 16:10:56 editiert. | |
Re: VB.net Treeview mit Checkboxes - Wie prüfe ich ob TopNode gecheckt wurde | | | Autor: Jenpet | Datum: 28.05.14 16:06 |
| Ah danke, jetzt hab ichs kapiert.
| |
Immer noch .... | | | Autor: Manfred X | Datum: 28.05.14 16:25 |
| Diese Zeile
If e.Node.Bounds.Y = 0 And _
Not Me.Nodes(0) Is e.Node Then Exit Sub 'Bug abfangen ist zu ersetzen durch
If e.Node.Bounds.Width = 0 Then Exit Sub 'Bug abfangen So klappt es dann auch wieder mit dem Scrollen des Treeview.
Beitrag wurde zuletzt am 28.05.14 um 16:29:05 editiert. | |
| 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 TOP! Unser Nr. 1
Neu! sevDataGrid 3.0
Mehrspaltige Listen, mit oder ohne DB-Anbindung. Autom. Sortierung, Editieren von Spalteninhalten oder das interaktive Hinzufügen von Datenzeilen sind ebenso möglich wie das Erstellen eines Web-Reports. Weitere Infos
|