Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 395

TreeView и коллекция моего класса

23.04.2017, 22:27. Показов 2763. Ответов 26
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Предположим существует класс.

C#
1
2
3
4
5
6
class S
{
    string name; //ноды верхнего уровня
    int[] arr; //субноды
}
List<S> sList = new List<S>();
Мне хотелось бы сделать наглядное отображение всего что имеется в этой коллекции на TreeView.
Я умею такое делать с коллекциями, содержащими стандартные типы. Но как сделать такое, с коллекцией собственных типов?
Разумеется нужно, чтобы изменения в членах коллекции отражались и на форме.
Заранее спасибо.

Добавлено через 20 секунд
Если можно, дайте небольшой пример.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
23.04.2017, 22:27
Ответы с готовыми решениями:

Коллекция объектов моего класса
Привет :) Я только начал изучение PHP, поэтому просьба не кидаться в меня камнями. Я создал свой класс, и теперь мне надо...

Музыкальная коллекция. taglib treeview QAbstractItemModel
Добрый день! Нашел в сети такой вот редактор тегов - http://code.google.com/p/qtagger/ Десять раз прочитал документацию -...

Коллекция узлов TreeView и передача аргументов
Итак, опять я в недоумении. Перед добавлением нового узла в TreeView выполняется некая проверка (функцией GetBusyNumbers) на...

26
 Аватар для Aferuga
645 / 529 / 324
Регистрация: 20.05.2015
Сообщений: 1,471
24.04.2017, 04:35
Посмотрите здесь
0
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 395
24.04.2017, 17:01  [ТС]
Спасибо. А без базы данных нельзя? Я с ними не работал.
Нужно просто с коллекцией собственных классов.
0
478 / 241 / 74
Регистрация: 25.05.2012
Сообщений: 1,138
Записей в блоге: 1
24.04.2017, 17:56
lonelyhunter, 2 вложенных цикла?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
24.04.2017, 19:43
Цитата Сообщение от lonelyhunter Посмотреть сообщение
Мне хотелось бы сделать наглядное отображение всего что имеется в этой коллекции на TreeView.
Я умею такое делать с коллекциями, содержащими стандартные типы. Но как сделать такое, с коллекцией собственных типов?
Как вариант - использовать FastTree, вместо TreeView.
Цитата Сообщение от lonelyhunter Посмотреть сообщение
Если можно, дайте небольшой пример.
FastTree: Checkbox у конкретных узлов Tree
2
 Аватар для Aferuga
645 / 529 / 324
Регистрация: 20.05.2015
Сообщений: 1,471
24.04.2017, 22:46
lonelyhunter, можно, главное создать список NodeItems, а затем передать его LoadFast.
Ниже пример с прикрученным к проекту классом.
0
18 / 18 / 8
Регистрация: 11.01.2016
Сообщений: 54
25.04.2017, 16:44
Студии под рукой нет, но как-то так.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
        public class S
        {
            public string name; //ноды верхнего уровня
            public int[] arr; //субноды
        }
        List<S> sList = new List<S>();
 
 
        private void sListToNodes()
        {
            if (treeView1.Nodes.Count > 0) { treeView1.Nodes.Clear(); }
            if (sList != null && sList.Count > 0)
            {
                int i = 0;
                foreach (S itm in sList)
                {
                    if (itm.name != null)
                    {
                        TreeNode tn = new TreeNode();
                        tn.Name = i.ToString();
                        tn.Text = itm.name;
                        tn.ToolTipText = itm.name;
                        treeView1.Nodes.Add(tn);
                        if (itm.arr != null && itm.arr.Length > 0)
                        {
                            sListChildToNodes(itm, tn);
                        }
                        i++;
                    }
                }
            }
        }
 
        private void sListChildToNodes(S ParentClass, TreeNode parentNode)
        {
            int i = 0;
            foreach (int itm in ParentClass.arr)
            {
                TreeNode tn = new TreeNode();
                tn.Name = ParentClass.name + "_" + i.ToString();
                tn.Text = itm.ToString();
                tn.ToolTipText = itm.ToString();
                parentNode.Nodes.Add(tn);
                i++;
            }
        }
Добавлено через 9 минут
Это просто чтобы отобразить коллекцию. При желании можно унаследовать свой класс от TreeNode и делать в нём вообще что угодно. Раньше я так и делал. Сейчас я просто пишу свой контрол, унаследовав его от TreeView и в нём заворачиваю вообще всё (так бы это выглядело таким образом MyTreeView1.ListOfMyclass = sList. А при изменении коллекции, чтобы не перерисовывать всё заного, можно, при желании, прикрутить событие, которое и изменит нужную ноду.
0
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 395
25.04.2017, 17:09  [ТС]
Я тоже вручную отображал. Но дело в том, что данные для этой TreeView находятся в другом классе, в другом потоке. И соответственно, когда юзер должен удалить какой-то элемент, он должен удалить его и класса движка и из элемента интерфейса. В общем, мне есть над чем подумать.) Все это еще обновляется через равные периоды времени. И не дай бог, юзер захочет удалить именно в активный момент. Борюсь короче.
0
18 / 18 / 8
Регистрация: 11.01.2016
Сообщений: 54
25.04.2017, 18:11
В том, другом классе создаёте событие. В этом на него подписываетесь. Перерисовываете по событию. В этом классе обновление по времени не нужно. Если будут накладки, то вставляете механизм блокировки. В общем там всё просто.
И да, если желаете работать с данными другого класса/потока напрямую (что я бы не советовал), то я стал бы использовать не лист, а ConcurrentDictionary. Чудная вещь

Добавлено через 26 минут
Т.Е. Как-то так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Первый класс{
        public class MyEventArgs : EventArgs
        {
            public  List<S> sList { get; set; }
            public Exception ex { get; set; }
            public MyEventArgs (List<S> SList, Exception Ex) { sList = SList; ex = Ex; }
        }
 
        public delegate void UpdateEventHandler(object sender, MyEventArgs e);
        public static event UpdateEventHandler UpdateEvent;
        static void OnSEND(MyEventArgs e)
        {
            UpdateEvent?.Invoke(null, e);
        }
 
После изменения списка вызываем: OnSEND(new MyEventArgs(SList, null)); (либо передаём эксепшн если надо)
 
}
 
Второй класc, в котором GUI
{
 
В нём, например при загрузке формы, подписываемся на событие,
            Первый класс.UpdateEvent += updateEvent; 
 и добавляем обработчик:
 
        internal delegate void ObjectDelegate(Первый класс.MyEventArgs e);
 
        private void updateEvent(object sender, Первый класс.MyEventArgs e)
        {
            try
            {
                this.BeginInvoke(new ObjectDelegate(refreshTreeView), e);
            }
            catch (Exception ex)
            { MessageBox.Show(ex.Message, "Перехват исключения"); }
        }
 
Ну а дальше 
      private void refreshDataTables(Engine.SqLite.SqlStock.SqliteUpdateEventArgs e)
        {
            if (e.ex != null) { MessageBox.Show(e.ex.Message); }
            else
            {..... и то что я написал постом выше.
             }
}
Если есть опасность, что события пойдут пулеметом, а перерисовка долгая(тогда бы я вообще посоветовал тривью не юзать), просто сделайте флаг блокировки перерисовки, и флаг необходимости перерисовки и храните последнюю версию аргумента события. Не реагируйте на событие во время перерисовки, но если во время перерисовки пришло новое событие, перерисуйте с новыми данными. Колхоз конечно, но должно работать без нареканий. Но если много данных, тормоза будут. Поэтому я свои контролы и пишу.

Добавлено через 2 минуты
ПыСы Статичное событие лучше вообще вынести за все эти классы, и как дёргать так и реагировать на него откуда угодно. Очень удобно передавать между разными классами и потоками всё что угодно и когда угодно .

Добавлено через 5 минут
Для этого в MyEventArgs добавьте ещё кто посылает - и подпишитесь на него с обоих классов. и реагируйте соответственно.

Добавлено через 13 минут
ПыСыСы В другом случае можно создать 2 события, одно - когда изменились данный, второе, когда юзер хочет поменять данные. и подписаться на них соответственно из своих классов. В любом случае выполнятся всё будет в нужных потоках и накладок не будет (писал сервер/клиента на сокетах для нашего производства. Сервер хранил эталонную БД и о любых изменениях её сообщал БД клиентов. Классы работавшие с БД клиентов были отдельным потоком, сокет-клиентская часть так же, была отдельным потоком. Все данные перебрасывались событиями. Третий год работает - нареканий нету.)
0
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 395
25.04.2017, 18:15  [ТС]
попробуй, спасибо)
0
18 / 18 / 8
Регистрация: 11.01.2016
Сообщений: 54
25.04.2017, 18:21
Копировал у себя, тут, естественно, вместо
C#
1
private void refreshDataTables(Engine.SqLite.SqlStock.SqliteUpdateEventArgs e)
должно быть
C#
1
private void refreshTreeView(Первый класс.MyEventArgs e)
0
 Аватар для Aferuga
645 / 529 / 324
Регистрация: 20.05.2015
Сообщений: 1,471
26.04.2017, 06:22
Я тоже раньше грузил данные в цикле через
C#
1
treeView1.Nodes.Add(tn);
поштучно подходит при ручном добавлении, а вот при массовом он начинает грузиться слишком долго(то есть если 10 нодов грузится 10мс, то 100 уже будет грузиться 150 и дальше по нарастающей). Асинхронка такую проблему решает только внешне.
От мерцания и проблем с прорисовкой помогли эти строчки:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        public TreeViewFast()
        {
                        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        }
 
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
                return cp;
            }
        }
0
 Аватар для Aferuga
645 / 529 / 324
Регистрация: 20.05.2015
Сообщений: 1,471
26.04.2017, 07:34
Есть демка для сравнения
Вложения
Тип файла: rar TreeViewFast.rar (67.7 Кб, 13 просмотров)
0
18 / 18 / 8
Регистрация: 11.01.2016
Сообщений: 54
26.04.2017, 13:56
Двойная буфферизация конечно хорошая вещь, можно и прорисовку вообще отключать (SetVisibleCore) и показывать на фоне какую-нить красивую анимацию ожидания, вот только, когда я давненько пытался оптимизировать всю эту байду, толк от неё так и не увидел.
Глянул мельком, ИМХО, Ваш пример не вполне корректен. В первом случае Вы бегаете по нодам самого контрола, а во втором, вы загнали всё в Dictionary и бегаете уже по нему. Оттуда и выигрыш. если сделать не 5К а 50К, то бегая по тривью можно уже повеситься. Свангую, что если точно так же засуну данные в дататейбл - и буду бегать по ним, то у меня получится сравнимо с Вашими результатами. без всяких буфферизаций и прочего. Должно быть помедленней за счёт переноса в БД, но не на много - в зависимости от размера данных и с первым случаем конечно будет так же не сравнить. Чуть позже закину Ваш пример с третим тривью
0
18 / 18 / 8
Регистрация: 11.01.2016
Сообщений: 54
26.04.2017, 14:40
Вот как-то так. Это вопрос тупо организации данных.
Вложения
Тип файла: zip TreeViewFast.zip (88.4 Кб, 15 просмотров)
0
 Аватар для Aferuga
645 / 529 / 324
Регистрация: 20.05.2015
Сообщений: 1,471
27.04.2017, 04:24
Цитата Сообщение от SvetR Посмотреть сообщение
толк от неё так и не увидел.
Да можете в проект добавить увидите разницу.
Если с использовать буфферизацию мой может отобразится быстрее вашего хотя время покажет другое и даже если ваш будет заполняться первым. Хотя буфферизацию также легко можно прикрутить и к вашему варианту.
Цитата Сообщение от SvetR Посмотреть сообщение
без всяких буфферизаций и прочего
К слову в примере и не используется буфферизация.
Цитата Сообщение от SvetR Посмотреть сообщение
Вот как-то так. Это вопрос тупо организации данных.
Сложнее когда заполнение происходит из разных таблиц. Тогда к слову и встал вопрос оптимизации, потому что как и в примере приходилось использовать find.
0
 Аватар для Aferuga
645 / 529 / 324
Регистрация: 20.05.2015
Сообщений: 1,471
27.04.2017, 09:41
Цитата Сообщение от SvetR Посмотреть сообщение
если сделать не 5К а 50К
Да че мелочиться можно сразу миллион
Миниатюры
TreeView и коллекция моего класса  
0
18 / 18 / 8
Регистрация: 11.01.2016
Сообщений: 54
27.04.2017, 13:59
О чём спорим не пойму. Как я и говорил, это вопрос организации данных и всё. Сам контрол вообще не причём и работает с одинаковой скоростью во всех трёх случаях и всякие шаманства с ним ничего практически не дают. В том, что Dictionary быстрее SQL запроса к DataTable (тем более на миллион записей), а "бегание" каждый чих по всем нодам медленней их обоих вместе взятых я сразу сказал, с этим никакой дурак спорить не будет. Вот Ваш миллион записей. Скорость самого тривью у Вас, если замерить, будет та же что и у меня.

Кликните здесь для просмотра всего текста
P.S. Немного лирики. По моему глубокому убеждению нет "плохих" или "хороших" вариантов. Есть только удовлетворяющие требованиям в данной конкретной ситуации. Вы описали стоящую перед Вами задачу и удовлетворившее решение. Когда я воследний раз имел дело с тривью, самое большое, что там в нём было - это разделы склада и категории инвентарных объектов, а их ну ни как не может быть больше тысячи - двух наименований. Зато вообще все данные (из которых вообще весь склад, включая и инвентарные единицы - хорошо если одна десятая общих данных) хранились в Mysql на сокет-сервере с которой кроссплатформенные(!) клиенты общались сериализованными(ProtoBuf) и зашифрованными обновлениями БД. Клиентские же БД - были sqlite-копиями серверной, зашифрованные по ключу устройства, получаемого с сервера после авторизации пользователя. Потому у меня в том проекте вообще все контролы были заточены под работу с БД. А из мелкого тривью вообще вышел монстр, который делал как GUI по фантазиям упыре.. тьфуты, начальства (моментальный поиск как поисковиках, фильтрацию нод, всякие DragNDrop-ы и прочий хлам), так же сам работал с локальной БД, предоставляя любые, даже малосвязанную с ним данные другим классам, сам обращался с классом сокет-клиента, по поводу внесения изменения связанных с ним данных и т.д. ( если что, уровень абстракции был достаточно высоким). Когда на pc-клиенте пара сотен не особо связанных между собой форм, не знаю как кому, но мне проще такие вещи делать блоками и потом их тупо уже расставлять. По моему, был он не особо быстрым, но никто на тормоза и затыки никогда не жаловался. Про то что вышло из Датагрида - вот он как раз был одним из основных контролов, даже говорить не буду.
Миниатюры
TreeView и коллекция моего класса  
0
 Аватар для Nalik
176 / 124 / 49
Регистрация: 30.11.2012
Сообщений: 1,330
10.10.2020, 22:26
Storm23, последовал твоему совету и попробовал FastTree. Но что-то не могу понять как там получать Node под курсором? Свойства HitTest там нет, GetChildAtPoint возвращает null.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
10.10.2020, 23:57
Цитата Сообщение от Nalik Посмотреть сообщение
как там получать Node под курсором?
Сначала получаем индекс элемента под курсором методом
C#
1
public int PointToIndex(Point p)
А затем получаем объект нода через метод
C#
1
public virtual object GetNodeByIndex(int index)
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
10.10.2020, 23:57
Помогаю со студенческими работами здесь

Коллекция объектов одного класса в экземпляре другого класса
Извиняюсь, если написал не совсем адекватный заголовок. В общем, у меня есть такая модель: public class AssetsFlowsViewModel { ...

Коллекция созданная из класса в коллекции из класса
Разбираюсь с C#, для практики решил написать просто приложение: на форме (WPF) есть 2-ва ListView, в правом находится список людей (Имя и...

Коллекция их обобщенного класса
&quot;Создать коллекцию, представляющую собой обобщенный класс, ограниченный только объектами-наследниками класса FileStream&quot; ...

Сериализация в XML (коллекция внутри класса)
Здравствуйте. Объекты класса Student сериализируется и с ним все хорошо. Объекты Group не сериализируются польностью, в xml-файле...

Список моего класса
Здравствуйте, у меня была программа и всё работало, но её удалили, а сохранить я не успел) пытаюсь восстановить по памяти и есть одна...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
Программный отбор значений справочника
Maks 21.03.2026
Установка программного отбора значений справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит предопределенное значение перечислений. Процедура. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru