Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

TreeNodeCollection::IndexOfKey не ищет Node

11
28 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Рисую TreeView из БД:
где row[0] - уникальный индекс (автоинкримент)
row[1] - родительский индекс (ссылка на row[0])
row[2] - текстовое поле
запрос из бд упорядочен по row[1] для того что бы при прохождении от начала до конца каждое последующее значение уже имело родителя
Код:
TreeNodeCollection tnc = treeView1.Nodes;
            foreach (DataRow row in dt.Rows)
            {
               
                if ((int)row[5] == 0) //root
                {
                    tnc.Add(Convert.ToString(row[0]), (string)row[2]);
                }
                else
                {
                    int i = tnc.IndexOfKey(Convert.ToString(row[1]));
                    if (i>=0)
                        tnc.Nodes.Add(Convert.ToString(row[0]), (string)row[2]);
                }

проблема в этой строчке: int i = tnc.IndexOfKey(Convert.ToString(row[1]));
ищет индекс только для 0-го уровня
Как сделать что бы искал по всему TreeNodeCollection?
5
28 апреля 2008 года
hardcase
4.5K / / 09.08.2005
Попробуйте при построении дерева завести словарь узлов
Dictionary<int, TreeNode>:
Код:
Dictionary<int, TreeNode> nodes = new Dictionary<int, TreeNode>();
TreeNodeCollection tnc = treeView1.Nodes;
foreach (DataRow row in dt.Rows)
{
                int id = row[0];
                TreeNode node = new TreeNode(Convert.ToString(row[0]), (string)row[2]);
                nodes[id] = node;
                if ((int)row[5] == 0) //root
                {
                    tnc.Add(node);
                }
                else
                {
                    TreeNode parent = null;
                    if(nodes.TryGetValue(row[1], ref parent))
                        parent.Nodes.Add(node);
                }

(код не проверял - писал в браузере)

Но вообщето впихивать в код построения интерфейса запрос к БД - очень плохая практика.
11
28 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
сделал вот так:
Код:
DataTable dt = create_TV1TableAdapter1.GetData(0);
TreeNodeCollection tnc = treeView1.Nodes;
           
foreach (DataRow row in dt.Rows)
{

      if ((int)row[5] == 0) //root
          tnc.Add(Convert.ToString(row[0]), (string)row[2]);
     else
     {
         TreeNode []tnc1 = tnc.Find(Convert.ToString(row[1]), true);
         if (tnc[0] !=null)
            tnc1[0].Nodes.Add(Convert.ToString(row[0]), (string)row[2]);
      }          
}

[QUOTE=hardcase]
Но вообщето впихивать в код построения интерфейса запрос к БД - очень плохая практика. [/QUOTE]
Чем плохо? (TV рисуется один раз при запуске приложения, далее просто от него нужны индексы для запроса в БД)
Где надо?
Как сделать?

ЗЫ: интересует, насколько метод Find(...) будет быстрее/медленней C++ map<int, TreeNode*>
5
28 апреля 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: oxotnik333
Чем плохо? (TV рисуется один раз при запуске приложения, далее просто от него нужны индексы для запроса в БД)
Где надо?
Как сделать?


Это скорее вопрос проектирования архитектуры приложения.
Разделение логики его работы от интерфейса пользователя.
Я бы объявил отдельные классы, которые отвечают за сами "узлы" и уже с их помощью отображал бы дерево объектов.

11
29 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: hardcase
Это скорее вопрос проектирования архитектуры приложения.
Разделение логики его работы от интерфейса пользователя.
Я бы объявил отдельные классы, которые отвечают за сами "узлы" и уже с их помощью отображал бы дерево объектов.



Если честно, то плохо представляю как это можно в отдельный класс загнать..
Пример бы какой посмотреть, о чем вообще речь идет

5
29 апреля 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: oxotnik333
Если честно, то плохо представляю как это можно в отдельный класс загнать..
Пример бы какой посмотреть, о чем вообще речь идет


Более менее путевое обсуждение нашел здесь (запрос гуглу вида DAL DAO BLL).

Идея. Создается многослойное приложение (multi-tier app) каждый слой отвечает за четко определённые действия и работает напрямую только с предыдущим:

1) Уровень хранения Data Store, обычно реализуется в СУБД, это реляционные таблицы + [иногда] довольно простые хранимые процедуры для добавления, удаления, модификации строк.

2) Уровень доступа к данным Data Access Layer. Реализует сценарии доступа к данным, как то: использование типизированных датасетов, использование ORM (Object Relational Mapping) генераторов типа NHibernate, использование самописного ORM.
Обычно этот уровень предоставляет совего рода API для работы над данными и выполнением запросов - некоторые куски бизнесс-логики приложения из которых на следующем уровне сформируется законченный бизнесс-процесс.
Например, когда используется самописный ORM, то этот API - часто, всего лишь, обертки над вызовами хранимых процедур в СУБД + некоторое кеширование частых запросов.
На этом уровне также могут быть определены DTO (Data Transfer Object) объекты - специальные легковесные сущности, обычно представляющие конкретные строки в таблицах СУБД или коллекции строк (чем не датасет? ;) ); они могу использоваться как промежуточное звено для передачи данных на BLL уровень.

3) Уровень бизнесс-логики Bussines Logic Layer. Уровень на котором формируются бизнесс-объекты - сущности, реализующие абстракцию "реального мира". Т.е. если мы создаем базу данных DVD дисков, то бизнесс объектом станет DvdDisk, Artist и прочие подобные. Эти объекты позволяют выполнять какие-либо высокоуровневые действия (помещение диска в БД и одновременно занесение туда нового артиста) - бизнесс-логику.

4) Уровень представления User Interface. Это пользовательскй фронт-энд. Например, веб-страничка или форма настольного приложения. Интерфейс содержит лишь элементы представления бизнесс-объектов (деревья, таблички, выпадающие списки) и элементы для управления бизнесс-объектами.

Очень рекомендуется руководствоваться принципами MVC (Model View Controller) архитектуры при проектировании BLL и построении интерфейса пользователя. Критерий качества: BLL можно обернуть и в WinForms и в ASP.NET юзерский интерфейс (view), при этом не придется править ни единой строчки ни в нем, ни в нижележащих уровнях.

341
29 апреля 2008 года
Der Meister
874 / / 21.12.2007
Мож проще сделать класс, производный от TreeNode, содержащий ссылку на запись в таблице, ему соответствующую, а так же таблицу с записями дочерних элементов, а само дерево строить посредством серии запросов SELECT * FROM TableName WHERE ParentID = @id? Дерево же всё равно строится лишь единожды. Тогда можно получать возможность более гибкого управления данными.
Ну, типа так:
Код:
class MyTreeNode : TreeNode
{
    public MyRowType DataSource;
    private MyTableType m_Childeren;

    public MyTableType Childeren
    {
        get
        {
            if (m_Childeren == null)
                m_Childeren = new MyTableType();
            return m_Childeren;
        }
    }

    public void UpdateData(bool Save)
    {
        if (DataSource != null)
        {
            if (Save)
            {
                try
                {
                    MyDataAdapter.Update(DataSource);
                    DataSource.AcceptChanges();
                }
                catch
                {
                }

                foreach(MyTreeNode child in this.Nodes)
                {
                    child.UptateData(true);
                }
            }
            else // !Save
            {
                this.Text = DataSource[2];
                MyDataAdapter.FillChilderen(Childeren, (int)DataSource[0]);
                foreach(MyRowType child in Childeren)
                {
                    item = new MyTreeNode();
                    item.DataSource = child;
                    item.UpdateData(false);
                }
            }
        }
    }
}

PS Аналогично, код писан навскидку в браузере
11
29 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Der Meister
Мож проще сделать класс, производный от TreeNode, содержащий ссылку на запись в таблице, ему соответствующую, а так же таблицу с записями дочерних элементов, а само дерево строить посредством серии запросов SELECT * FROM TableName WHERE ParentID = @id? Дерево же всё равно строится лишь единожды. Тогда можно получать возможность более гибкого управления данными.



такая схема будет тормозная, т.к. записей м.б. весьма и весьма много (пробовал на 100 000) рисует очень долго.
долго думал над алгоритмом быстрого рисования, в результате остановился на том что написал выше, только еще его подредактировал, в соответсвии с советом hardcase
вот что получилось:

Код:
TreeNodeCollection tnc = treeView1.Nodes;
Dictionary<int, TreeNode> NodeMap = new Dictionary<int,TreeNode>();
treeView1.BeginUpdate();
foreach (DataRow row in dt.Rows)
{
   if ((int)row[5] == 0) //root nodes
   {
      NodeMap[(int)row[0]] = tnc.Add(Convert.ToString(row[0]), (string)row[2]);
    }
    else //child nodes
    {
       TreeNode parent;
       if (NodeMap.TryGetValue((int)row[1], out parent))
          NodeMap[(int)row[0]] = parent.Nodes.Add(Convert.ToString(row[0]), (string)row[2]);
    }          
}
treeView1.EndUpdate();

всего на 100 000 записей уходит около 30 сек.

ЗЫ: VCL от борланда по такой же схеме за 2.5 мин строит
341
29 апреля 2008 года
Der Meister
874 / / 21.12.2007
Моя модель упрощает организацию процесса отложенной загрузки данных о дочерних узлах, что, в твоём случае, явно будет решением, способным сократить время построения с 30 до 0.5 секунд, а то и до меньшей величины. Собсна, об этом и намекало свойство, реализующее отложенное создание таблицы с данными о дочерних записях. Кроме того, поиск дочерних записей, в твоём случае, - ресурсоёмкая операция, и было бы логичнее нагрузить её на сервер, который, скорее всего, будет более производительным, нежели клиентская машина. Не забывай, что 30 секунд - время построения дерева на твоей машине. Плюс ко всему, ниличие продвинутой индексации в СУБД, скорее всего, даст более быстрые результаты поиска, чем поиск в твоей программе по словарю. При оложенном же заполнении резко упадёт нагрузка как на сервер (во всяком случае, канал/pipe), так и на клиентскую часть
11
29 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Der Meister
Моя модель упрощает процесс отложенной загрузки данных дочерних узлов, что, в твоём случае, явно будет решением, способным сократить время построения с 30 до 0.5 секунд, а то и до меньшей величины. Собсна, об этом и намекало свойство, реализующее отложенное создание таблицы с данными о дочерних записях



появляется дополнительный гемор с рисованием крестиков на тех нодах у которых есть подчиненые

ЗЫ: сервер делает всего 1(один) запрос и выдает упорядоченное по ParentIndex представление базовой таблицы (таким образом для каждой последующей записи уже есть Parent, для этого и загоняю в словарь все ноды), потом я проято програмно пробегаюсь по всем записям и строю дерево

341
29 апреля 2008 года
Der Meister
874 / / 21.12.2007
Цитата: oxotnik333
появляется дополнительный гемор с рисованием крестиков на тех нодах у которых есть подчиненые


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

Организация выполнения любого из этих действий не должна, по идее, вызвать у тебя особых проблем.

11
29 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Der Meister
Я считаю, что лучше потратить 2 часа на организацию проверки наличия дочерних узлов, чем каждый раз тратить по пол-минуты на запуск. Кроме того, в зависимости от ситуации, можно предпринять как минимум три действия, с решением этой проблемы связанных:
- запрашивать количество дочерних узлов
- отображать кнопку разворачивания всегда, а запрашивать дочерние узлы лишь при необходимости
- запрашивать дочерние записи для всез видимых узлов дерева

Организация выполнения любого из этих действий не должна, по идее, вызвать у тебя особых проблем.



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

341
29 апреля 2008 года
Der Meister
874 / / 21.12.2007
Сортировка на сервере происходит ничуть не быстрее фильтрации (эт я мягко выразился), а вот объём пересылаемых через канал данных для решения, ориентированного на удовлетворение запросов сотен пользователей, стоит оч даж дорого. По-моему, политика отдела автоматизации любой здравомыслящей конторы такова: проще купить один нормальный сервак, чем сотню компов пользакам. Ладно, тебе видней... Тем более, что мозгам и задницам админов и товарисчей из службы поддержки по-любому уже не привыкать.
5
29 апреля 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: oxotnik333
Я считаю что лучше при загрузке один раз подождать (визуализировав процесс загрузки)


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

41K
02 октября 2008 года
AZHOO
4 / / 25.09.2008
tnc.Add(Convert.ToString(row[0]), (string)row[2]);
Такой вопрос, каким макаром потом вытащить Convert.ToString(row[0]) из три вью??
То есть получить это значение??
11
02 октября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: AZHOO
tnc.Add(Convert.ToString(row[0]), (string)row[2]);
Такой вопрос, каким макаром потом вытащить Convert.ToString(row[0]) из три вью??
То есть получить это значение??


 
Код:
TreeView::SelectedNode::Name
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог