Списковые формы справочников

Если требуемый уровень настройки внешнего вида списковой формы справочника превышает возможности, предлагаемые системой Ultima Businessware® (см. раздел Системные инструменты настройки внешнего вида экранных форм), можно создать свою списковую форму для любого справочника.

Для упрощения работы в системе реализована следующая иерархия классов:

DevBookmark_Scripts BaseListForm

tree DevBookmark_Scripts BaseDictionaryListForm

tree DevBookmark_Scripts BaseFlatDictionaryListForm

tree DevBookmark_Scripts BaseTreeDictionaryListForm

Форма BaseFlatDictionaryListForm предназначена для реализации списковых форм плоских справочников, BaseTreeDictionaryListForm – древовидных.

Для реализации списковой формы справочника необходимо унаследовать ее от подходящей формы (плоской или древовидной) и реализовать интерфейсы IRecordBrowser<T> и IRecordSelector<T>, где Т – тип справочника.

Система для показа списка записей будет искать форму, реализующую интерфейс IRecordBrowser<T>, а для выбора записей (например, при нажатии на кнопку PrintForms_scr_DictEditForm1_But3 в элементе управления DictionaryLookupEdit) форму, реализующую IRecordSelector<T>. Если в системе не окажется ни одной такой формы, откроется базовая списковая форма справочника. Если в системе окажется более одной такой формы, то система выдаст ошибку. Это позволяет избежать неочевидного поведения системы при ошибке настройки системы администратором.

Прикладной разработчик может запросить открытие списковой формы через класс DevBookmark_Scripts DictionaryHelper с помощью методов SelectRecord<T>, SelectRecords<T> или BrowseRecords<T>, где Т – тип справочника, форму которого требуется открыть. Первые два метода открывают списковую форму для выбора одной или нескольких записей, третий метод используется для просмотра списка записей.

Наиболее частая причина создания собственной списковой формы – реализация master-detail интерфейса, также называемого фильтром. Поэтому в форме BaseFlatDictionaryListForm уже размещен элемент управления SplitContainer, на правой панели которого расположена компонента для представления записей справочника со всеми стандартными инструментами – подбором колонок, фильтрами и т.д. Левая панель зарезервирована под размещение фильтра (таблицы или дерева), если оставить эту область пустой – она будет скрыта в итоговой форме.

Также для создания списковых форм справочников, например, для реализации фильтра, прикладной разработчик может воспользоваться следующими элементами управления:

DictionaryGridViewPanel – для отображения таблицы с панелью инструментов;

DictionaryTreeViewPanel – для отображения древовидных справочников с панелью инструментов.

Аналогично реализована форма BaseTreeDictionaryListForm.

Полный список классов, форм и элементов управления можно посмотреть в соответствующем разделе Элементы управления Ultima.

Рассмотрим создание списковой формы на примере справочника транспортных средств Vehicle:

Example_CreateDictList1

Например, сделаем так, чтобы транспортные средства фильтровались по выбранной модели транспортного средства (записям справочника Vehicle model):

Example_CreateDictList2

В проекте модуля создаем новый объект Windows Form, наследуем его от класса BaseFlatDictionaryListForm (из пространства имен Ultima.Client.Dictionaries) и реализуем интерфейсы IRecordBrowser<T> и IRecordSelector<T>.

Example_CreateDictList3

Example_CreateDictList4

public partial class VehicleListForm : BaseFlatDictionaryListForm,

 IRecordBrowser<Vehicle>, IRecordSelector<Vehicle>

{

 public VehicleListForm()

 {

         InitializeComponent();

 }

}

Example_CreateDictList5

Чтобы получить доступ к элементам управления Ultima необходимо создать папку (например, Ultima) в Toolbox и добавить в нее элементы управления из библиотеки BaseClientLibrary.dll (Choose Items -> Browse -> BaseClientLibrary.dll).

Example_CreateDictList6

Для отображения записей справочника Vehicle model используем элемент управления DictionaryGridViewPanel. Перетаскиваем его на форму и (в свойствах) переименовываем для удобства в VehicleModelGridViewPanel. Выбираем метод заливки Dock = Fill, чтобы он заполнил всю область элемента SplitContainer.

Чтобы вывести в элементе управления записи справочника, в параметрах устанавливаем значение DictionaryType = Ultima.Metadata.VehicleModel. Для его таблицы (элемент управления GridControl библиотеки DevExpress) добавляем аналогичный источник данных:

Example_CreateDictList7

Example_CreateDictList8

Example_CreateDictList9

Реализуем необходимые методы (которые описаны в коде):

public partial class VehicleListForm : BaseFlatDictionaryListForm,

 IRecordBrowser<Vehicle>, IRecordSelector<Vehicle>

{

 public VehicleListForm()

 {

         InitializeComponent();

 

         // Чтобы выбор записи справочника VehicleModel в элементе

         // VehicleModelGridViewPanel влиял на содержимое GridPanel, отображающей

         // записи справочника Vehicle, следует добавить фильтр. Привязываем

         // обработчик на событие ApplyCustomFilter элемента управления GridPanel.

         GridPanel.ApplyCustomFilter += GridPanel_ApplyCustomFilter;

 

         // Чтобы в создаваемой записи справочника Vehicle модель транспортного

         // средства автоматически подставлялась в соответствии с выбранной в

         // элементе VehicleModelGridViewPanel записью справочника Vehicle model,

         // следует добавить фильтр. Привязываем обработчик на событие

         // InsertRecord элемента управления GridPanel.

         GridPanel.InsertRecord += GridPanel_InsertRecord;

 

         // Убираем из панели GridPanel лишние иснтрументы.

         GridPanel.Properties.LimitCounterVisible = false;

         GridPanel.Properties.GroupButtonVisible = false;

         GridPanel.Properties.PrintButtonVisible = false;

         GridPanel.Properties.IDEditVisible = false;

         GridPanel.Properties.CommandsMenuVisible = false;

 }

 

 // Загружаем записи в элемент управления VehicleModelGridViewPanel.

 protected override async Task LoadRecords()

 {

         await VehicleModelGridViewPanel.LoadRecords();

         await base.LoadRecords();

 }

 

 // При смене выбора модели в элементе VehicleModelGridViewPanel необходимо

 // каждый раз обновлять список записей GridPanel. Для этого будем реагировать

 // на событие SelectionChanged элемента VehicleModelGridViewPanel.

 private async void VehicleModelGridViewPanel_SelectionChanged(object sender,

         EventArgs e)

 {

         await GridPanel.LoadRecords();

 }

 

 // Обработчик события ApplyCustomFilter элемента GridPanel.

 private void GridPanel_ApplyCustomFilter(object sender,

         Client.Controls.CustomFilterEventArgs e)

 {

         var selectedModels = VehicleModelGridViewPanel.SelectedRecordList;

         var customFilter =

                 DictionaryFilterHelper.GetContainsFilterExpression("ModelID",

                 selectedModels, e.ParameterExpression);

         e.FilterExpressions.Add(customFilter);

 }

 

 // Обработчик события InsertRecord элемента GridPanel.

 private void GridPanel_InsertRecord(object sender, InsertRecordEventArgs e)

 {

         var selected = VehicleModelGridViewPanel.SelectedRecordList;

         if (!selected.IsEmpty)

         {

                 e.Parameters["ModelID"] = selected.First();

         }

 }

}

Компилируем проект, копируем созданные библиотеки в папку модуля в клиентском приложении Client/ClientModules/TradeTestSolution, перезагружаем метаданные и открываем созданную списковую форму справочника той же командой, что и прежнюю:

SCR_ReloadMetadata

Example_CreateDictList10