Павло Чистов
Для початку було перерито безліч форумів. Здебільшого в них пропонували зберігати стан в додатковій колонці. Але в моєму дереві понад 400 тис. Записів, а це додаткові витрати пам'яті. Тому я пішов іншим шляхом.
Аналіз завдання привів до наступних висновків:
- зберігати потрібно список тільки розгорнутих рядків дерева;
- якщо рядок згортається, зберігати її в списку більше не потрібно;
- список розгорнутих рядків дерева зберігаємо на клієнті, щодо всього дерева він зазвичай дуже невеликий;
- якщо є виділена рядок, після поновлення дерева виділяємо її знову;
- оскільки після відновлення дерева ідентифікатори в ДаннихФормиДерево змінюються, нам потрібно це проконтролювати.
Для клієнтської сторони була введена змінна типу Відповідність. Вона буде зберігати для розгорнутих рядків їх унікальні значення (як ключ) і ідентифікатори рядків (як значення). Важливим є те, що не можна в якості ключів використовувати ідентифікатори рядків. Як я написав вище, вони змінюються системою при оновленні дерева, і вплинути на це неможливо.
У таблиці керованої форми, пов'язаної з ДеревомЗначеній, з'являються дві події - ПередРазворачіваніем () і ПередСворачіваеніем (). У ці події поміщаємо алгоритми додавання / видалення даних по розгортається / звернутій рядку дерева.
При відкритті форми дерево заповнюється автоматично в подію ПріСозданііНаСервере () і знаходиться з згорнутому стані.
Користувач може самостійно оновити дані, наприклад, після натискання кнопки. Наведемо програмне оновлення дерева на клієнтській стороні.
Ефективно використовувати час дерева виконуємо на сервері.
Коротко опишу, що відбувається. Запитом формуємо ієрархію довідника Номенклатура і будуємо дерево. Щоб виключити повторне додавання в дерево вже наявних елементів, відсікаємо, використовуючи СоответствіеНоменклатуриІСтрокДерева. Також попутно з цієї відповідності отримуємо рядок-батько дерева для нового елемента.
Після того, як дерево побудовано, формуємо таблицю з даними розгорнутих рядків. Ця частина актуальна для перестроювання дерева. При першому побудові вона пропускається, оскільки у нас немає розгорнутих вузлів.
Коли таблиця створена, перенавантажуємо дерево в реквізит форми ДеревоЗначеній. Потім методом ОбновітьТабліцуІдентіфікаторовСтрокДереваНаСервере () перебираємо дані реквізиту ДеревоЗначеній (він має тип ДанниеФормиДерево) і шукаємо номенклатуру з дерева в таблиці ТабліцаРазвернутихСтрокДерева. Якщо збіги перебувають, змінюємо ідентифікатори в рядках ТабліциРазвернутихСтрокДерева. Якщо у користувача була виділена рядок, також шукаємо новий ідентифікатор цього рядка і запам'ятовуємо його. У методі ОбновітьТабліцуІдентіфікаторовСтрокДереваНаСервере () встановлено обмеження, яке спрацьовує, якщо оновлені ідентифікатори всіх розгорнутих рядків.
Далі управління повертається в процедуру ОбновітьДеревоЗначенійНаСервере (). де клієнтська змінна відповідності ідентифікаторів рядків дерева оновлюється актуальними даними. На клієнті рядки дерева розгортаються згідно з даними відповідності, виділяється рядок, оновлення дерева завершується.
Сам алгоритм досить простий, незважаючи на немаленький обсяг коду. Використовувати його можна в будь-якому дереві. Досить визначити унікальне значення для кожного рядка дерева.
Працює код теж швидко. Зокрема, через веб-клієнта на комп'ютері середньої продуктивності дерево з 400 тис. Рядків будується приблизно за 2 хвилини, перебудовується за 40 секунд.