Úprava objektu TreeView   zodpovězená otázka

VB.NET, WinForms

Zdravím, otevírám ještě toto téma k mému pokusu upravit si treeView. Původní můj dotaz byl zde:

http://www.vbnet.cz/forum-tema--2397-tre...

ale ptal jsem se na trošku něco jiného a bylo mi odpovězeno, tak proto otevírám tento topic.

Jde mi hlavně o to aby mi někdo zkušenější řekl zda na to nejdu uplně špatně, popřípadě mě navedl správným směrem.

Konečně jsem se dobral k tomu abych si přečetl články o objektech. Na základě těchto článku se pokouším upravit komponentu treeView (chybí mi tam možnost zakázání konkrétního node).

Pro začátek jsem si udělal vlastní node:

Public Class myTreeNode
    Inherits System.Windows.Forms.TreeNode

    Private _enabledNode As Boolean = True


    Public Property EnabledNode() As Boolean
        Get
            Return _enabledNode
        End Get

        Set(ByVal value As Boolean)
            ExecuteEnabled(_enabledNode)
            _enabledNode = value
        End Set
    End Property


    Sub ExecuteEnabled(ByVal enabled As Boolean)

        If enabled = True Then
            Me.NodeFont = New Font("Microsoft Sans Serif", 8)
            Me.BackColor = Color.Black
        Else
            Me.NodeFont = New Font("Microsoft Sans Serif", 8, FontStyle.Italic)
            Me.BackColor = Color.Gray
        End If
    End Sub

End Class

Vytvoření treeView a node do treeView a vložení na formulář udělám například takto:

        Dim treeview1 As TreeView = New TreeView
        treeview1.Anchor = AnchorStyles.Bottom Or AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top


        Dim nd As myTreeNode = treeview1.Nodes.Add("Parent")
        Dim nd2 As myTreeNode = treeview1.Nodes(0).Nodes.Add("Child")

        Me.Controls.Add(treeview1)

No a já bych teď potřeboval abych nd mohl nadeklarovat jako myTreeNode. Když se o to pokusím tak mi to ošklivě vynadá. Typuju že si budu muset vytvořit svůj treeView:

Public Class myTreeView
    Inherits System.Windows.Forms.TreeView

  
End Class

A typuju že zde budu muset přepsat metodu která do treeView vkládá node. Zde jsem se ale zarazil protože jednak nemůžu přijít co to je za metodu a jednak nemůžu přijít na to co do ní dát.

Doufám že jsem všechno nepochopil uplně špatně, kdyžtak mě trochu usměrněte:)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ze všeho nejdříve bych zmínil, že vámi navrhovaná třída má funkčnost pouze vizuální, nikoliv mechanickou, tj. barva se sice změní, ale na položku půjde i nadále klepnout, půjde rozbalit, atd. Abyste dosáhl skutečně zakázané položky, bylo by nutné velice low-level přepracování TreeNode, obávám se že pouze s použitím Windows API. Pokud vám stačí vizuální funkčnost, navrhuji použít mírně upravenou třídu:

Public Class CustomTreeNode
  Inherits TreeNode
  Private _foreColor As Color
  Private _isEnabled As Boolean
  Public Sub New()
    MyBase.New()
    _foreColor = Me.ForeColor
    _isEnabled = True
  End Sub
  Public Property IsEnabled() As Boolean
    Get
      Return _isEnabled
    End Get
    Set(ByVal value As Boolean)
      _isEnabled = value
      If Not _isEnabled Then
        _foreColor = Me.ForeColor
        Me.ForeColor = SystemColors.GrayText
      Else
        Me.ForeColor = _foreColor
      End If
    End Set
  End Property
End Class

S přidáním vlastní položky zděděné od TreeNode samosebou není problém, protože položka CustomTreeNode je kompatibilní s TreeNode, která se používá jako parametr metody Add.

TreeView1.Nodes.Add(New CustomTreeNode())

Není problém míchat dohromady TreeNode a CustomTreeNode:

Dim node1 As New TreeNode()
Dim node2 As New CustomTreeNode()
TreeView1.Nodes.AddRange(New TreeNode() {node1, node2})
nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Aha děkuji, pokud přidávám node tak jako vy tk mi to skutečně funguje:)

O tom že efekt je pouze vyzuální vím. Chtěl jsem si nejdříve zkusit jak na to než se ponořím do psaní funkčnosti. Moje představa byla taková (doufám že ne mylná) že bych nějákým způsobem dal (už přímo ve třídě) do události beforeSelecte kód který by kontroloval zda je enabled false nebo true a podle toho by dal e.cancel=true nebo by nechal kód proběhnout.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Tak ještě to treeview...

Public Class TreeViewCustom
    Inherits TreeView
    Public Sub New()
        MyBase.New()
    End Sub
    Protected Overrides Sub OnBeforeSelect(ByVal e As System.Windows.Forms.TreeViewCancelEventArgs)
        If e.Node.ForeColor = SystemColors.GrayText Then
            e.Cancel = True
        End If
        MyBase.OnBeforeSelect(e)
    End Sub
End Class
nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ještě bych se chtěl zeptat na jednu věc. Vámi upravený kód mi je jasný až na řádek:

MyBase.New()

který je umístěn v kontruktoru. Mohl by jste mi prosím osvětlit co tento příkaz dělá?

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Zavolá konstruktor bázové třídy (třídy ze které bylo odvozeno). Používá se to když je v konstruktoru bázové třídy nějaká inicializace, zde to volám pro jistotu.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Děkuji

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Taky moc díky.

Přikládám kód pokusného formuláře:

Imports System.Windows.Forms
Public Class Form1
    Dim WithEvents tv As TreeViewEx
    Dim lv As ListView

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        tv = New TreeViewEx
        tv.Dock = DockStyle.Fill
        lv = New ListView
        lv.Dock = DockStyle.Fill
        Dim nd As TreeNodeEx = New TreeNodeEx
        nd.Text = "ABC"
        tv.Nodes.Add(nd)
        For i As Integer = 1 To 3
            Dim nc As TreeNodeEx = New TreeNodeEx
            With nc
                .Text = nd.Text & i.ToString
                If i = 2 Then .IsEnabled = False
            End With
            nd.Nodes.Add(nc)
        Next
        nd.ExpandAll()
        Dim sc As SplitContainer = New SplitContainer
        With sc
            .Panel1.Controls.Add(tv)
            .Panel2.Controls.Add(lv)
            .Dock = DockStyle.Fill
        End With
        Me.Controls.Add(sc)
    End Sub
End Class

Public Class TreeNodeEx
    Inherits TreeNode
    Private _foreColor As Color
    Private _isEnabled As Boolean

    Public Sub New()
        MyBase.New()
        _foreColor = Me.ForeColor
        _isEnabled = True
    End Sub
    Public Property IsEnabled() As Boolean
        Get
            Return _isEnabled
        End Get
        Set(ByVal value As Boolean)
            _isEnabled = value
            If Not _isEnabled Then
                _foreColor = Me.ForeColor
                Me.ForeColor = SystemColors.GrayText
            Else
                Me.ForeColor = _foreColor
            End If
        End Set
    End Property
End Class

Public Class TreeViewEx
    Inherits TreeView
    Public Sub New()
        MyBase.New()
    End Sub
    Protected Overrides Sub OnBeforeSelect(ByVal e As System.Windows.Forms.TreeViewCancelEventArgs)
        If e.Node.ForeColor = SystemColors.GrayText Then
            e.Cancel = True
        End If
        MyBase.OnBeforeSelect(e)
    End Sub
End Class

Netuším, co bude dál, ale určitě toho bude

ještě hromada chybět a těším se, zda ještě

něco přibyde. Mnoho zdaru!

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Stornování rozhodně neprovádět na základě barvy položky...

Protected Overrides Sub OnBeforeSelect(ByVal e As TreeViewCancelEventArgs)
  If TypeOf e.Node Is CustomTreeNode Then
    If Not DirectCast(e.Node, CustomTreeNode).IsEnabled Then
      e.Cancel = True
    End If
  End If
  MyBase.OnBeforeSelect(e)
End Sub

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Takže jsem zde s další úpravou:) Jen jsem přidal funkci, že zakázané node pokud je parent se zabalí a nejde rozbalit (abych nemusel po jednom zakazovat položky pro které je rodič a pak je případně povolovat)

Takže customTreeNode:

Public Class CustomTreeNode
    Inherits TreeNode
    Private _foreColor As Color
    Private _isEnabled As Boolean
    Public Sub New()
        MyBase.New()
        _foreColor = Me.ForeColor
        _isEnabled = True
    End Sub
    Public Property IsEnabled() As Boolean
        Get
            Return _isEnabled
        End Get
        Set(ByVal value As Boolean)
            _isEnabled = value
            If Not _isEnabled Then
                _foreColor = Me.ForeColor
                Me.ForeColor = SystemColors.GrayText
                Me.Collapse()
            Else
                Me.ForeColor = _foreColor
            End If
        End Set
    End Property
End Class

Custom treeView:

Public Class customTreeView
    Inherits TreeView

    Protected Overrides Sub OnBeforeSelect(ByVal e As TreeViewCancelEventArgs)
        If TypeOf e.Node Is CustomTreeNode Then
            If Not DirectCast(e.Node, CustomTreeNode).IsEnabled Then
                e.Cancel = True
            End If
        End If
        MyBase.OnBeforeSelect(e)
    End Sub



    Protected Overrides Sub OnBeforeExpand(ByVal e As TreeViewCancelEventArgs)
        If TypeOf e.Node Is CustomTreeNode Then
            If Not DirectCast(e.Node, CustomTreeNode).IsEnabled Then
                e.Cancel = True
            End If
        End If
        MyBase.OnBeforeExpand(e)
    End Sub

Vytvoření treeView a přidání node:

    Dim TreeView1 As customTreeView = New customTreeView




    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim Parent1 As customTreeNode = New customTreeNode
        Dim Parent2 As customTreeNode = New customTreeNode
        Dim Child1 As customTreeNode = New customTreeNode
        Dim Child2 As customTreeNode = New customTreeNode
        Dim Child3 As customTreeNode = New customTreeNode
        Dim Child4 As customTreeNode = New customTreeNode
        Dim Child5 As customTreeNode = New customTreeNode
        Dim Child6 As customTreeNode = New customTreeNode

        TreeView1.Name = "TreeView1"
        TreeView1.Size = New Size(300, 300)

        Me.Controls.Add(TreeView1)


        Parent1.Text = "Parent 1"
        TreeView1.Nodes.Add(Parent1)

        Child1.Text = "Child 1.1"
        TreeView1.Nodes(0).Nodes.Add(Child1)

        Child2.Text = "Child 1.2"
        TreeView1.Nodes(0).Nodes.Add(Child2)

        Parent2.Text = "Parent 2"
        TreeView1.Nodes.Add(Parent2)

        Child3.Text = "Child 2.1"
        TreeView1.Nodes(1).Nodes.Add(Child3)

        Child4.Text = "Child 2.2"
        TreeView1.Nodes(1).Nodes.Add(Child4)

        Child5.Text = "Child 2.1.1"
        TreeView1.Nodes(1).Nodes(0).Nodes.Add(Child5)

        Child6.Text = "Child 2.1.2"
        TreeView1.Nodes(1).Nodes(0).Nodes.Add(Child6)



        Me.TreeView1.ExpandAll()
    End Sub

Buttony pro otestování (zakáže/povolí se první node které je parent:

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If TypeOf TreeView1.Nodes(0) Is CustomTreeNode Then DirectCast(TreeView1.Nodes(0), CustomTreeNode).IsEnabled = False
    End Sub


    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        If TypeOf TreeView1.Nodes(0) Is CustomTreeNode Then DirectCast(TreeView1.Nodes(0), CustomTreeNode).IsEnabled = True
    End Sub

Něják mě to chytlo, zkusím s tím ještě chvilku blbnout:)

Jen mi moc není jasný příkaz DirectCast. To je přetypování objektu?

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback