Имя: Пароль:
1C
1С v8
Обновить отображение узла ДереваЗначений на форме
0 zelenprog
 
21.06.23
15:48
Добрый день!

Есть обработка по записи некоторых данных в справочник контрагентов.
На форме (УФ) есть реквизит ДЗКонтрагенты (тип ДеревоЗначений) - это список контрагентов.
На форме есть Таблица, которая отображает это дерево значений.
Каждая строка первого уровня (узел) этого дерева - это основная информация о контрагенте (грубо говоря, просто наименование контрагента).
Подчиненные строки узла - это интересующие подробности об этом контрагенте. Подчиненные строки могут быть, а могут отсутствовать.

При открытии обработки (формы) дерево заполняется.

Затем в процессе работы с обработкой по кнопке на форме в справочник контрагентов записываются изменения.
Какие контрагенты были изменены - известно.

Нужно сделать, чтобы при изменении данных контрагента, также изменилось (обновилось) визуальное отображение "узла", соответствующего этому контрагенту.
То есть чтобы узел стал отображать подчиненные строки с новой информацией из справочника.
Перерисовывать все дерево не хотелось бы. Нужно перерисовать только соответствующие узлы.

Как это сделать?

Сейчас в коде запросом новые данные из базы извлекаются, строки дерева значений для нужного узла перезаполняются.
Однако, эти изменения никак не отображаются на дереве.
Есть какой-нибудь метод, который делает перерисовку текущего узла (или всего дерева значений) на форме?
Подскажите плиз.
1 Волшебник
 
21.06.23
15:51
Нужно свернуть и развернуть узел.
2 zelenprog
 
21.06.23
16:25
(1) Программно свернуть и развернуть?

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

Когда в такой псевдо-узел программно добавляются строки, то на форме у этого уже полноценного узла значок сворачивания-разворачивания не появляется.
Соответственно невозможно его свернуть-развернуть.

А если речь о программном сворачивании-разворачивании, то как это сделать?
И правильно ли это - для обновления отображения выполнять какие-то манипулцуии?
3 zelenprog
 
21.06.23
17:14
Понял в чем проблема....

Я передавал на сервер все полное ДеревоЗначений, там его обрабатывал: выбираю из дерева нужных строк, записываю данные в соответствующих контрагентов, обновляю строки дерева.
Естественно на форме дерево значений обновилось только после
    ЗначениеВРеквизитФормы(лДЗ, "ДеревоЗначенийКонтрагенты");

Но этот вариант плохой.
Так как приходится обновлять все дерево полностью, даже если был записан только один контрагент.

А как сделать правильно?
Если мне надо обновить контрагента только в одной строке, как это надо делать?
4 zelenprog
 
23.06.23
10:00
Получается, нужно сделать частичное обновление только некоторых строк дерева.
Как это сделать?

Следующий код, как я понимаю, не подходит:

РеквизитФормыВЗначение("ДЗКонтрагенты");
...
ЗначениеВРеквизитФормы(лДЗ, "ДЗКонтрагенты");

Так как команда "ЗначениеВРеквизитФормы" перезаполняет всю таблицу на форме полностью.
Как перезаполнить только часть таблицы - элемента формы?
5 Мультук
 
гуру
23.06.23
10:29
(4)

Обработка.

https://dropmefiles.com/rhzrr

Простой псведо-код. Просто для демонстрации
1) В коде нет РеквизитФормыВЗначение, ЗначениеВРеквизитФормы
2) По нажатию одной кнопки он заполняет дерево, по нажатию другой дополняет некий узел
3) Да, поиск перебором -- полная хрень, но это просто пример


Нажатие

&НаКлиенте
Процедура Заполнить(Команда)
    ЗаполнитьНаСервере();
КонецПроцедуры

&НаКлиенте
Процедура Добавить(Команда)
    ДобавитьНаСервере();
КонецПроцедуры


&НаСервере
Процедура ЗаполнитьНаСервере()
    корень = ДеревоКакРеквзититФормы.ПолучитьЭлементы();
    корень.Очистить();
    
    к1 = корень.Добавить();
    к1.Контрагент = "Контрагент1";
    к1Строки = к1.ПолучитьЭлементы();
    к11 = к1Строки.Добавить();    
    к11.Контрагент = "Контрагент11";
    
    к2 = корень.Добавить();
    к2.Контрагент = "Контрагент2";
    

    к3 = корень.Добавить();
    к3.Контрагент = "Контрагент3";
    
КонецПроцедуры


&НаСервере
Процедура ДобавитьНаСервере()
    корень = ДеревоКакРеквзититФормы.ПолучитьЭлементы();
    Для каждого строка из корень Цикл
        
        Если строка.Контрагент = "Контрагент2" Тогда
            кСтроки = строка.ПолучитьЭлементы();
            к11 = кСтроки.Добавить();    
            к11.Контрагент = "Контрагент21";
            
            к11 = кСтроки.Добавить();    
            к11.Контрагент = "Контрагент22";
        КонецЕсли;    
    КонецЦикла;    
    
КонецПроцедуры
6 НЕА123
 
23.06.23
10:39
(4) п.3.
А можно без цикла для ДанныеФормыКоллекцияЭлементовДерева?
7 НЕА123
 
23.06.23
10:39
*(5)
8 Мультук
 
гуру
23.06.23
10:42
(6)

"Я не тактик, я стратег" (с). Наверное можно организовать какой-то словарь (Соответствие). Не было у меня такой задачи.
9 zelenprog
 
23.06.23
10:43
(5) А что такое "ДеревоКакРеквзититФормы"? Это реквизит формы типа "ДеревоЗначений"?
Так ведь в процедуре &НаСервере к нему нельзя просто так обратиться.
Надо делать "РеквизитФормыВЗначение". А значит в конце добавления строк в узел придется сделать и "ЗначениеВРеквизитФормы".
По сути произойдет полная перезаполнение дерева-таблицы на форме.

А нужно перезаполнить и перерисовать только один измененный узел.
10 Мультук
 
гуру
23.06.23
10:45
(9)

Сцуко. Я написал реально работающий код .
Приложил реально работающую обработку.

Вы код смотрели? Обработку запускали ?
11 zelenprog
 
23.06.23
10:55
(10) Код посмотрел. Но не понял, как возможно напрямую обращение к дереву значений минуя "ЗначениеВРеквизитФормы".
А обработку скачать не смог, почему-то при попытке скачивания что-то мелькает и скачивание на происходит. Пробовал в трех браузерах.
Извините, можете куда-нибудь еще выложить обработку?
12 Мультук
 
гуру
23.06.23
11:03
13 zelenprog
 
23.06.23
11:21
(12) Все понял, спасибо.
В обработке работа не с самим ДеревомЗначений, а с его "представлением" ДанныеФормыДерево.

Если так можно работать, то для чего нужны методы "РеквизитФормыВЗначение", "ЗначениеВРеквизитФормы"?

Это просто два разных подхода с реквизитами формы?
Какие отличия и преимущества у каждого их этих способов?
14 Мультук
 
гуру
23.06.23
11:29
(13)

1) Например, ради вот таких случаев. Когда одного представления мало

https://infostart.ru/1c/articles/153602/


&НаСервере
Процедура ЗаполнитьТЧПоДаннымПоследнегоДокумента(Контрагент)

            ДокОбъект = РеквизитФормыВЗначение("Объект");
            ДокОбъект.ЗаполнитьТЧПоДаннымПоследнегоДокумента(Контрагент);
            ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

КонецПроцедуры

2)

&НаСервере
Процедура ЗаполнитьЧегоТоТам()

       об = РеквизитФормыВЗначение("Объект");
       об.МояФункцияВМодулеОбработки()

КонецПроцедуры
15 zelenprog
 
23.06.23
11:36
(14) Эту статью я сам находил и читал, перед тем как писать тему.
Но "тонкости" не понял. Попробую еще раз разобраться.
16 zelenprog
 
23.06.23
12:17
А почему в обработке вот эта процедура сделана "&НаСервере"?

&НаСервере
Процедура ДобавитьНаСервере()
    корень = ДеревоКакРеквзититФормы.ПолучитьЭлементы();
    Для каждого строка из корень Цикл
        
        Если строка.Контрагент = "Контрагент2" Тогда
            кСтроки = строка.ПолучитьЭлементы();
            к11 = кСтроки.Добавить();    
            к11.Контрагент = "Контрагент21";
            
            к11 = кСтроки.Добавить();    
            к11.Контрагент = "Контрагент22";
        КонецЕсли;    
    КонецЦикла;    
    
КонецПроцедуры

Ведь мы же работаем не с прикладным типом данных.
Значит, по идее эти же команды можно выполнить и на клиенте?
17 Мультук
 
гуру
23.06.23
12:36
(16)

>> Значит, по идее эти же команды можно выполнить и на клиенте?
Конечно.

Но функция которая вернет данные на клиент для обновления должна:
а) вернуть массив структур или структуру
б) быть &НаСервереБезКонтекста

Иначе игры "в оптимизацию" бесполезны.
18 zelenprog
 
23.06.23
14:33
А как теперь работая с ДанныеФормыДерево заполнить строку по именам колонок?

С ДеревомЗначений это было вот так:

        Для Сч = 1 По лКолвоКолонок Цикл
            лНомерКолонки = Сч - 1;
            лИмяКолонки = лДеревоЗначений.Колонки[лНомерКолонки].Имя;
            СовпадающаяКолонка = мТЗКонтрагенты.Колонки.Найти(лИмяКолонки);
            Если СовпадающаяКолонка <> Неопределено Тогда
                лСтрокаДЗ[лИмяКолонки] = СтрокаТЗКонтрагенты[лИмяКолонки];
            КонецЕсли;
        КонецЦикла;
19 Мультук
 
гуру
23.06.23
14:42
(18)

КолонкиДляЗаполнения = "Контрагент, Сумма, Количество";
масКолонкиДляЗаполнения = СтрРазделить(КолонкиДляЗаполнения, ",");


Для каждого лИмяКолонки из масКолонкиДляЗаполнения Цикл
    лСтрокаДЗ[лИмяКолонки] = СтрокаТЗКонтрагенты[лИмяКолонки];
КонецЦикла;
20 НЕА123
 
23.06.23
14:42
(18)
ЗаполнитьЗначенияСвойств(лСтрокаДЗ,СтрокаТЗКонтрагенты)
вместо цикла?
не?
21 zelenprog
 
23.06.23
16:13
(19),(20) Да, можно так. ОК.
22 zelenprog
 
23.06.23
16:17
А как бы теперь сделать, чтобы в цикле обновление строки на форме отображалось после изменения каждой строки?
Сейчас получается, что изменения становятся видны только когда весь цикл завершился.

&НаСервере
Процедура ДобавитьНаСервере()
    корень = ДеревоКакРеквзититФормы.ПолучитьЭлементы();
    Для каждого строка из корень Цикл
        
        Если строка.Контрагент = "Контрагент2" Тогда
            кСтроки = строка.ПолучитьЭлементы();
            к11 = кСтроки.Добавить();    
            к11.Контрагент = "Контрагент21";
            
            к11 = кСтроки.Добавить();    
            к11.Контрагент = "Контрагент22";
        КонецЕсли;    
    КонецЦикла;    
    
КонецПроцедуры