Хотел написать много красивых и умных слов, но вместо этого решил перейти сразу к делу. По пунктам и коротко:
1. Причина данного баяна: необходимость запомнить между вызовами обработки значения реквизитов объекта, а также дать пользователю возможность управлять составом запоминаемых реквизитов. Стандартные механизмы управляемых форм требуют во-первых дополнительного кода для редактирования состава, а во-вторых не сохраняют объекты сложных типов ако таблицы и деревья значений. Точнее сохраняют, но не во всех вариантах клиентов.
2. Подход к реализации: Сохранение всех данных в реквизите управляемой формы типа "Список значений". Это удобно тем, что во-первых используется стандартное хранилище и стандартный механизм сохранения, а во-вторых из-за того, что процедуры обработки сохранения и восстановления настроек серверные и мы минимизируем клиентское взаимодействие со сложными типами данных, поддерживаемых не всеми клиентами, и легко добиваемся мультиклиентности.
3. Реализация: Реализация способа сохранения состоит из сохраняемого реквизита управляемой формы типа СписокЗначений с именем "СохраняемыеСвойстваОбъекта" и двух процедур: 1) для Сохранения/Восстановления значений и 2) редактирования списка сохраняемых реквизитов. Указанные процедуры вызываются из обработок стандартных событий формы "ПриСохраненииДанныхВНастройкахНаСервере" и "ПриЗагрузкеДанныхИзНастроекНаСервере" (для Сохранения/Восстановления) и произвольнымобразом для регулирования списка настроек (я добавил команду для командной панели формы).
4. Конкретно инструкция:
а) Создаем для управляемой формы реквизит типа СписокЗначений с названием (в моем примере): "СохраняемыеСвойстваОбъекта".
б) Создаем кнопку с процедурой или команду для вызова процедуры "РедактироватьСписокСохраняемыхРеквизитов". В примере это команда формы "РедактироватьСохраняемыеРеквизиты". Размещаем кнопочку для вызова на форме или (как в примере) вызов команды из меню.
в) Инициируем стандартные обработчики событий формы "ПриСохраненииДанныхВНастройкахНаСервере" и "ПриЗагрузкеДанныхИзНастроекНаСервере"
г) После всего вышеизложенного в модуль формы добавляем 2 процедуры: "РедактироватьСписокСохраняемыхРеквизитов" и "ОбработатьСохраняемыеРеквизитыОбъекта" и настраиваем вызов процедуры "ОбработатьСохраняемыеРеквизитыОбъекта" из стандартных обработчиков, а процедуры "РедактироватьСписокСохраняемыхРеквизитов" из специальной команды/процедуры связанной с элементом управления или пунктом меню формы. В качестве аргумента СохраняемыйСписокРеквизитФормы передается название списка значений с сохраняемыми настройками (в примере это "СохраняемыеСвойстваОбъекта", в общем случае - как назовете реквизит формы, так и передаете при вызове)
д) собственно пример текста модуля с командами и процедурами:
&НаСервере
Процедура ОбработатьСохраняемыеРеквизитыОбъекта(НастройкиСохранения, СохраняемыйСписокРеквизитФормы, Сохранить)
СписокТиповДанныхФормы = Новый СписокЗначений;
СписокТиповДанныхФормы.Добавить(Тип("ДанныеФормыСтруктура"),"Структура");
СписокТиповДанныхФормы.Добавить(Тип("ДанныеФормыКоллекция"),"ТаблицаЗначений");
СписокТиповДанныхФормы.Добавить(Тип("ДанныеФормыСтруктураСКоллекцией"),"СписокЗначений");
СписокТиповДанныхФормы.Добавить(Тип("ДанныеФормыДерево"), "ДеревоЗначений");
СтарыйСписок = ЭтаФорма[СохраняемыйСписокРеквизитФормы];
СписокРеквизитов = ?(СтарыйСписок.Количество()>0, СтарыйСписок[0].Значение, Новый СписокЗначений);
Если Сохранить Тогда
НовыйСписок = Новый СписокЗначений;
НовыйСписок.Вставить(0, СписокРеквизитов);
Для Каждого СохраняемыйРеквизит Из СписокРеквизитов Цикл
Если СохраняемыйРеквизит.Пометка Тогда
ТипДанныхРеквизита = СписокТиповДанныхФормы.НайтиПоЗначению(ТипЗнч(Объект[СохраняемыйРеквизит.Значение]));
Если НЕ ТипДанныхРеквизита = Неопределено Тогда
СохраняемоеЗначение = ДанныеФормыВЗначение(Объект[СохраняемыйРеквизит.Значение], Тип(ТипДанныхРеквизита.Представление));
Иначе
СохраняемоеЗначение = Объект[СохраняемыйРеквизит.Значение];
КонецЕсли;
НовыйСписок.Добавить(СохраняемоеЗначение, СохраняемыйРеквизит.Значение);
КонецЕсли;
КонецЦикла;
НастройкиСохранения[СохраняемыйСписокРеквизитФормы] = НовыйСписок;
Иначе
Для Каждого ЭлементСтарогоСписка Из СтарыйСписок Цикл
Для Каждого Реквизит Из СписокРеквизитов Цикл
Если Реквизит.Значение = ЭлементСтарогоСписка.Представление Тогда
Если НЕ СписокТиповДанныхФормы.НайтиПоЗначению(ТипЗнч(Объект[ЭлементСтарогоСписка.Представление])) = Неопределено Тогда
ЗначениеВДанныеФормы(ЭлементСтарогоСписка.Значение, Объект[ЭлементСтарогоСписка.Представление]);
ЭлементСтарогоСписка.Значение = Объект[ЭлементСтарогоСписка.Представление];
Иначе
Объект[ЭлементСтарогоСписка.Представление] = ЭлементСтарогоСписка.Значение;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура РедактироватьСписокСохраняемыхРеквизитов(СохраняемыйСписокРеквизитФормы)
СтарыйСписок = ЭтаФорма[СохраняемыйСписокРеквизитФормы];
СтарыйСписок = ?(СтарыйСписок.Количество()>0, СтарыйСписок[0].Значение, Новый СписокЗначений);
Если Ложь Тогда
СтарыйСписок = Новый СписокЗначений;
КонецЕсли;
сп = Новый СписокЗначений;
Для Каждого РеквизитОбъекта Из ЭтаФорма.Элементы Цикл
Попытка // Попытку можно опустить если не будет использоваться веб клиент.
Если Объект.Свойство(РеквизитОбъекта.Имя) Тогда
сп.Добавить(РеквизитОбъекта.Имя, РеквизитОбъекта.Заголовок);
ЭлементСтарогоСписка = СтарыйСписок.НайтиПоЗначению(РеквизитОбъекта.Имя);
Если НЕ ЭлементСтарогоСписка = Неопределено Тогда
сп.НайтиПоЗначению(РеквизитОбъекта.Имя).Пометка = ЭлементСтарогоСписка.Пометка;
КонецЕсли;
КонецЕсли;
Исключение
КонецПопытки;
КонецЦикла;
сп.ОтметитьЭлементы("Выбор сохраняемых реквизитов объекта");
ЭтаФорма[СохраняемыйСписокРеквизитФормы].Вставить(0, сп);
КонецПроцедуры
&НаСервере
Процедура ПриСохраненииДанныхВНастройкахНаСервере(Настройки)
// Вставить содержимое обработчика.
ОбработатьСохраняемыеРеквизитыОбъекта(Настройки, "СохраняемыеСвойстваОбъекта", Истина);
КонецПроцедуры
&НаСервере
Процедура ПриЗагрузкеДанныхИзНастроекНаСервере(Настройки)
// Вставить содержимое обработчика.
ОбработатьСохраняемыеРеквизитыОбъекта(Настройки, "СохраняемыеСвойстваОбъекта", Ложь);
КонецПроцедуры
&НаКлиенте
Процедура РедактироватьСохраняемыеРеквизиты(Команда)
// Вставить содержимое обработчика.
РедактироватьСписокСохраняемыхРеквизитов("СохраняемыеСвойстваОбъекта");
КонецПроцедуры
Ну вот собственно и почти все. Осталось сказать несколько слов о некрасивой Попытке и о тестировании метода. Не случайно в текст метода была введена Попытка и не случайно стоит коммент о том, что она нужна только для web клиентов. По ходу тестов под разными клиентами я убедился в полной работоспособности метода для управляемых форм на толстых и тонкуих клиентах, а вот с web пришлось попотеть. Дело в том, что процедура перебирает все элементы формы для поиска данных, но шутка в том, что web клиент не отрисовывает все элементы формы с полным набором свойств в том числе и со свойством Имя. Такая вот фитча (или баг:) у меня наблюдалась в IE. Побеждать то, что обусловлено скорее даже не платформой, а способностями браузеров я не стал, хотя теоретически можно было бы разложить форму на винтики в серверной процедуре и передать web клиенту списком только нужные реквизиты. Это, конечно, избавило бы код от Попытки, но, думаю, не добавило бы в итоге ни простоты ни красоты. Так что я смирился, а Вы как хотите - используйте, дописывайте, переписывайте, критикуйте, ругайте, предлагайте что-то лучшее и т.д. В комментах...:)