powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Создание базы данных с Treeview
4 сообщений из 29, страница 2 из 2
Создание базы данных с Treeview
    #38584056
rock-n-roll
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Claymore,

Не совсем понятно что бы хотите услышать своим "апом".
Вам же уже много кто сказал - id,parentid как правило... как правило оба int(id даже автоинкиментом можно сделать)
Ну а ключами нодов как вариант будут "_"+str(id)

Если три поля в таблице кажутся "правильнее" - дело Ваше, Вам сопровождать
...
Рейтинг: 0 / 0
Создание базы данных с Treeview
    #38584081
Claymore
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rock-n-roll,

Ды понимаешь я не соображу как код написать в init (V_V)
...
Рейтинг: 0 / 0
Создание базы данных с Treeview
    #38584254
rock-n-roll
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Claymore,

в смысле как- а что он должен делать?
Наполнять первый уровень тривью?(кстати, если поискать по этому же форуму-полно объяснений почему рекомендуется строить только "необходимое отображать в данный момент")- так и этому полно примеров на этом же форуме

Дай перефразирую твой вопрос-"Есть таблица id,parentid,name. Нужны обобщенные методы по наполнению тривьюхи"
Так?

Тогда делается это примерно так:
Рисуется метод (ADDLEVEL) который будет строить уровень по переданному ParentID также этот метод добавит по одному "ФИКТИВНОМУ" узлу для всех имеющих потомков в таблице только для того чтобы появился крест(здесь извини лень вырезать .is_color и .is_ico считай что .F.)
Код: plsql
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.
PARAMETERS INT_ID,IS_FIRST&&,REC_ID
******************

LOCAL CHAR_ID,INT_TEKID,COL_CHILD,tcNameImage,tcIs_first,tcIs_Image,tnTally
*CHAR_ID=IIF(VARTYPE(REC_ID)=='C',REC_ID,'_'+ALLTRIM(STR(INT_ID)))
CHAR_ID='_'+ALLTRIM(STR(INT_ID))
SELECT ID,PARENTID,NAME,TYPE,FICT FROM (THIS.ALIAS) WHERE PARENTID=m.INT_ID INTO CURSOR (THIS.TEMP_CURS) ORDER BY SORT
tnTally=_tally
LOCAL taArray(tnTally,5)
COPY TO ARRAY taArray 

FOR i=1 TO tnTally
 m.INT_TEKID=taArray(i,1)
 m.KEY_ITEM='_'+ALLTRIM(STR(taArray(i,1)))
 m.tcNameImage='im'+ALLTRIM(STR(taArray(i,4)))
 m.tcIs_first=IIF(IS_FIRST,',','m.CHAR_ID,4')
 m.tcIs_Image=IIF(this.is_ico,IIF(OCCURS(','+m.tcNameImage+',',This.listim)=1,',"'+m.tcNameImage+'"',''),'')
  TEXT TO tcTempText NOSHOW TEXTMERGE PRETEXT 15
    THIS.TREEVIEW.Nodes.Add(<<m.tcIs_first>>,m.KEY_ITEM,taArray(i,3)<<m.tcIs_Image>>) 
  ENDTEXT
  &tcTempText
  THIS.TREEVIEW.Nodes(m.KEY_ITEM).ForeColor = IIF(this.is_color,THIS.ForeColor,0)
  THIS.TREEVIEW.Nodes(m.KEY_ITEM).BackColor = IIF(this.is_color,THIS.BackColor,16777215)&&&16777215=RGB(255,255,255)

  SELECT COUNT(id) as count FROM (THIS.ALIAS) WHERE PARENTID = m.INT_TEKID INTO CURSOR rez
  m.COL_CHILD=rez.count
  USE IN rez
  IF m.COL_CHILD>0&&достраиваем фиктивный узел   
    THIS.TREEVIEW.Nodes.Add(m.KEY_ITEM,4,'F'+m.KEY_ITEM,'')
  ENDIF
*  ENDIF 
ENDFOR 




Метод EXPEND тривьюхи если есть фиктивный-удаляет его и строит следующий уровень, если нет значит ветвь уже построена ранее
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
*** ActiveX Control Event ***
LPARAMETERS node
LOCAL KEY_CHILD
KEY_CHILD=node.Child.key&&собственно первый// если есть фиктивный он один и он же первый
IF KEY_CHILD=='F'+node.key
   WITH THIS.PARENT
    .REMOVENODE(KEY_CHILD)
    .ADDLEVEL(.KEY_TO_ID(node.key))
   ENDWITH  
ENDIF 
node.expanded=.t.&&&на случай если метод вызывается программно   





Итого что может быть в ините..
Ну наверно ADDLEVEL(0,.T.)
ну если все таки хочется придать "полуразвернутый вид" пару EXPEND

А я вообще правильно тебя понял?
Если да то не ленись, пошукай по форуму-сее уже обсуждалось и не раз
...
Рейтинг: 0 / 0
Создание базы данных с Treeview
    #38584294
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ClaymoreВладимирМ,

Только "Вариант 2" остальные исключаются!
Это Вы сейчас так думаете. Причем, насколько я понимаю, думаете только Вы. Мнением пользователей Вы не интересовались. О чем я и говорю. TreeView - друг ОДНОГО человека. В данном случае персонально Ваш.

ClaymoreЯ тут подумал, правильнее таблица будет выглядеть так:
Не то, чтобы описанная структура была не правильной, но она избыточна. Вам придется кроме генерации значения id еще как-то "сконструировать" генератор значения key.

Да, TreeView требует в качестве значения ключа узла символьное значение. Но ведь можно символьное значение получать "на лету" (в процессе построения дерева) из числового значения id. Например, переведя id в строку и добавив какой-нибудь символ. Например, "_".

Другими словами, вполне достаточно будет иметь такую структуру

Код: sql
1.
2.
3.
4.
5.
6.
7.
create cursor curTest (id i, parentid i, znachenie c(50))
insert into curTest (id, parentid, znachenie) values (1, 0, "Node 1")
insert into curTest (id, parentid, znachenie) values (2, 0, "Node 2")
insert into curTest (id, parentid, znachenie) values (3, 1, "Node 1A")
insert into curTest (id, parentid, znachenie) values (4, 1, "Node 1B")
insert into curTest (id, parentid, znachenie) values (5, 2, "Node 2A")
insert into curTest (id, parentid, znachenie) values (6, 2, "Node 2B")


А при заполнении TreeView формировать значение ключа примерно так

Код: sql
1.
key = "_"+ltrim(str(id))



ClaymoreНе могу сообразить как правильно написать код в init формы form1, помогите)

Существует 2 принципиальные стратегии заполнения TreeView

Вариант 1

Сразу заполнить все узлы дерева на всех уровнях вложенности

Недостаток: при большом количестве узлов дерева потребует много времени на его заполнения. С точки зрения пользователя, форма будет открываться очень долго.

Правда, понятие "много узлов" сильно зависит от железа. Т.е. "много" - это когда время открытия формы больше 2..3 секунд. А сколько узлов можно успеть создать за это время напрямую зависит от используемого железа. От структуры дерева и алгоритма его наполнения время построения дерева зависит слабо.

Вариант 2

При открытии формы заполняется только первый уровень. А остальные уровни заполняются "по требованию". Обычно в момент первого раскрытия соответствующего узла. Так работает проводник в Windows.


Оба варианта требуют не очевидного программирования. Не сложного, а именно не очевидного. Не привычного.

Сразу заполнить все узлы дерева на всех уровнях вложенности

Проблема в том, что в TreeView невозможно сначала создать дочерний узел, а потом - родительский. Необходимо строить дерево строго "сверху вниз". Сначала родителя, потом потомка. На первый взгляд кажется ничего сложного. Но это при "гладкой" структуре заполнения таблицы как в примере. А если структура данных будет не "гладкая", ну, например

idparentid102153102150

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

Если не создавать дополнительных полей сортировки с "обвязкой" в виде триггеров для поддержания этих полей в актуальном состоянии, то возможны два решения

1. Рекурсия
2. "Бесконечный" цикл с исключением ранее использованных значений

Системным ограничением FoxPro является ограничение на количество процедур, вызванных одна из другой. В данном случае это означает ограничение на количество рекурсий или количество уровней дерева. Для VFP9 - по умолчанию не более 128 вложенных процедур. Для младших версий - не более 32.

Если рассматривать решение с бесконечным циклом, то можно так

Код: sql
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.
47.
48.
49.
50.
51.
52.
* Делаем выборку во временную таблицу из исходной таблицы (исходная - это та, что в начале данного поста)
* добавляя два поля-флага, которые будут определять факт использования записи
select id, parentid, znachenie, .f. as isBuild, .f. as isParent ;
from curTest ;
into cursor curBuild readWrite

Local lnParentId, lcKey, lcParentId

* Первый родитель имеет код 0
* поскольку искать будем дочерние узлы, то это значение в поле ParentId
lnParentId = 0
lcParentId = "_" + ltrim(str(m.lnParentId))

* Для корректного входа в цикл выполняю поиск первой дочерней записи указанного родителя
select curBuild
locate for ParentId = m.lnParentId and isBuild = .F.

* Организую "бесконечный" цикл по факту нахождения записи
do while found('curBuild')

	* Перебираю все узлы, относящиеся напрямую к указанному родителю
	select curBuild
	scan for ParentId = m.lnParentId and isBuild = .F.
	    * Создаем узел в объекте TreeView, предполагая, что он лежит непосредственно на форме
	    * и имеет имя TreeView1
	    lcKey = "_" + ltrim(str(curBuild.id))
	    if m.lnParentId = 0
	         thisForm.TreeView1.Nodes.add(,,m.lcKey, alltrim(curBuild.znachenie))
	    else
	         thisForm.TreeView1.Nodes.add(m.lcParentId,4,m.lcKey, alltrim(curBuild.znachenie))
	    endif

	    * Помечаем запись как использованную при создании узла в TreeView
	    replace isBuild with .T.
	endscan

	* Помечаю запись с использованным кодом родителя 
	select curBuild
	locate for id = m.lnParentId
	if found('curBuild')
	    replace isParent with .T.
	endif

	* Беру нового родителя среди уже использованных при построении дерева
	select curBuild
	locate for isBuild = .T. and isParent = .F.

	* Обновляю значения кодов очередного родителя
	lnParentId = curBuild.id
	lcParentId = "_" + ltrim(str(m.lnParentId))

enddo
...
Рейтинг: 0 / 0
4 сообщений из 29, страница 2 из 2
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Создание базы данных с Treeview
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]