الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ال Treeview و ال Linklabel

بدأه C++er في 26 أغسطس 2009 · 13 رد · 5,114 مشاهدة · في قسم الدروس والمواضيع المتميزة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

لدى على جهازى كتب كثيره جدا فقمت بأرشفتها داخل قاعدة بيانات حسب مجموعات و لكن المشكله كانت فى التنقل بين افرع الشجره فلابد منى ان اسحب الـ Scrollbar إلى اعلى و الى اسفل يمنة و يسارا فقط للوصول إلى عنصر فى الشجره فى حين انه يوجد فى المسار الذى اقف عليه فى هذا الوقت.

لذا فكرت فى صنع اداة LinkLabel تعرض المسار الخاص بالـ Node التى اقف عليها و تقوم بفصل تلك العناصر على اساس انى استطيع التنقل بين عناصر الشجره الموجوده فى المسار الحالى فقط بالضغط عليه داخل الـ LinkLabel و هو يقوم بتحديد هذا الفرع و تحريك الـ Scroll عليه.

و لكى لا اطيل عليكم هذه هى الاداه

<ToolboxBitmap(GetType(LinkLabel))> _
Public Class TreeViewLink
	Inherits LinkLabel

	Dim mTreeView As TreeView
	Public Property TreeView() As TreeView
		Get
			Return mTreeView
		End Get
		Set(ByVal value As TreeView)
			mTreeView = value

			If value IsNot Nothing Then
				AddHandler mTreeView.AfterSelect, AddressOf tvwAfterSelect
			End If
		End Set
	End Property

	Protected Overrides Sub OnLinkClicked(ByVal e As LinkLabelLinkClickedEventArgs)
		MyBase.OnLinkClicked(e)

		If mTreeView IsNot Nothing Then
			Dim key As String = GetNodeKey(Me.Text, Me.Text.Substring(e.Link.Start, e.Link.Length))
			mTreeView.SelectedNode = mTreeView.Nodes.Find(key, True)(0)
			mTreeView.SelectedNode.EnsureVisible()
			mTreeView.Focus()
		End If

	End Sub

	Function GetNodeKey(ByVal path As String, ByVal Name As String) As String
		Dim p() As String = path.Split(New String() {mTreeView.PathSeparator}, StringSplitOptions.RemoveEmptyEntries)

		For w As Integer = 0 To p.Length - 1
			If p(w) = Name Then
				If w = p.Length - 1 Then Exit For
				ReDim Preserve p(w)
				Exit For
			End If
		Next

		Dim nod As TreeNodeCollection = mTreeView.Nodes

		For x As Integer = 0 To p.Length - 2
			nod = InternalFind(p(x), nod)
		Next

		For i As Integer = 0 To nod.Count - 1
			If nod(i).Text = Name Then
				Return nod(i).Name
			End If
		Next

		Return String.Empty

	End Function

	Function InternalFind(ByVal name As String, ByVal col As TreeNodeCollection) As TreeNodeCollection

		For i As Integer = 0 To col.Count - 1
			If col(i).Text = name Then
				Return col(i).Nodes
			End If
		Next

		Return col

	End Function


	Private Sub tvwAfterSelect(ByVal sender As Object, ByVal e As TreeViewEventArgs)
		Dim path() As String = mTreeView.SelectedNode.FullPath.Split(New String() {mTreeView.PathSeparator}, StringSplitOptions.RemoveEmptyEntries)
		Me.Links.Clear()
		Me.Text = mTreeView.SelectedNode.FullPath

		Dim start As Integer = 0
		Dim ends As Integer = path(0).Length

		For i As Integer = 0 To path.Length - 1
			Me.Links.Add(start, ends)
			start += path(i).Length + mTreeView.PathSeparator.Length

			If i + 1 > path.Length - 1 Then Exit For
			ends = path(i + 1).Length
		Next

		Erase path

	End Sub
End Class

لإستخدامها داخل برنامجك فقط قم بوضعها على الفورم ثم قم بتحديد اسم الـ TreeView من الخاصيه TreeView الموجوده بالأداه. و لكل Node داخل الشجره قم بوضع قيمه داخل الخاصيه Name لهذه الـ Node و يفضل ان لا يتكرر.

قمت بعمل مثال تطبيقى لهذه الاداه فقط قم بعمل Build للمشروع قبل ان تفتح الفورم حتى يتم عمل Build للاداه

هذه صوره للمثال

post-135620-1251283685_thumb.jpg

الكود فى المرفقات (الإصدار الأول)

TreeviewExample.rar

الكود (الإصدار الثانى)

TreeLink.rar

و الله ولى التوفيق

تم تعديل هذه المشاركة بواسطة Muhammad alaa في 16 ديسمبر 2009 في 03:39

مدونتي: C++ Tips and Tricks

#2

أنا لازم أقابلك علشان اخد منك مجموعة الكتب القيمة دى :D :D

إن قلت قال الله قال رسولـه همزوك همز المنكر المتعالي
أو قلت قد قال الصحابة والألـى تبعاً لهم بالقول والأعمال
أو قلت قـال الشافعي وأحمد و أبو حنيفة والإمام الغالي
صدوا عن وحي الإله ودينـه واحتالوا على حرام الله بالإحلال
يا أمةً لعبت بدين نبيها كتلاعب الصبيان في الأوحال
حاشا رسول الله يحكم بالهوى تلك إذاً حكومة الضلال

feed.1.gif

#3

:lol: :lol:

ياراجل انا اجبهالك لحد عندك

مدونتي: C++ Tips and Tricks

#4
Muhammad alaa كتب:
:lol: :lol:

ياراجل انا اجبهالك لحد عندك

ربنا يخليك يامحمد ,, هاكلمك على الخاص لما أروح البيت إن شاء الله لأن فعلا شكل الكتب دى يفتح النفس :P

1

إن قلت قال الله قال رسولـه همزوك همز المنكر المتعالي
أو قلت قد قال الصحابة والألـى تبعاً لهم بالقول والأعمال
أو قلت قـال الشافعي وأحمد و أبو حنيفة والإمام الغالي
صدوا عن وحي الإله ودينـه واحتالوا على حرام الله بالإحلال
يا أمةً لعبت بدين نبيها كتلاعب الصبيان في الأوحال
حاشا رسول الله يحكم بالهوى تلك إذاً حكومة الضلال

feed.1.gif

#5

منتظرك بعد الفطار

1

مدونتي: C++ Tips and Tricks

#6

بصراحة... أداة جميلة تشكر على مشاركتها معنا أخي محمد.

تم التحميل.

تحياتي...

1
#7

بصراحة... أداة جميلة و مفيدة جدا جدا جدا و هذا الكنترول محتاجه من زمان و لكني يا صديقي لم افهمها 100 بالمية لذلك لم انجح بتطبيقها على كودي طبعا لانني لا أفقه شيئ في برمجة الادوات ,

اخي محمد علاء أنا اعبئ الشجرة بكود مختلف عنك و ذلك لان الشجرة في الداتا بيس غير مرتبه (مبعثرة)

على كُلٍا أرفقت الكود الخاص بمثالي , مع عكسه على فكرتك لكنه لم يزبط عند الضغط على الأداة TreeViewLink1 حيث أنه يرجع الى رأس الـ :blink: Tree

طبعا بعد عدة محاولات لي أسألك أين الخلل في كودي :blush: ...... ؟ أليست هذه الاداة عامة لاي شجرة. :ohmy:

Accounts Tree View.rar

<EMBED src=http://www.abdelghafar.com/images/banners/bm2.swf width=486 height=60 type=application/x-shockwave-flash EMBED < menu="false" loop="true" quality="high">

#8

الخطأ هو خطئى من البدايه حث لم اقوم بأعطائكم كافة المعلومات عنها. الأداه تعمل مع اى Treeview فقط قم بتحديد Name لكل Node يتم وضعها.

داخل الكود الخاص بك قم بإضافة السطر التالى داخل الداله AddSubNode.

            SubNode.Name = drLine("ID").ToString

بعد هذا السطر

            SubNode.Tag = drLine("ID").ToString

و ستعمل معك الأداه بشكل جيد.

قمت بتحديث المشاركه الرئيسيه لتحتوى على هذه المعلومه.

ملحوظه اخرى: قم بإضافة ملف قاعدة البيانات داخل المشروع مباشرة (و ذلك عن طريق Add-> Existing Item) و بهذا سيتم نسخه لفولدر الـ Debug او الـ Release حسب عملك و ايضا ستتجنب حدوث تعديلات غير مرغوب فيها على النسخه الأصليه منها اثناء تنقيح كود البرنامج.

و الله ولى التوفيق

1

مدونتي: C++ Tips and Tricks

#9

اولا شكرا لك اخي محمد علاء على هذا التوضيح , و في الحقيقة هذا مثال للتعلم فقط :ph34r: , و لكن تعليقا على هذه الجملة

:cool:

اقتباس
و لكل Node داخل الشجره قم بوضع قيمه داخل الخاصيه Name لهذه الـ Node و يفضل ان لا يتكرر.

اعدت ارفاق المثال بشبكي على جدول آخر , انظر الى أداتك فهي لا تعمل بالشكل السليم , فانت قلت

اقتباس
يفضل ان لا يتكرر
و لكن في الحقيقة يجب ألا تتكرر الاسماء , هل يوجد في جعبتك حل لهذه المشكلة حتى تصبح أداتك مثالية , فهي بصراحة و بدون مجاملة اعجبتني كثيرا جدا , فهي عملية للشجرة الضخمة المتفرعة بكثرة , و معظم المشاريع تكون ذلك :happy:

ملاحظة : في الشجرة كلمة مدراء المشاريع متكررة و منهدسي المواقع و الدكيومنت كنترولر متكررة بكثرة ايضا :wink:

Accounts Tree View.rar

تم تعديل هذه المشاركة بواسطة assaf_abdullah في 9 ديسمبر 2009 في 23:29

<EMBED src=http://www.abdelghafar.com/images/banners/bm2.swf width=486 height=60 type=application/x-shockwave-flash EMBED < menu="false" loop="true" quality="high">

#10
اقتباس
و لكن في الحقيقة يجب ألا تتكرر الاسماء

نعم كلامك صحيح اخى، و لكن إن تكرر الإسم (Name) فى فرعين ليسوا تحت نفس المسار فلا مشكله.

لتلاشى مشكله تكرار الإسم يوجد امامك 3 حلول:

1 - قم بجعل قيمة الخاصيه Name تساوى قيمة حقل الـ PrimaryKey الخاص بالجدول (هذا على اعتبار ان الجدول به حقل PrimaryKey واحد فقط).

2 - قم بإنشاء متغير رقمى و مع كل مرة قبل إضافة فرع جديد قم بزيادته بواحده و قم بوضع القيمه داخل الخاصية Name.

3 - استخدم Guid.NewGuid().ToString لوضع قيمة لا تتكرر داخل خاصية الـ Name.

و الله ولى التوفيق

1

مدونتي: C++ Tips and Tricks

#11

عندما اردت استخدام اداة TreeViewLink داخل احد مشاريعى وجدت ان موضوع خاصية الـ Name هذا مرهق بالإضافة لكود البحث داخل الأداه نفسها لذا قمت بإعادة برمجتها من جديد بإسلوب مختلف و اسرع كثيرا هذه المره حيث تلك المره اتعامل مع الـ Handle الخاص بالـ TreeNode.

قمت بتسمية الاداه TreeLink

للتحميل اخر المشاركه الأولى ستجد كود الاداة الجديده.

و الله ولى التوفيق

تم تعديل هذه المشاركة بواسطة Muhammad alaa في 16 ديسمبر 2009 في 03:41

مدونتي: C++ Tips and Tricks

#12

لو سمحت انا عايز شرح للكود

وكيف يتم تعبئة الشجرة

ضروري جدا حضرتك تشرح الكود بتاع التعبية

ونان لو عايز اضيف في الشجر ازاي اقد اوصل للرقم اللي علية الدور

وازاي اعدل وازي احذف

فكرت كتير جدا فيها لحد لما خلاص جبت اخري بجد صعبة جدا

#13
اقتباس
لو سمحت انا عايز شرح للكود

وكيف يتم تعبئة الشجرة

ضروري جدا حضرتك تشرح الكود بتاع التعبية

ونان لو عايز اضيف في الشجر ازاي اقد اوصل للرقم اللي علية الدور

وازاي اعدل وازي احذف

فكرت كتير جدا فيها لحد لما خلاص جبت اخري بجد صعبة جدا

موضوع تعبئة الشجره يعتمد بشكل اساسى على جداول قاعدة البيانات و كيفية تنظيم البيانات داخلها و إليك مثال بسيط ليوضح لك الكيفيه:

بإفتراض انك قمت بتحميل المرفقات الموجوده بالمشاركه الأولى (الإصدار الأول) ستجد بها قاعدة بيانات Access داخلها جدول اسمه Category يحتوى على 3 اعمده هم ID و Name و ParentID.بيانات هذا الجدول هى اقسام للكتب و حيث ان كل قسم قد يوجد تحته اقسام اخرى و قد يندرج هذا القسم نفسه تحت اقسام اخرى و من هنا يأتى دور الحقل ParentID حيث داخله يتم تسجيل رقم القسم الرئيسى للحالى و إذا كان القسم لا يوجد رئيسى له يتم وضع صفر داخل هذا الحقل.

قبل التطرق لملء الشجره نحتاج لمعرفة بعض العمليات التى نستطيع عملها على هذه الشجره.

الأداه TreeView تحتوى على الخاصية Nodes (الأفرع) اى فرع موجود داخل هذه الخاصيه مباشرة يتم اظهاره داخل الشجره فى المستوى الأول اى لا يوجد مستوى افرع اعلى منه (هو المستوى الأول).

توجد العديد من الطرق لإضافة فرع داخل هذه الخاصيه، الفرع نفسه هو من نوع TreeNode و يحتوى على خاصيتين فى غاية الأهميه الأولى Text و التى تظهر قيمتها اماك على الشجره و الأخرى هى Name.

توجد داخل اداة الـ TreeView داله اسمها FindNode هذه الداله معاملين اولهم نص هذا النص يتم البحث به داخل الخاصية Name الموجوده داخل الـ TreeNode (الخاصية الثانية) فإذا حدث تطابق يتم اكمال عملية البحث و المعامل الثانى هو قيمة boolean ان كانت true سيتم البحث داخل كل الأفرع و إن كانت false سيتم البحث داخل الأفرع الرئيسيه فقط و فى النهايه يتم العوده بمصفوفه من TreeNode و تحتوى على كل الأفرع التى خاصية Name لها تحتوى على نفس القيمه التى تم تمريرها للداله FindNode.

بعد ان عرفنا كيفية التعامل مع اداة الشجره و كذلك عرفنا تنظيم الجدول لم يتبقى غير البدء بملء الشجره و يتم بمجموعه من الخطوات كالتالى:

1 - احضار البيانات من الجدول مرتبه حسب الـ ID (حتى لا يتم احضار صف الـ ParentID له لم يتم اضافته فى الشجره بعد).

2 - الدخول فى حلقة حول البيانات التى تم استرجعاها.

3 - اختبار حالة الحقل ParentID للصف الحالى فإن كان صفر يتم اضافته مباشرة داخل الخاصيه Nodes و يتم جعل الخاصية Name له تساوى قيمة حقل الـ ID لهذا الصف.

4 - إذا كان الحقل ParentID للصف الحالى لا يساوى صفر نستخدم الداله FindNode و نقوم بتمرير لها قيمة ParentID و القيمه العائدة (سنفترض انه توجد قيمه عائده) عيارة عن مصفوفه يتم اخذ اول عنصر و تخزينه داخل متغير مؤقت (tmp مثلا) ثم يتم اضافة الصف الحالى لفرع جديد و نجعل قيمه الخاصية Name له هى الـ ID لهذا الصف ثم يتم اضافة هذا الفرع للخاصية Nodes للفرع tmp.

5 - اكمال حلقة الدوران بالعوده إلى رقم 3 او الخروج بإنتهاء الحلقه.

اعتقد ان الأمر اصبح واضح للنكتب الكود

Imports System.Data
Imports System.Data.OleDb


Sub FillTree()
    Dim cn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Test.mdb")
    Dim cmd As OleDbCommand = cn.CreateCommand
    Dim dr As OleDbDataReader

    ' step 1
    cn.Open()
    cmd.CommandType = CommandType.Text
    cmd.CommandText = "select * from Category Order by ID"
    dr = cmd.ExecuteReader

    ' step 2
    While dr.Read
        ' step 3
        If CInt(dr("ParentID")) = 0 Then
            TreeView1.Nodes.Add(dr("ID").ToString, dr("Name").ToString)
        Else
            ' step 4
            Dim tmp As TreeNode = TreeView1.Nodes.Find(CStr(dr("ParentID")), True)(0)
            tmp.Nodes.Add(dr("ID").ToString, dr("Name").ToString)
        End If
    End While


    dr.Close()
    cmd.Dispose()
    cn.Close()
    cn.Dispose()

End Sub

و الله ولى التوفيق

تم تعديل هذه المشاركة بواسطة Muhammad alaa في 14 مايو 2010 في 08:53

مدونتي: C++ Tips and Tricks

#14

شكرااااااااااااا الله يعطيك العافيه وسلامه

مواضيع مشابهة