Поиск блогу

четверг, 30 июня 2011 г.

Получение данных выделенной строки из таблицы

Вывод выделенной строки оказался весьма нетривиальным заданием.

Данный фрагмент кода выведет в MessageBox содержимое выделенной строки в табличном контроле с названием "Журнал заявки".

LayoutHelper layoutHelper = new LayoutHelper(CardControl.LayoutControl, CardControl.BarManager, Session, CardData.Type.Id);
DocsVision.BackOffice.View.WinForms.LayoutItems.ICustomPropertyItem propertyItem = layoutHelper.GetCustomPropertyItem("Журнал заявки");
var refMapper = new CardPropertyDescriptionMapper(Session);
DocsVision.BackOffice.Model.CardProperties.Entities.CardPropertyTable cpt = null;
foreach (DocsVision.BackOffice.Model.Layouts.Entities.CardPropertyTableDescription refPropertyTableDesc in refMapper.FindTableProperties(CardData.Type.Id))
          {
              if (refPropertyTableDesc.Name == "Журнал заявки")
               {
                 var propertyMapper = new CardPropertyMapper(Session, CardData.Id, DomainObject.CustomPropertiesSectionId);
                   cpt = propertyMapper.FindTable(refPropertyTableDesc);
                   break;
               }
          }
System.Reflection.Assembly asm = System.Reflection.Assembly.Load("DocsVision.BackOffice.View, Version=4.5.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519");
Type tableType = asm.GetType("DocsVision.BackOffice.View.WinForms.PropertyControls.TablePropertyControl");
var propInfo = tableType.GetProperty("GridView");
object ooo = propInfo.GetValue(propertyItem.Control, System.Reflection.BindingFlags.NonPublic, null, null, System.Globalization.CultureInfo.InvariantCulture);
DocsVision.BackOffice.View.WinForms.Controls.GridExView gridExView = ooo as DocsVision.BackOffice.View.WinForms.Controls.GridExView;
DevExpress.XtraGrid.Views.Grid.GridView gridView = gridExView as DevExpress.XtraGrid.Views.Grid.GridView;
object key = ((System.Data.DataRowView)gridView.GetFocusedRow()).Row[gridExView.KeyField];
          foreach (DocsVision.BackOffice.Model.CardProperties.Entities.CardPropertyTableRow row in cpt.Rows)
          {
              if (row.Key == (Guid)key)
              {
                  string message = "";                  
                  foreach (DocsVision.BackOffice.Model.CardProperties.Entities.CardProperty cellProp in row.Cells)
                      {
                       object val = cellProp.Value;                          
                       message += val == null ? "null" : val.ToString();
                       message += " ";    
                      }
                      MessageBox.Show(message);
                      }
    
              }


Для работы скрипта нужно прописать в using:

using DocsVision.Platform.WinForms.DataSource;
using DocsVision.BackOffice.Model.CardProperties.DataAccess;


Возможно, что-то еще...

а также подключить сборки DevExpress. А именно
DevExpress.XtraLayout.9.2.dll
DevExpress.XtraGrid.9.2.dll
DevExpress.Data.9.2.dll
DevExpress.Utils.9.2.dll

Добавление новой строки в табличный контрол из скрипта

Оговорю сразу, что данный метод работает, если для табличного контрола создана отдельная секция в карточке, так как добавление происходит через добавление записи в секцию.

Рассмотрим на примере таблицы, содержащей 3 столбца: Дату, идентификатор сотрудника и некоторый текст.

в приведенном скрипте:
secComment - это идентификатор табличной секции(Guid);
comment - какая-то строка(string)

Скрипт записывает текущую дату, пользователя, который открыл карточку в данный момент и некоторый текст.

Guid g = Guid.NewGuid();
CardData.Sections[secComment].BeginUpdate();
RowData newComment = CardData.Sections[secComment].CreateRow(g);
newComment.SetString("Текст", comment);
newComment.SetGuid("Автор", new EmployeeMapper(Session).GetCurrentUserId());
newComment.SetDateTime("Дата", DateTime.Now);
CardData.Sections[secComment].EndUpdate();

суббота, 21 мая 2011 г.

Смена атрибутов контрола из скрипта. На примере атрибута ReadOnly

Данный скрипт полезен в тех случаях, когда, например, измененное значение одного контрола влияет на доступность другого.

using System;
using System.Windows.Forms;
using DocsVision.Platform.ObjectManager;
using DocsVision.BackOffice.View.WinForms;
using DocsVision.BackOffice.Model;
using DocsVision.BackOffice.Model.Layouts.DataAccess;
using DocsVision.BackOffice.Model.Base.Entities;
using DocsVision.BackOffice.Model.CardProperties.Entities;
using DocsVision.BackOffice.Model.Layouts.Entities;
using DocsVision.BackOffice.Model.RoleModel.DataAccess;
using DocsVision.BackOffice.Model.RoleModel.Entities;
using DocsVision.BackOffice.View.WinForms.Helpers;

private void cardControl_AfterActivate(System.Object sender, System.EventArgs e)
    {
  CardProperty prop = GetCardProperty("имя контрола");
  CardPropertyDescription.LayoutAttributeSet attrSet = prop.Description.GetLayoutAttributes(CardControl.DomainObject.SelectedLayoutId);
        attrSet.ReadOnly = true;
        PropertyController.Refresh();
    }

//Поиск контрола с нужным именем  
private CardProperty GetCardProperty(string propertyName)
 {
 foreach (CardProperty property in PropertyController.CardProperties)
  {
  if (property.Name == propertyName)
  return property;
  }
 return null;
 }

среда, 11 мая 2011 г.

Перезапуск сервисов из командной строки

Думаю, что многие сталкивались с проблемой, что какие-то изменения, внесенные в структуру DV требовали перезапуска серверов, SQL и IIS. На это уходит много времени, так как надо полазать по различным административным менюшкам и покликать много кнопок.

Я предлагаю вариант, когда перезапуск всех служб можно будет делать по двойному клику на ярлык на рабочем столе.

1. создаем новый текстовый файл.
2. в тело пишем

NET stop DVStorageServer45
NET stop WFServer45
NET stop MSSQL$SQLEXPRESS
IISReset
NET start MSSQL$SQLEXPRESS
NET start DVStorageServer45
NET start WFServer45


3. сохраняем файл на рабочий стол под именем Reset.bat и в свойствах файла выставляем "Запускать от имени Администратора". Иногда для этого приходится создать ярлык на этот батник и в его свойствах поставить запуск от имени администратора.
4. наслаждаемся перезапуском в один клик.

P.S. Возможно, что SQL сервер у вас называется не SQLEXPRESS. В таком случае либо просто удалите из батника строку перезапуска SQL (Обычно такой перезапуск не требуется), либо впишите свое название сервера.

Скрипт смены состояния карточки из бизнес-процесса

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


// подключение системных библиотек
using System;
using System.Xml;

// подключение библиотек СУБП
using DocsVision.Workflow.Objects;
using DocsVision.Workflow.Runtime;
using DocsVision.Workflow.Gates;
using DocsVision.Platform.HelperAPI;
using DocsVision.Platform.ObjectManager;

namespace DVScriptHost
{
   class DVScript
   {
       // стандартная функция, которая будет вызвана подсистемой СУБП
       //
       // входные параметры функции:
       //
       // process - информация о процессе. содержит коллекции
       //     Gates - коллекция шлюзов процесса
       //     Variables - коллекция переменных процесса
       // passInfo - информация о текущем проходе
       //
        private string state = "Согласование с контрагентом"; //Название состояния, в которое мы хотим перевести карточку
        private DVGate m_DVGate;
       public void Execute (DocsVision.Workflow.Runtime.ProcessInfo process, PassState passInfo)
       {
            try
            {
                //Получаем ссылку на карточку, у которой надо сменить состояние. В данном случае она хранится в переменной процесса, которая называется "Инициирующий договор"
                ProcessVariable pvCard = process.GetVariableByName("Инициирующий договор");
                DVCard dvCard = (DVCard)pvCard.Value;

                //получаем шлюз
                m_DVGate = (DVGate)process.Gates[DVGate.GateID];

                // получаем сессию
                UserSession oSes = m_DVGate.Session;
                  
                //Получаем данные карточки
                CardData card = oSes.CardManager.get_CardData(dvCard.ID);

                //Получаем ссылку на секцию "Основная информация". Так как карточка стандартная, то гуид берем из справочника в предыдущем посте. В противном случае - из DVExplorer.
                SectionData mainInfo = card.Sections["8C77892A-21CC-4972-AD71-A9919BCA8187"];

                //Получаем ссылку на справочник типов. Гуид берем из справочника в предыдущем посте.
                CardData RefTypes = oSes.CardManager.get_DictionaryData("BE14D55D-92B7-4345-AD10-32588981F83D");

                //Получаем тип карточки из справочника типов
                RowData currentType = RefTypes.Sections["49AD5A2D-17EC-46E2-A49E-C58D0BBD9C1A"].Rows[mainInfo.FirstRow.get_Value("Type")];

                //Устанавливаем состояние карточки, найдя его по имени и в соответствии с типом карточки
                mainInfo.FirstRow.set_Value("DocState", currentType.ChildRows.GetItemByValue("Name", state).ID);

            }
            catch (Exception ex)
            {
                 // запись в журнал ошибки исполнения
                 process.LogMessage("Ошибка выполнения скрипта:" + ex.Message);
            }
            return;
        }
    }
}

Описание полей стандартных карточек.

Думаю, что многие из вас сталкивались с проблемой отсутствия документации по структуре стандартных справочников и карточек. Я сам лично довольно долго мучился в поисках подобной информации, но недавно мне удалось найти очень полезный документ, в котором содержатся описания всех полей стандартных карточек.
Также, благодаря этому документу я выяснил, что у всех стандартных карточек и справочников постоянные идентификаторы, которые не зависят от того, где установлена система. Они тоже приведены в этом файле.
Описание полей стандартных карточек.doc

Также, если кому-то нужна литература по C#, то выкладываю самоучитель: Секунов С.Ю. - Самоучитель С# - 2001.pdf

И также самоучитель по xml: samou4itel_xml.rar

Новости блога. Дополнительные возможности при просмотре блога.

Благодаря нововведениям платформы Blogger, наш блог теперь можно просматривать в различных видах, используя страницу видов. Ссылка на данную страницу теперь всегда доступна из списка полезных ссылок справа.

Подробнее об этой фиче можно почитать тут.

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

четверг, 10 марта 2011 г.

Добавление пользовательского свойства карточки в представление

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

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

В примере Договора в табличном контроле 2 столбца: Контрагент и его адрес.
Free Image Hosting at www.ImageShack.us
Задача: вывести в представлении фамилию контрагента. Вот так:
Free Image Hosting at www.ImageShack.us

Сначала делаем все, как и при обычном создании представления: создаем представление, добавляем колонки.
Затем нужно сделать следующие присоединения:
1.Free Image Hosting at www.ImageShack.us
Привязываем свойство с названием "Контрагент", принадлежащее данной карточке (InstanceID)
2.Free Image Hosting at www.ImageShack.us
Не очевидная привязка выбранных значений. Нужна, так как столбец табличного контрола представляет собой массив. После этого в после "Выбранное значение" будут находиться идентификаторы контрагентов
3.Free Image Hosting at www.ImageShack.us
Получение по Идентификатору из выбранного значения информации о контрагенте.

После перечисленных привязок можно сделать присвоение колонке значения поля Фамилия из привязанной карточки контрагентов:
Free Image Hosting at www.ImageShack.us

P.S. Если есть проблема с добавлением простого (не табличного) пользовательского свойства в представление, дайте знать в комментах. В таком случае напишу и про них.

воскресенье, 6 марта 2011 г.

Смена состояния карточки из скрипта

На первый взгляд простое задание - сменить состояние карточки из скрипта. Вроде и у карточки стандартная кнопка для смены состояния есть, но и тут не обходится без бубна.

На данный момент простого способа сменить состояние из скрипта я не нашел. Единственный способ требует знания гуида конечного состояния. Данный идентификатор не доступен ни в одном из стандартных справочником и контекстных меню, поэтому приходится идти в обход.

Создаем строковый контрол на карточке. Затем на какую-нибудь кнопку ставим команду, записывающую в этот котрол значение из DomainObject.StateManager.CurrentStateId. (В моем случае по какой-то причине на активацию карточки поставить не удалось, только на кнопку или команду меню). Сохраняем карточку, закрываем конструктор.

Открываем карточку в навигаторе, прогоняем состояние карточки стандартной кнопкой "Сменить состояние" до нужного состояния и выполняем скрипт, записывающий состояние в строку. Вот он наш искомый гуид.

Далее в конструкторе в нужном Вам месте пишем:
DomainObject.StateManager.SetCurrentState(new Guid("fce438e8-d38c-4552-86d0-36d464920265"));

CardControl.RefreshLayout();

Вместо "fce438e8-d38c-4552-86d0-36d464920265" конечно же нужно поставить нужный гуид.

P.S. Я полагаю, что возможно как-то менять состояние карточки проще, используя команду DomainObject.ChangeCardState(StateMachineBranch branch), но я так и не смог понять, как ей пользоваться. Если кто-то разберется, то очень хотел бы получить совет в комментах.

среда, 2 марта 2011 г.

Вызов картинки с локального диска, запись в стандартный контрол типа "изображение"

System.Drawing.Image image = System.Drawing.Image.FromFile(@"c:\Img.jpg");

PropertyController.UpdateProperty("imageControl", image); //imageControl - имя контрола типа "Изображение"

CardControl.RefreshLayout();