Блог программиста Еремина Вячеслава Викторовича
(NET) NET (2005 год)

Редактируемое дерево с меняющимся контекстным меню

На этой задаче я в очередной раз убедился, что далеко не все задачи в принципе реализуемы в Web. Задача управления классификаторами получается, увы, слишком тыжеловесна для Web. Поэтому значительную часть функций возможно выполнить ТОЛЬКО в Windows. Это происходит по двум причинам:

В итоге, большая часть управления классикаторами перекочевала в Win-приложение...





В качестве бонуса я покажу тут текст своего одного неплохого контрола, который представляется собою редактируемое дерево c динамически меняющимся контекстным меню. Этот мой редактор классификаторов имеет больше десяток форм, использующих этот контрол, некоторое их которых вы видите выше. Этот контрол я написал не то в 2001-м, не то в 2002-году, когда только появился седьмой бейсик. Этот контрол основан на довольно интресной технике работы с делегатами, похожую технику я использовал здесь.

Вот собственно модуль контрола:

00001: <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
00002: Partial Class Ed_TreeViewTest
00003:     Inherits System.Windows.Forms.Form
00004: 
00005:     'Form overrides dispose to clean up the component list.
00006:     <System.Diagnostics.DebuggerNonUserCode()> _
00007:     Protected Overrides Sub Dispose(ByVal disposing As Boolean)
00008:         If disposing AndAlso components IsNot Nothing Then
00009:             components.Dispose()
00010:         End If
00011:         MyBase.Dispose(disposing)
00012:     End Sub
00013: 
00014:     'Required by the Windows Form Designer
00015:     Private components As System.ComponentModel.IContainer
00016: 
00017:     'NOTE: The following procedure is required by the Windows Form Designer
00018:     'It can be modified using the Windows Form Designer.  
00019:     'Do not modify it using the code editor.
00020:     <System.Diagnostics.DebuggerStepThrough()> _
00021:     Private Sub InitializeComponent()
00022:         Me.components = New System.ComponentModel.Container
00023:         Me.SplitContainer1 = New System.Windows.Forms.SplitContainer
00024:         Me.Ed_TreeView1 = New Global.Ed_TreeView.Ed_TreeView
00025:         Me.ContextMenuStrip1 = New System.Windows.Forms.ContextMenuStrip(Me.components)
00026:         Me.ToolStripMenuItem2 = New System.Windows.Forms.ToolStripMenuItem
00027:         Me.Label1 = New System.Windows.Forms.Label
00028:         Me.SplitContainer1.Panel1.SuspendLayout()
00029:         Me.SplitContainer1.Panel2.SuspendLayout()
00030:         Me.SplitContainer1.SuspendLayout()
00031:         Me.ContextMenuStrip1.SuspendLayout()
00032:         Me.SuspendLayout()
00033:         '
00034:         'SplitContainer1
00035:         '
00036:         Me.SplitContainer1.Dock = System.Windows.Forms.DockStyle.Fill
00037:         Me.SplitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2
00038:         Me.SplitContainer1.Location = New System.Drawing.Point(0, 0)
00039:         Me.SplitContainer1.Name = "SplitContainer1"
00040:         Me.SplitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal
00041:         '
00042:         'SplitContainer1.Panel1
00043:         '
00044:         Me.SplitContainer1.Panel1.Controls.Add(Me.Ed_TreeView1)
00045:         '
00046:         'SplitContainer1.Panel2
00047:         '
00048:         Me.SplitContainer1.Panel2.Controls.Add(Me.Label1)
00049:         Me.SplitContainer1.Size = New System.Drawing.Size(292, 273)
00050:         Me.SplitContainer1.SplitterDistance = 240
00051:         Me.SplitContainer1.TabIndex = 0
00052:         '
00053:         'Ed_TreeView1
00054:         '
00055:         Me.Ed_TreeView1.BackColor = System.Drawing.SystemColors.Control
00056:         Me.Ed_TreeView1.ContextMenuStrip = Me.ContextMenuStrip1
00057:         Me.Ed_TreeView1.Dock = System.Windows.Forms.DockStyle.Fill
00058:         Me.Ed_TreeView1.Ed_Level = 1
00059:         Me.Ed_TreeView1.Ed_NodeAdd_Delegate_AddressOf = Nothing
00060:         Me.Ed_TreeView1.Location = New System.Drawing.Point(0, 0)
00061:         Me.Ed_TreeView1.Name = "Ed_TreeView1"
00062:         Me.Ed_TreeView1.Size = New System.Drawing.Size(292, 240)
00063:         Me.Ed_TreeView1.TabIndex = 0
00064:         '
00065:         'ContextMenuStrip1
00066:         '
00067:         Me.ContextMenuStrip1.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.ToolStripMenuItem2})
00068:         Me.ContextMenuStrip1.Name = "ContextMenuStrip1"
00069:         Me.ContextMenuStrip1.Size = New System.Drawing.Size(92, 26)
00070:         '
00071:         'ToolStripMenuItem2
00072:         '
00073:         Me.ToolStripMenuItem2.Name = "ToolStripMenuItem2"
00074:         Me.ToolStripMenuItem2.Size = New System.Drawing.Size(91, 22)
00075:         Me.ToolStripMenuItem2.Text = "1"
00076:         '
00077:         'Label1
00078:         '
00079:         Me.Label1.AutoSize = True
00080:         Me.Label1.Dock = System.Windows.Forms.DockStyle.Fill
00081:         Me.Label1.Location = New System.Drawing.Point(0, 0)
00082:         Me.Label1.Name = "Label1"
00083:         Me.Label1.Size = New System.Drawing.Size(39, 13)
00084:         Me.Label1.TabIndex = 0
00085:         Me.Label1.Text = "Label1"
00086:         '
00087:         'Ed_TreeViewTest
00088:         '
00089:         Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
00090:         Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
00091:         Me.ClientSize = New System.Drawing.Size(292, 273)
00092:         Me.Controls.Add(Me.SplitContainer1)
00093:         Me.Name = "Ed_TreeViewTest"
00094:         Me.Text = "Form1"
00095:         Me.SplitContainer1.Panel1.ResumeLayout(False)
00096:         Me.SplitContainer1.Panel2.ResumeLayout(False)
00097:         Me.SplitContainer1.Panel2.PerformLayout()
00098:         Me.SplitContainer1.ResumeLayout(False)
00099:         Me.ContextMenuStrip1.ResumeLayout(False)
00100:         Me.ResumeLayout(False)
00101: 
00102:     End Sub
00103:     Friend WithEvents SplitContainer1 As System.Windows.Forms.SplitContainer
00104:     Friend WithEvents Label1 As System.Windows.Forms.Label
00105:     Friend WithEvents Ed_TreeView1 As Ed_TreeView
00106:     Friend WithEvents ContextMenuStrip1 As System.Windows.Forms.ContextMenuStrip
00107:     Friend WithEvents ToolStripMenuItem2 As System.Windows.Forms.ToolStripMenuItem
00108: End Class

00001: 'Этот контрол с деревом позволяет редактировать по месту узлы в заданном уровне
00002: 'Контрол выдает события - изменения узла, выбора, удаления, добавления (надо задать делегат, возвращающий ключ в базе)
00003: 'Контрол добавляет к заданому извне контекстному меню свое собственное на заданный уровень для выполнения - удаления, добавления и изменения
00004: 'Дерево в контрол загружается извне
00005: 
00006: Imports System.ComponentModel
00007: Imports System.Windows.Forms
00008: 
00009: <Description("Дерево с редактированием узлов в заданном уровне")> _
00010: Public Class Ed_TreeView
00011: 
00012:     <Description("Cобытие выбора узла"), Category("Ed")> _
00013:     Public Event Ed_NodeSelected(ByVal SelectedKey As String, ByVal SelectedText As String)
00014:     <Description("Cобытие удаления узла"), Category("Ed")> _
00015:     Public Event Ed_NodeRemove(ByVal SelectedKey As String, ByVal SelectedText As String)
00016:     <Description("Cобытие изменения текста узла"), Category("Ed")> _
00017:     Public Event Ed_NodeChanged(ByVal SelectedKey As String, ByVal NewValue As String)
00018:     'Этот делегат должен вернуть реальный ключ, присвоенный добавленному узлу в базе
00019:     Public Delegate Function Ed_NodeAdd_Delegate(ByVal ParentNodeKey As String, ByVal NewValue As String) As String
00020: 
00021:     Dim a_Ed_NodeAdd_Delegate_Addr As Ed_NodeAdd_Delegate
00022:     <Description("Этот делегат должен вернуть реальный ключ, присвоенный добавленному узлу в базе"), Category("Ed")> _
00023:     Public Property Ed_NodeAdd_Delegate_AddressOf() As Ed_NodeAdd_Delegate
00024:         Get
00025:             Ed_NodeAdd_Delegate_AddressOf = a_Ed_NodeAdd_Delegate_Addr
00026:         End Get
00027:         Set(ByVal value As Ed_NodeAdd_Delegate)
00028:             a_Ed_NodeAdd_Delegate_Addr = value
00029:         End Set
00030:     End Property
00031: 
00032:     Dim a_Ed_Level As Integer
00033:     <Description("Уровень в дереве, который подлежит редактированию"), Category("Ed")> _
00034:     Public Property Ed_Level() As Integer
00035:         Get
00036:             Ed_Level = a_Ed_Level
00037:         End Get
00038:         Set(ByVal value As Integer)
00039:             a_Ed_Level = value
00040:         End Set
00041:     End Property
00042: 
00043:     Dim a_Ed_SelectedKey As String
00044:     <Description("Tекущий выбранный юзером ключ в дереве"), Category("Ed")> _
00045:     Public ReadOnly Property Ed_SelectedKey() As String
00046:         Get
00047:             Ed_SelectedKey = a_Ed_SelectedKey
00048:         End Get
00049:     End Property
00050: 
00051:     Dim a_Ed_SelectedText As String
00052:     <Description("Tекущий выбранный юзером текст в дереве"), Category("Ed")> _
00053:     Public ReadOnly Property Ed_SelectedText() As String
00054:         Get
00055:             Ed_SelectedText = a_Ed_SelectedText
00056:         End Get
00057:     End Property
00058: 
00059:     <Description("Ссылка на дерево в этом контроле - для внешнего заполнения"), Category("Ed")> _
00060:     Public ReadOnly Property TreeView() As TreeView
00061:         Get
00062:             TreeView = TreeView1
00063:         End Get
00064:     End Property
00065: 
00066:     Public Delegate Sub DoClick()
00067:     Dim a_ExternalContextMenu As ContextMenuStrip = New Windows.Forms.ContextMenuStrip
00068:     Dim a_InternalContextMenu As ContextMenuStrip = New Windows.Forms.ContextMenuStrip
00069:     Private Sub Ed_TreeView_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
00070:         a_ExternalContextMenu = Me.ContextMenuStrip
00071:         a_InternalContextMenu = Label1.ContextMenuStrip
00072:         If Not (Me.ContextMenuStrip Is Nothing) Then
00073:             For Each x As ToolStripMenuItem In Me.ContextMenuStrip.Items
00074:                 Dim Y As New ToolStripMenuItem
00075:                 Y.Text = x.Text
00076:                 Y.Image = x.Image
00077:                 Dim Z As DoClick = AddressOf x.PerformClick
00078:                 Dim A As MyEventHandler = New MyEventHandler(Z, Y)
00079:                 'AddHandler Y.Click, AddressOf ExternalMenuClick
00080:                 AddHandler Y.Click, AddressOf A.ExternalMenuClick
00081:                 a_InternalContextMenu.Items.Add(Y)
00082:             Next
00083:         End If
00084:         If a_Ed_Level = 0 Then MsgBox("Не задан уровень редактирования дерева")
00085:     End Sub
00086: 
00087:     'выбранный правой кнопкой мышки узел сразу становится SELECTED
00088:     Private Sub TreeView1_NodeMouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseClick
00089:         TreeView1.SelectedNode = e.Node
00090:         If e.Button = Windows.Forms.MouseButtons.Right Then
00091:             If e.Node.Level = a_Ed_Level Then
00092:                 'добавим сюда контекстное меню редактирования дерева
00093:                 TreeView1.ContextMenuStrip = Nothing
00094:                 TreeView1.ContextMenuStrip = a_InternalContextMenu
00095:             Else
00096:                 TreeView1.ContextMenuStrip = Nothing
00097:                 TreeView1.ContextMenuStrip = a_ExternalContextMenu
00098:             End If
00099:         End If
00100:     End Sub
00101: 
00102:     'узел выбран - выходим к юзеру с заблокированным курсором для удобства
00103:     Private Sub TreeView1_AfterSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
00104:         Dim O As Cursor = Me.Cursor
00105:         Me.Cursor = Cursors.WaitCursor
00106:         a_Ed_SelectedKey = e.Node.Name
00107:         a_Ed_SelectedText = e.Node.Text
00108:         RaiseEvent Ed_NodeSelected(e.Node.Name, e.Node.Text)
00109:         If e.Node.Level = a_Ed_Level Then
00110:             For Each X As TreeNode In TreeView1.Nodes
00111:                 Call Recurs(X)
00112:             Next
00113:             TreeView1.SelectedNode.ForeColor = Drawing.Color.Blue
00114:         End If
00115:         Me.Cursor = O
00116:     End Sub
00117: 
00118:     'Рекурсивный обход всех нодов и сброс выделения цветом в текущем рабочем уровне
00119:     Private Sub Recurs(ByVal x As TreeNode)
00120:         If x.Level = a_Ed_Level Then x.ForeColor = Drawing.Color.Black
00121:         If x.Level < a_Ed_Level Then
00122:             'продолжаем углубляться в глубину
00123:             If Not (x.Nodes Is Nothing) Then
00124:                 For Each Y As TreeNode In x.Nodes
00125:                     Recurs(Y)
00126:                 Next
00127:             End If
00128:         End If
00129: 
00130:     End Sub
00131: 
00132:     'Удаление узла
00133:     Private Sub УдалитьToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles УдалитьToolStripMenuItem.Click
00134:         If TreeView1.SelectedNode.Level = a_Ed_Level Then
00135:             Dim O As Cursor = Me.Cursor
00136:             Me.Cursor = Cursors.WaitCursor
00137:             TreeView1.SelectedNode.Remove()
00138:             RaiseEvent Ed_NodeRemove(a_Ed_SelectedKey, a_Ed_SelectedText)
00139:             Me.Cursor = O
00140:         End If
00141:     End Sub
00142: 
00143: #Region "Изменение узла"
00144: 
00145:     Private Sub ИзменитьToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ИзменитьToolStripMenuItem.Click
00146:         If TreeView1.SelectedNode.Level = a_Ed_Level Then
00147:             Dim T As New Windows.Forms.TextBox
00148:             T.Text = TreeView1.SelectedNode.Text
00149:             T.Top = TreeView1.SelectedNode.Bounds.Top
00150:             T.Left = TreeView1.SelectedNode.Bounds.Left
00151:             T.Width = Me.Width - 100
00152:             T.Cursor = Cursors.IBeam
00153:             Me.Controls.Add(T)
00154:             T.BringToFront()
00155:             T.Focus()
00156:             AddHandler T.Leave, AddressOf NodeChange
00157:             AddHandler T.KeyPress, AddressOf NodeEnter
00158:             AddHandler T.TextChanged, AddressOf TxtChange
00159:             TreeView1.Enabled = False
00160:         End If
00161:     End Sub
00162: 
00163:     Private Sub TxtChange(ByVal sender As System.Object, ByVal e As System.EventArgs)
00164:         Dim T As TextBox = CType(sender, TextBox)
00165:         T.ForeColor = Drawing.Color.Red
00166:     End Sub
00167: 
00168:     Private Sub NodeChange(ByVal sender As System.Object, ByVal e As System.EventArgs)
00169:         Dim O As Cursor = Me.Cursor
00170:         Me.Cursor = Cursors.WaitCursor
00171:         Dim T As TextBox = CType(sender, TextBox)
00172:         Dim NewText As String = T.Text
00173:         RemoveHandler T.Leave, AddressOf NodeChange
00174:         RemoveHandler T.Enter, AddressOf NodeChange
00175:         RemoveHandler T.TextChanged, AddressOf TxtChange
00176:         Me.Controls.Remove(T)
00177:         T = Nothing
00178:         TreeView1.SelectedNode.Text = NewText
00179:         a_Ed_SelectedText = NewText
00180:         RaiseEvent Ed_NodeChanged(a_Ed_SelectedKey, NewText)
00181:         Me.Cursor = O
00182:         TreeView1.Enabled = True
00183:     End Sub
00184: 
00185:     Private Sub NodeEnter(ByVal sender As System.Object, ByVal e As System.EventArgs)
00186:         If CType(e, Windows.Forms.KeyPressEventArgs).KeyChar = vbCr Then
00187:             Call NodeChange(sender, e)
00188:         End If
00189:     End Sub
00190: 
00191: #End Region
00192: 
00193: #Region "Добавление узла"
00194: 
00195:     Private Sub ДобавитьToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ДобавитьToolStripMenuItem.Click
00196:         If TreeView1.SelectedNode.Level = a_Ed_Level Then
00197:             Dim O As Cursor = Me.Cursor
00198:             Me.Cursor = Cursors.WaitCursor
00199:             Dim X As TreeNode = TreeView1.SelectedNode
00200:             Dim Y As TreeNode = TreeView1.SelectedNode.Parent
00201:             Y.Nodes.Add(Y.Name & "," & Guid.NewGuid.ToString, "")
00202:             Dim i As Integer
00203:             For i = Y.Nodes.Count - 1 To 1 Step -1
00204:                 'раздвижка - перегон всех узлов вниз - это удобно 
00205:                 Y.Nodes(i).Name = Y.Nodes(i - 1).Name
00206:                 Y.Nodes(i).Text = Y.Nodes(i - 1).Text
00207:                 If Y.Nodes(i) Is X Then
00208:                     Exit For
00209:                 End If
00210:             Next
00211:             Y.Nodes(i).Name = Y.Name & Guid.NewGuid.ToString
00212:             Y.Nodes(i).Text = ""
00213:             a_Ed_SelectedText = ""
00214:             'и переход в редактирование
00215:             Dim T As New Windows.Forms.TextBox
00216:             T.Text = TreeView1.SelectedNode.Text
00217:             T.Top = TreeView1.SelectedNode.Bounds.Top
00218:             T.Left = TreeView1.SelectedNode.Bounds.Left
00219:             T.Width = Me.Width - 100
00220:             T.Cursor = Cursors.IBeam
00221:             Me.Controls.Add(T)
00222:             T.BringToFront()
00223:             T.Focus()
00224:             AddHandler T.Leave, AddressOf NodeAdd
00225:             AddHandler T.KeyPress, AddressOf NodeAddEnter
00226:             Me.Cursor = O
00227:             TreeView1.Enabled = False
00228:         End If
00229:     End Sub
00230: 
00231:     Private Sub NodeAdd(ByVal sender As System.Object, ByVal e As System.EventArgs)
00232:         Dim O As Cursor = Me.Cursor
00233:         Me.Cursor = Cursors.WaitCursor
00234:         Dim T As TextBox = CType(sender, TextBox)
00235:         Dim NewText As String = T.Text
00236:         RemoveHandler T.Leave, AddressOf NodeAdd
00237:         RemoveHandler T.Enter, AddressOf TxtChange
00238:         Me.Controls.Remove(T)
00239:         T = Nothing
00240:         TreeView1.SelectedNode.Text = NewText
00241:         a_Ed_SelectedText = NewText
00242:         TreeView1.SelectedNode.Name = a_Ed_NodeAdd_Delegate_Addr(TreeView1.SelectedNode.Parent.Name, NewText)
00243:         a_Ed_SelectedKey = TreeView1.SelectedNode.Name
00244:         RaiseEvent Ed_NodeSelected(a_Ed_SelectedKey, a_Ed_SelectedText)
00245:         Me.Cursor = O
00246:         TreeView1.Enabled = True
00247:     End Sub
00248: 
00249:     Private Sub NodeAddEnter(ByVal sender As System.Object, ByVal e As System.EventArgs)
00250:         If CType(e, Windows.Forms.KeyPressEventArgs).KeyChar = vbCr Then
00251:             Call NodeAdd(sender, e)
00252:         End If
00253:     End Sub
00254: 
00255: #End Region
00256: 
00257:     Private Sub CM1_Opening(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles CM1.Opening
00258:         e.Cancel = False
00259:     End Sub
00260: 
00261: End Class
00262: 
00263: Public Class MyEventHandler
00264:     Dim X As Ed_TreeView.DoClick
00265:     Dim y As ToolStripMenuItem
00266: 
00267:     Public Sub New(ByVal PerformClick As Ed_TreeView.DoClick, ByVal sender As ToolStripMenuItem)
00268:         X = PerformClick
00269:         y = sender
00270:     End Sub
00271: 
00272:     Public Sub ExternalMenuClick(ByVal sender As Object, ByVal e As System.EventArgs)
00273:         X.Invoke()
00274:     End Sub
00275: 
00276: End Class

В библиотеке, этот класс у меня лежит прямо вместе с тестом, который выглядит так:





Как видите, мой контрол добавляет на заданный уровень дерева контекстное меню (в дополнение к заданному извне) и позволяет по месту редактировать дерево, обновляя его из базы. Желающие могут найти в моем коде несколько интересных моментов, начиная от элементарных - рекурсии, кончая техникой работы с захватом адресов переходов для контекстного меню.

Ну и наконец, тест теста - естественно при компиляции - укажите для вызова иную точку входа в библиотеку, чем просто для использования контрола.

00001: <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
00002: Partial Class Ed_TreeView
00003:     Inherits System.Windows.Forms.UserControl
00004: 
00005:     'UserControl overrides dispose to clean up the component list.
00006:     <System.Diagnostics.DebuggerNonUserCode()> _
00007:     Protected Overrides Sub Dispose(ByVal disposing As Boolean)
00008:         If disposing AndAlso components IsNot Nothing Then
00009:             components.Dispose()
00010:         End If
00011:         MyBase.Dispose(disposing)
00012:     End Sub
00013: 
00014:     'Required by the Windows Form Designer
00015:     Private components As System.ComponentModel.IContainer
00016: 
00017:     'NOTE: The following procedure is required by the Windows Form Designer
00018:     'It can be modified using the Windows Form Designer.  
00019:     'Do not modify it using the code editor.
00020:     <System.Diagnostics.DebuggerStepThrough()> _
00021:     Private Sub InitializeComponent()
00022:         Me.components = New System.ComponentModel.Container
00023:         Me.TreeView1 = New System.Windows.Forms.TreeView
00024:         Me.CM1 = New System.Windows.Forms.ContextMenuStrip(Me.components)
00025:         Me.ДобавитьToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem
00026:         Me.УдалитьToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem
00027:         Me.ИзменитьToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem
00028:         Me.ToolStripSeparator1 = New System.Windows.Forms.ToolStripSeparator
00029:         Me.Label1 = New System.Windows.Forms.Label
00030:         Me.CM1.SuspendLayout()
00031:         Me.SuspendLayout()
00032:         '
00033:         'TreeView1
00034:         '
00035:         Me.TreeView1.Dock = System.Windows.Forms.DockStyle.Fill
00036:         Me.TreeView1.Location = New System.Drawing.Point(0, 0)
00037:         Me.TreeView1.Name = "TreeView1"
00038:         Me.TreeView1.Size = New System.Drawing.Size(150, 150)
00039:         Me.TreeView1.TabIndex = 0
00040:         '
00041:         'CM1
00042:         '
00043:         Me.CM1.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.ДобавитьToolStripMenuItem, Me.УдалитьToolStripMenuItem, Me.ИзменитьToolStripMenuItem, Me.ToolStripSeparator1})
00044:         Me.CM1.Name = "CM1"
00045:         Me.CM1.Size = New System.Drawing.Size(136, 76)
00046:         '
00047:         'ДобавитьToolStripMenuItem
00048:         '
00049:         Me.ДобавитьToolStripMenuItem.Name = "ДобавитьToolStripMenuItem"
00050:         Me.ДобавитьToolStripMenuItem.Size = New System.Drawing.Size(135, 22)
00051:         Me.ДобавитьToolStripMenuItem.Text = "Добавить"
00052:         '
00053:         'УдалитьToolStripMenuItem
00054:         '
00055:         Me.УдалитьToolStripMenuItem.Name = "УдалитьToolStripMenuItem"
00056:         Me.УдалитьToolStripMenuItem.Size = New System.Drawing.Size(135, 22)
00057:         Me.УдалитьToolStripMenuItem.Text = "Удалить"
00058:         '
00059:         'ИзменитьToolStripMenuItem
00060:         '
00061:         Me.ИзменитьToolStripMenuItem.Name = "ИзменитьToolStripMenuItem"
00062:         Me.ИзменитьToolStripMenuItem.Size = New System.Drawing.Size(135, 22)
00063:         Me.ИзменитьToolStripMenuItem.Text = "Изменить"
00064:         '
00065:         'ToolStripSeparator1
00066:         '
00067:         Me.ToolStripSeparator1.Name = "ToolStripSeparator1"
00068:         Me.ToolStripSeparator1.Size = New System.Drawing.Size(132, 6)
00069:         '
00070:         'Label1
00071:         '
00072:         Me.Label1.AutoSize = True
00073:         Me.Label1.ContextMenuStrip = Me.CM1
00074:         Me.Label1.Location = New System.Drawing.Point(64, 134)
00075:         Me.Label1.Name = "Label1"
00076:         Me.Label1.Size = New System.Drawing.Size(0, 13)
00077:         Me.Label1.TabIndex = 1
00078:         '
00079:         'Ed_TreeView
00080:         '
00081:         Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
00082:         Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
00083:         Me.Controls.Add(Me.TreeView1)
00084:         Me.Controls.Add(Me.Label1)
00085:         Me.Name = "Ed_TreeView"
00086:         Me.CM1.ResumeLayout(False)
00087:         Me.ResumeLayout(False)
00088:         Me.PerformLayout()
00089: 
00090:     End Sub
00091:     Friend WithEvents TreeView1 As System.Windows.Forms.TreeView
00092:     Friend WithEvents CM1 As System.Windows.Forms.ContextMenuStrip
00093:     Friend WithEvents ДобавитьToolStripMenuItem As System.Windows.Forms.ToolStripMenuItem
00094:     Friend WithEvents УдалитьToolStripMenuItem As System.Windows.Forms.ToolStripMenuItem
00095:     Friend WithEvents ИзменитьToolStripMenuItem As System.Windows.Forms.ToolStripMenuItem
00096:     Friend WithEvents ToolStripSeparator1 As System.Windows.Forms.ToolStripSeparator
00097:     Friend WithEvents Label1 As System.Windows.Forms.Label
00098: 
00099: End Class

00001: Public Class Ed_TreeViewTest
00002: 
00003:     Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
00004:         Ed_TreeView1.TreeView1.Nodes.Add("root", "root")
00005:         Ed_TreeView1.TreeView1.Nodes(0).Nodes.Add("1", "1")
00006:         Ed_TreeView1.TreeView1.Nodes(0).LastNode.Nodes.Add("a", "a")
00007:         Ed_TreeView1.TreeView1.Nodes(0).LastNode.Nodes.Add("b", "b")
00008:         Ed_TreeView1.TreeView1.Nodes(0).Nodes.Add("2", "2")
00009:         Ed_TreeView1.TreeView1.Nodes(0).Nodes.Add("3", "3")
00010:         Ed_TreeView1.Ed_NodeAdd_Delegate_AddressOf = AddressOf Ed_NodeAdd
00011:     End Sub
00012: 
00013:     Private Sub Ed_TreeView1_Ed_NodeChanged(ByVal SelectedKey As String, ByVal NewValue As String) Handles Ed_TreeView1.Ed_NodeChanged
00014:         '
00015:     End Sub
00016: 
00017:     Private Sub Ed_TreeView1_Ed_NodeRemove(ByVal SelectedKey As String, ByVal SelectedText As String) Handles Ed_TreeView1.Ed_NodeRemove
00018:         '
00019:     End Sub
00020: 
00021:     Private Sub Ed_TreeView1_Ed_NodeSelected(ByVal SelectedKey As String, ByVal SelectedText As String) Handles Ed_TreeView1.Ed_NodeSelected
00022:         Label1.Text = SelectedKey
00023:     End Sub
00024: 
00025:     Public Function Ed_NodeAdd(ByVal ParentKey As String, ByVal NewText As String) As String
00026:         Return Guid.NewGuid.ToString
00027:     End Function
00028: 
00029:     Private Sub ToolStripMenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripMenuItem2.Click
00030:         '
00031:     End Sub
00032: 
00033: 
00034: End Class

Ну и в заключение этого топика я расскажу, как надо правильно заполнять деревья за одно обращение в базу - ну по крайней мере я делаю именно так уже не один год.

Конечно, деревья можно заполнять и в реляционной технике, те заполнив каждый узел, далее вытащить из базы все его подчиненные узлы. Но можете себе представить, какой жуткий SQL-трафик порождает это отстойная шестерочная техника.

Поэтому в .NET такие жутковатые шестерочные техники надо избегать всеми силами. Здесь ведь можно вытащить всю иерархию данных за одно обращение к SQL:



и загрузить ее в дерево буквально в три строки:



Что привлекательно в .NET, что Win-деревья и Web-деревья заполняются АБСОЛЮТНО аналогично.



Комментарии к этой страничке ( )
ссылка на эту страничку: http://www.vb-net.ru/wanted/asp2class/index.htm
<Назад/a>>  <Назад>  <Назад>  <Назад>  <Назад>  <На главную>  <В раздел ASP>  <В раздел NET>  <В раздел SQL>  <В раздел Разное>  <Написать автору>  < Поблагодарить>