Модераторы: gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Заполнение treeView из БД 
V
    Опции темы
IgorDV
Дата 6.2.2008, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 14.4.2007

Репутация: нет
Всего: нет



Приветствую.
Вообщем есть вопрос:
У меня есть таблицы в БД (MainPartSubPart)
MainPart главная, с ней по ключу связана SubPart. таблицы простые id и name_ поля только + во второй parent_id.
как мне заполнить treeView.
Как это реализовать на словах - понятно.
Взять запрос в двойном цикле создавать ноды. Но вот как это на деле-я не знаю.
Как по таблице цыклом пробежаться? Как создавать Child Ноды?
PM MAIL ICQ   Вверх
Able
Дата 6.2.2008, 21:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 82
Регистрация: 13.6.2006
Где: Тюмень

Репутация: нет
Всего: 2



PM MAIL WWW ICQ   Вверх
thomas
Дата 7.2.2008, 01:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доцент... почти
***


Профиль
Группа: Завсегдатай
Сообщений: 1385
Регистрация: 3.10.2006
Где: " Сказочное королевство"

Репутация: 35
Всего: 65



IgorDV
Приветствую.
Имею типизированный датаСет с двумя таблицами.
При загрузке формы гружу данные в таблицы датаСет и отображаю это дело в treeview.
Код

private void Form1_Load(object sender, EventArgs e)
        {
            this.tblGroepTableAdapter.Fill(this.myDataSet.tblGroep);
            this.tblCategorieTableAdapter.Fill(this.myDataSet.tblCategorie);
            // сначала пробежал по всем строкам главной таблицы
            foreach (DataRow dr in this.myDataSet.tblGroep.Rows)
            {
                TreeNode node = new TreeNode();
                node.Text = dr["GroepNaam"].ToString();
                node.Name = dr["GroepId"].ToString();
                treeView1.Nodes.Add(node);
                //  а тут пробегаюсь по строкам подчиненной таблицы, но только по тем,
                //  которые относятся к текущей строке главной таблицы
                foreach (DataRow r in this.myDataSet.tblCategorie.Select("GroepId = " + node.Name))
                {
                    node.Nodes.Add(r["CategorieNaam"].ToString());
                }
            }
        }


Всё.  smile 


--------------------
Крепко жму горло, искренне ваш Thomas. (С)vingrad
Некоторые сорта флоры буквально за одно мгновение превращают нас в фауну!
Проблемы негров шерифа не волнуют.
PM MAIL   Вверх
IgorDV
Дата 7.2.2008, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 14.4.2007

Репутация: нет
Всего: нет



Спасибо. smile
PM MAIL ICQ   Вверх
Softaz
Дата 17.2.2008, 23:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


wasm
**


Профиль
Группа: Участник
Сообщений: 373
Регистрация: 16.1.2006

Репутация: 4
Всего: 16



Очень хочу посмотреть на такое дерево, когда в БД будет тыщь 10 узлов  smile 
Надо грузить только первый уровень (несколько нод из него если их много), потом обрабатывать событие BeforeExpand и загружать чилдов раскрывшегося нода и так далее.


--------------------
Разочарованный в .NET
PM MAIL WWW   Вверх
unicuum
Дата 19.2.2008, 03:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 16.3.2005
Где: Рашка

Репутация: нет
Всего: 8



Цитата(Softaz @  17.2.2008,  23:23 Найти цитируемый пост)
Очень хочу посмотреть на такое дерево, когда в БД будет тыщь 10 узлов  smile 

10 тысяч это совсем немного, надо поставить TreeView.BeginUpdate до начала заливки и TreeView.EndUpdate после, всё работает мгновенно. Вообще, я могу конечно тебе дать такую программу, но ничего интересного в ней нет, загрузка 10 тысяч проходит мгновенно даже на пентиуме II.

Поскольку свой код мне писать влом буду комментировать то, что сделал thomas. Про BeginUpdate и EndUpdate было сказано, в стандартных примерах МСДН ещё курсор меняют на ожидающий, да и самому можно, что угодно придумать.

Интересно так же отметить, что TreeNode.Name (в коде node.Name) в .NET Framework 1.1 отсутствует. Значит был использован .NET Framework 2.0, а может и выше, за последним я уже не следил. Это строковый идентификатор, а ключ таблицы как правило int (целочисленный).

В общем, техника работы с древовидным списком сводится к следующему. Вот в вышеупомянутом примере есть treeView1.Nodes.Add(node);. node создан так TreeNode node = new TreeNode();, т.е. от класса TreeNode. А нужно создать новый класс, наследованный от TreeNode, добавить туда необходимые свойства, например идентификатор таблицы, тип узла и так далее, и создавать экземпляр этого класса.

Потом преобразуя его в TreeNode с помощью метода Add класса TreeNodeCollection добавляем его в древовидный список. Назову пронаследованный класс для удобства InheritTreeNode. Ну так вот, раз объект находящийся в коллекции древоузлов изначально был создан конструктором InheritTreeNode, то при извлечении TreeNode можно сделать обратное преобразование в InheritTreeNode.

То есть преобразования InheritTreeNode => TreeNode получаются в любом случае, а для TreeNode => InheritTreeNode надо чтобы объект был создан конструктором класса более глубоким по иерархии, там нюансы, но это уже заморочки языка. Таким образом программист получает расширенный функционал (узлы могут изображать папки, файлы, или всё что в голову придёт, дополнительный код позволяет правильно обрабатывать узлы) и синхронизацию с базой данных (свойство ID из бд или отсоединённого объекта). И не стоит забывать о том, что переопределять можно не только узлы, но и вообще всё что угодно.

По поводу заливки. Некоторые применяют заливку вначале работы программы и загрузку из древосписка в конце. Недостаток в том, что при аварийном завершение программы (электричество отрубили, или сглючила программа, ОС и так далее), данные не запишутся. Приведённый мной способ позволяет держать синхронизацию в любой момент времени, но опять же, от способа зависит и возможная структура таблицы для хранения древовидных узлов.

Вообще, способов хранения данных не мало. Например, в загрузке и выгрузке при открытии и закрытии программы, общую структуру можно представить как полностью раскрытый список, там так прямо и записывают, а таблицу просто очищают перед записью. У thomas например две таблицы, одна группа, а другая то что внутри, и из группы происходит постоянный скачок внутрь другой таблицы, проход по ней фильтром в поисках нужных узлов, и по строковой переменной.

Как известно древовидный список основывается на древовидном графе, он в свою очередь является подмножеством общего графа. А значит для записи любого уровня вложенности узлов достаточно таблицу связей и таблицу узлов. Однако в данной и конкретной задаче этого не требуется.Что же ещё можно сказать, ну пожалуй, когда я делал похоже, то во вложенном цикле использовал DataRow.GetChildRows. У меня была установлена зависимость, причём я её просто сгенерил через xsd.

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

узел с полями (а надо бы свойства)
Код

Public Class InheritTreeNode
    Inherits TreeNode

    Public isMainPart As New Boolean
    Public idMainPart As New Integer
    Public idSubPart As New Integer
End Class


класс, по идее нужно писать переопределение от TreeView, но у меня обычный объект, так как в первом случае надо понимать, что такое базовый конструктор, а такие люди уже не задают вопросы
Код

'... какой-то класс

    Public trvMyTree As TreeView
    ' Набор данных.
    Friend WithEvents dsMyDataset As MyDataset

    Public Sub FillMyTreeView()
        BeginUpdate()

        trvMyTree.Nodes.Clear()

        Dim nsMainPart As InheritTreeNode
        Dim ndSubNode As InheritTreeNode

        For Each rowMainPart As DataRow In dsMyDataset.tblMainPart.Rows

            nsMainPart = New InheritTreeNode
            nsMainPart.isMainPart = True
            nsMainPart.idMainPart = CInt(rowMainPart(0))
            nsMainPart.Text = CStr(rowMainPart(1))
            trvMyTree.Nodes.Add(nsMainPart)

            For Each rowSubPart As DataRow In row.GetChildRows(dsMyDataset.Relations("tblMainParttblSubPart"))
                ndSubNode = New InheritTreeNode
                ndSubNode.isMainPart = False
                ndSubNode.idMainPart = CInt(rowMainPart(0))
                ndSubNode.idSubPart = CInt(rowSubPart(0))
                ndSubNode.Text = CStr(rowSubPart(1))
                node.Nodes.Add(ndSubNode)
            Next

        Next

        EndUpdate()
    End Sub 'FillMyTreeView


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

    Private Sub TreeView1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TreeView1.DoubleClick
        If Not TreeView1.SelectedNode Is Nothing Then

            Dim sln As InheritTreeNode = CType(TreeView1.SelectedNode, InheritTreeNode)

            If sln.isMainPart Then
                MsgBox("Главная часть: " & sln.idMainPart)
            Else
                MsgBox("Подразделение: " & sln.idSubPart & vbNewLine & "находится в " & sln.idMainPart & " главной части")
            End If

        End If

    End Sub


Вот как-то так и надо писать, только с учётом принципов ООП, а не как попало.


--------------------
user posted image
обычный день на винграде
PM   Вверх
Softaz
Дата 19.2.2008, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


wasm
**


Профиль
Группа: Участник
Сообщений: 373
Регистрация: 16.1.2006

Репутация: 4
Всего: 16



Цитата
10 тысяч это совсем немного, надо поставить TreeView.BeginUpdate до начала заливки и TreeView.EndUpdate после, всё работает мгновенно. Вообще, я могу конечно тебе дать такую программу, но ничего интересного в ней нет, загрузка 10 тысяч проходит мгновенно даже на пентиуме II.

Ну не совсем мгновенно. Дерево с трехуровневыми нодами грузилось за 2-5 секунд.
Здесь важно, насколько много будет узлов. Если меньше тысячи и программа будет локальной, то нефиг мудорствовать.

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


Это сообщение отредактировал(а) Softaz - 19.2.2008, 11:50


--------------------
Разочарованный в .NET
PM MAIL WWW   Вверх
unicuum
Дата 20.2.2008, 02:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 16.3.2005
Где: Рашка

Репутация: нет
Всего: 8



Цитата(Softaz @  19.2.2008,  11:43 Найти цитируемый пост)

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

Я согласен насчёт загрузки первого уровня, но не ради десяти тысяч, а скажем ради миллиона или более узлов. Здесь ведь ещё зависит от структуры хранения самого списка в БД. Ведь можно записывать в одной таблице узлы и связи (указатель на родительский узел) всего древосписка, а можно иначе. Всё зависит от того что выбрал программист. Оптимизация безусловно очень важна. По идее если узлов будет 10 миллионов, 100 миллионов, то алгоритмы работы БД должны быть до предела оптимизированы. Ну 10 тысяч для нынешних компьютеров не серьёзно. smile 


--------------------
user posted image
обычный день на винграде
PM   Вверх
Softaz
Дата 20.2.2008, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


wasm
**


Профиль
Группа: Участник
Сообщений: 373
Регистрация: 16.1.2006

Репутация: 4
Всего: 16



Цитата(unicuum @ 20.2.2008,  02:22)
Ну 10 тысяч для нынешних компьютеров не серьёзно. smile

Я больше по части КПК.

Добавлено через 2 минуты и 2 секунды
На 3-х уровневое древко (с простенькой менюшкой типа создать-править-удалить) ушло около недели и 900 строчек кода.


--------------------
Разочарованный в .NET
PM MAIL WWW   Вверх
Siscipsak
Дата 1.9.2022, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 31.8.2022

Репутация: нет
Всего: нет




Модератор: Сообщение скрыто.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
stab
mr.DUDA
Exception

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, stab, mr.DUDA, Exception.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Базы данных под .NET | Следующая тема »


 




[ Время генерации скрипта: 0.1573 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.