Необходимо подключение библиотеки DataConnection.dll.
Шаблон кастомного DataConnection
<DataConnectionName="CustomGetDataConnection"Type="CustomGetDataConnection"Assembly="Template"><!-- Элементы DataConnection --></DataConnection>
В атрибуте Type указывается имя класса, описывающего кастомный DataConnection, а в качестве значения атрибута Assembly указывается имя сборки, в которой реализован этот класс.
Для удобства и разделения логики, исходный код DataConnection можно разбить на два класса:
CustomGetDataConnectionXmlSettings - класс загрузки данных из xml-файла;
CustomGetDataConnection - класс с логикой формирования результирующей таблицы.
Парсинг xml
Полный код шаблона:
usingSystem.Xml;namespaceWorkflowForms.DataConnections{publicclassCustomGetDataConnectionXmlSettings:GetDataConnectionXmlSettings {/* * Набор свойств для хранения данных * public string PropertyName { get; private set; } */ public CustomGetDataConnectionXmlSettings(IDependable parent, IWorkflowForm form, XmlNode node, XmlSqlQueryProvider queryProvider)
: base(parent, form, node) {/* * Здесь должен быть парсинг xml-кода, * чтобы получить значения тэгов и их атрибутов. */ } }}
Конструктор класса принимает параметры:
parent IDependable - ссылка на экземпляр класса CustomCommand, для которого создавался объект типа CustomCommandSettings;
form IWorkflowForm - форма, на которой описана кастомная команда;
node XmlNode - узел, который соответствует тэгу <Command>, описанному в xml-файле формы.
dataBindingProvider IDataBindingProvider -
Исполняемый код
Полный код класса:
usingSystem;usingSystem.Collections.Generic;usingSystem.Data;usingSystem.Threading.Tasks;namespaceWorkflowForms.DataConnections{publicclassCustomGetDataConnection:GetDataConnection {privateconststring SET_PROPERTY ="SetProperty";privateconststring ANY_PROPERTY ="AnyProperty";privateDataTable _table;privateIWorkflowForm _form;protectedList<Item> list =newList<Item>(); // Менеджер строковых ресурсов для поддержки языков в интерфейсе // private Template.StringManager _manager;#regionCustom Propertiesprivatestring _anyProperty;privatestring AnyProperty {get {return _anyProperty; }set { _anyProperty = value; // Когда изменяется значение свойства объекта, необходимо сделать рассылку события всем подписчикам.OnPropertyChange(ANY_PROPERTY); } }#endregionpublicCustomGetDataConnection(IWorkflowForm form,System.Xml.XmlNode node): base(form, node) { }#regionИнициализация DCpublicoverridevoidInternalInit(System.Xml.XmlNode node,IWorkflowForm form) { base.InternalInit(node, form); _form = form; // _manager = new Template.StringManager(form);LoadSettings(node, form); // Создаем структуру результирующей таблицыCreateTable(); }protectedvoidLoadSettings(System.Xml.XmlNode node,IWorkflowForm form) {var settings =newCustomGetDataConnectionXmlSettings(this, form, node,newXmlSqlQueryProvider());/* * Получение значений и сохранение в переменные */ }publicoverrideasyncTaskPostInit() {awaitRefresh();awaitTask.CompletedTask; }#endregion#regionОсновная логика // Метод, через который элементы формы будут получать данные из DCpublicoverrideDataTableGetDataTable() {return _table; }publicoverrideasyncTaskRefresh(string queryName =null) {awaitRefreshDataAsync();FillTable(); // Вызов метода для рассылки события подписчикам об изменении данных в DCOnChange(); }privateasyncTaskRefreshDataAsync() { // Получение строкового ресурса по ключу // string str = _manager.GetString("TextId"); }#endregion#regionSetPropertypublicoverridevoidSetProperty(string propertyName,Dictionary<string,object> parameters) {if (propertyName.Equals(SET_PROPERTY,StringComparison.OrdinalIgnoreCase)) { // Логика обработки }else { base.SetProperty(propertyName, parameters); } }#endregion#regionGetPropertypublicoverrideobjectGetProperty(string propertyName,Dictionary<string,object> parameters) {if (propertyName.Equals(ANY_PROPERTY,StringComparison.OrdinalIgnoreCase)) {return AnyProperty; }else {return base.GetProperty(propertyName, parameters); } }#endregion#regionЗаполнение таблицыprivatevoidFillTable() {_table.Clear();list.ForEach(item => {DataRow row =_table.NewRow();row["FirstColumn"] =item.FirstField;row["SecondColumn"] =item.SecondField;row["ThirdColumn"] =item.ThirdField;_table.Rows.Add(row); }); }#endregion#regionСоздание таблицыprivatevoidCreateTable() { // Пример создания колонок результирующей таблицы _table =newDataTable("myTableName");_table.Columns.Add(CreateColumn("FirstColumn",typeof(int)));_table.Columns.Add(CreateColumn("SecondColumn",typeof(string)));_table.Columns.Add(CreateColumn("ThirdColumn",typeof(bool))); }privateDataColumnCreateColumn(string columnName,Type dataType,object defaultValue =null) {var column =newDataColumn { ColumnName = columnName, DataType = dataType };if (defaultValue !=null) {column.DefaultValue= defaultValue; }return column; }#endregion }#regionВложенные типыpublicclassItem {publicint FirstField { get; set; }publicstring SecondField { get; set; }publicbool ThirdField { get; set; } }#endregion}
Get/Set-проперти
Кастомный GetDataConnection может иметь свои get и set-проперти, реализация которых описывается в методах GetProperty и SetProperty соответственно.
Обращение к set-проперти происходит через команду ValueSetCommand:
В конструкторе класса CustomGetDataConnectionXmlSettings необходимо прописать код вида:
// using WorkflowForms.Conditions;// public ICondition AnyCondition { get; private set; }string name =XmlParser.GetRequiredAttributeValue<string>( form, node,"AnyCondition","Name");AnyCondition =form.GetCondition(name);
Так как имя условия указывается в качестве значения атрибута обязательного тэга, то для его получения используется статический метод GetRequiredAttributeValue класса XmlParser. В третьем параметре (string path) указываем полный путь до тэга, значение атрибута которого нужно получить. Имя атрибута указывается в четвертом параметре (string attribute). Если элемент или его атрибут отсутствует, будет возвращено исключение типа InvalidXmlException.
Если необходимо получить значение необязательного атрибута, то следует использовать метод GetAttributeValue. Этот метод в случае отсутствия элемента или его атрибута будет возвращать значение по умолчанию, переданное в параметрах метода.
Имея имя условия, объект типа ICondition можно получить через переменную form типа IWorkflowForm, используя метод GetCondition.
Исполняемая часть
В методе LoadSettings из объекта settings, переданного в метод в качестве параметра, можно получить объект типа ICondition, обратившись к публичному свойству AnyCondition:
// using WorkflowForms.Conditions;// public ICondition _anyCondition;_anyCondition =settings.AnyCondition;
В методе ExecuteAsyncCommand можно получать значение условия, обращаясь к свойству Value:
if (_anyCondition.Value){ // ...}
SQL-запросы
Если соединение с данными должно отправлять на сервер запрос на выполнение SqlQuery, то всегда должно указываться имя процесса (WorkflowName), в рамках которого описан SQL-запрос. Аналогичный тэг указывается в описании PrimaryGetDataConnection.
Так как имя процесса и запрос являются обязательными для описания в команде, то для получения их значений используется статический метод GetRequiredAttributeValue класса XmlParser. В третьем параметре (string path) указываем полный путь до тэга, значение атрибута которого нужно получить. Имя атрибута указывается в четвертом параметре (string attribute). Если элемент или его атрибут отсутствует, будет возвращено исключение типа InvalidXmlException.
Исполняемая часть
В методе LoadSettings из объекта settings, переданного в метод в качестве параметра, можно получить имя процесса и имя SQL-запроса, который нужно выполнять:
// public string _workflowName;// public string _anySqlQueryName;_workflowName =settings.WorkflowName;_anySqlQueryName =settings.AnySqlQueryName;
В методе ExecuteAsyncCommand для выполнения запроса к серверной части, необходимо из объекта формы получить клиента серверной части (WorkflowEngineClient). В метод ExecuteQuery клиента необходимо передать имя процесса, имя SQL-запроса (описанного в серверном xml-файле) и словарь параметров, значения которых должны подставляться в текст запроса:
/* * Формирование словаря параметров, значения которых будут * подставляться в текст запроса вместо переменных */var parameters =newDictionary<string,object>() { // ...};DataTable table =await_form.WorkflowEngineClient.ExecuteQuery( _workflowName, _anySqlQueryName, parameters).ConfigureAwait(false);// var arr = table.AsEnumerable().ToList().Select(row => row["title"]);
Результатом выполнения метода ExecuteQuery будет таблица типа DataTable, дальнейшая работа с которой может быть с помощью LINQ, либо путем перебора всех строк:
В конструкторе класса CustomGetDataConnectionXmlSettings необходимо прописать код вида:
// using WorkflowForms.Controls;// public IControl AnyConrol { get; private set; }string name =XmlParser.GetRequiredAttributeValue<string>( form, node,"AnyControl","Name");AnyConrol =form.GetControl(name);
Так как имя объекта формы указывается в качестве значения атрибута обязательного тэга, то для его получения используется статический метод GetRequiredAttributeValue класса XmlParser. В третьем параметре (string path) указываем полный путь до тэга, значение атрибута которого нужно получить. Имя атрибута указывается в четвертом параметре (string attribute). Если элемент или его атрибут отсутствует, будет возвращено исключение типа InvalidXmlException.
Если необходимо получить значение необязательного атрибута, то следует использовать метод GetAttributeValue. Этот метод в случае отсутствия элемента или его атрибута будет возвращать значение по умолчанию, переданное в параметрах метода.
Имея имя объекта формы, объект типа IControl можно получить через переменную form типа IWorkflowForm, используя метод GetControl.
Исполняемая часть
В методе LoadSettings из объекта settings, переданного в метод в качестве параметра, можно получить ссылку на объект формы:
// using WorkflowForms.Controls;// private IControl _anyConrol;_anyConrol =settings.AnyConrol;
Для получения значения из объекта формы необходимо обращаться к свойству Value:
В конструкторе класса CustomGetDataConnectionXmlSettings необходимо прописать код вида:
// public IGetDataConnection AnyDataConnection { get; private set; }string name =XmlParser.GetRequiredAttributeValue<string>( form, node,"AnyDataConnection","Name");AnyDataConnection =form.GetDataConnection(name);
Так как имя DataConnection указывается в качестве значения атрибута обязательного тэга, то для его получения используется статический метод GetRequiredAttributeValue класса XmlParser. В третьем параметре (string path) указываем полный путь до тэга, значение атрибута которого нужно получить. Имя атрибута указывается в четвертом параметре (string attribute). Если элемент или его атрибут отсутствует, будет возвращено исключение типа InvalidXmlException.
Если необходимо получить значение необязательного атрибута, то следует использовать метод GetAttributeValue. Этот метод в случае отсутствия элемента или его атрибута будет возвращать значение по умолчанию, переданное в параметрах метода.
Имея имя соединения с данными, объект типа IGetDataConnection можно получить через переменную form типа IWorkflowForm, используя метод GetDataConnection.
Исполняемая часть
В методе LoadSettings из объекта settings, переданного в метод в качестве параметра, можно получить ссылку на DataConnection:
// using WorkflowForms.DataBindings;// private IGetDataConnection _anyDataConnection;_anyDataConnection =settings.AnyDataConnection;
Если кастомный DataConnection использует данные другого DataConnection, то необходимо установить зависимость первого от второго, чтобы гарантировать порядок загрузки при старте формы. Для этого в метод InternalInit класса CustomGetDataConnection необходимо добавить строки: