Списковые формы документов

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

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

DevBookmark_Scripts BaseListForm

tree DevBookmark_Scripts BaseDocumentListForm

tree DevBookmark_Scripts BaseFlatDocumentListForm

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

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

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

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

Рассмотрим создание списковой формы документов на примере журнала закупок Purchase:

Example_CreateDocList1

Например, сделаем так, чтобы документы фильтровались по выбранному складу (записям справочника Store), а в дополнительном поле отображался подтип выбранного документа.

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

public partial class PurchaseListForm : BaseFlatDocumentListForm,

 IRecordBrowser<PurchaseDocument>, IRecordSelector<PurchaseDocument>

{

 public PurchaseListForm()

 {

         InitializeComponent();

 }

}

Example_CreateDocList2

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

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

Example_CreateDocList3

Example_CreateDictList8

Example_CreateDocList4

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

Example_CreateDocList5

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

public partial class PurchaseListForm : BaseFlatDocumentListForm,

 IRecordBrowser<PurchaseDocument>, IRecordSelector<PurchaseDocument>

{

 // Импортеруем менеджер, необходимый для получения подтипа документа.

 [Import]

 private IDictionaryManager DictionaryManager { get; set; }

 

 public PurchaseListForm()

 {

         InitializeComponent();

 

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

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

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

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

         GridPanel.ApplyCustomFilter += GridPanel_ApplyCustomFilter;

 

         // Чтобы в создаваемом документе склад автоматически подставлялся

         // в соответствии с выбранной в элементе StoreGridViewPanel

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

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

         GridPanel.InsertRecord += GridPanel_InsertRecord;

 

         // Для вывода в элементе UltimaTextEdit подтипа выбранного в элементе

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

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

         GridPanel.SelectionChanged += GridPanel_SelectionChanged;

 }

 

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

 protected async override Task LoadRecords()

 {

         await StoreGridViewPanel.LoadRecords();

         await base.LoadRecords();

 }

 

 // При смене склада в таблице StoreGridViewPanel необходимо каждый раз

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

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

 private async void StoreGridViewPanel_SelectionChanged(object sender, EventArgs e)

 {

         await GridPanel.LoadRecords();

 }

 

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

 private void GridPanel_ApplyCustomFilter(object sender,

         Client.Controls.CustomFilterEventArgs e)

 {

         var selectedStores = StoreGridViewPanel.SelectedRecordList;

         var customFilter =

                 DictionaryFilterHelper.GetContainsFilterExpression("StoreID",

                 selectedStores, e.ParameterExpression);

         e.FilterExpressions.Add(customFilter);

 }

 

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

 private void GridPanel_InsertRecord(object sender, InsertRecordEventArgs e)

 {

         var selected = StoreGridViewPanel.SelectedRecordList;

         if (!selected.IsEmpty)

         {

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

         }

 }

 

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

 private void GridPanel_SelectionChanged(object sender, EventArgs e)

 {

         UpdateSummary();

 }

 

 // Выводим в элементе UltimaTextEdit подтип выбранного в GridPanel документа.

 private void UpdateSummary()

 {

         var summaryText = string.Empty;

         if (SelectedList.Count == 0)

         {

                 summaryText = "Ни один документ не выбран.";

                 ultimaTextEdit1.Text = summaryText;

                 return;

         }

 

         if (SelectedList.Count > 1)

         {

                 summaryText = string.Format("Количество выбранных документов {0}.",

                         SelectedList.Count);

                 ultimaTextEdit1.Text = summaryText;

                 return;

         }

 

         var documentId = SelectedID;

         var docSubtypeId = DocumentManager.GetDocumentSubtypeID(documentId);

         var docSubtypeName = DictionaryManager.

                 GetRecord<DocumentSubtype>(docSubtypeId).Name;

         summaryText = string.Format("Подтип выбранного документа (id {0}) - {1}.",

                 documentId, docSubtypeName);

         ultimaTextEdit1.Text = summaryText;

 }

}

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

Example_CreateDocList6