Ошибка: Создаем несколько разметок для разных видов карточки. При редактировании каждой разметки (добавлении контролов), причем только в случае использования многозакладочности, имена контролам могут присвоиться одинаковые для разных разметок. КР сначала не видит ошибку. Но при закрытии КР и повторном входе выдает ошибку о нескольких контролах с одинаковым именем.
Способ решения: при добавлении контролов в разные разметки карточки нужно не допускать совпадания имен контролов, иначе карточка станет недоступна для редактирования. При перезагрузке КР и навигатора карточка загружается без последних изменений.
Мы обсуждаем следующие темы: Docsvision, редактирование и создание карточек документов, процесс, написание кода на C#
Темы обсуждений
бизнес-календарь
(2)
бизнес-процесс
(1)
блог
(3)
виды
(2)
дайджест
(1)
дополнительные сборки
(1)
изображение
(1)
карточки
(4)
кнопка
(1)
конструктор
(9)
литература
(1)
навигатор
(1)
настройка представлений
(1)
нумератор
(2)
ошибки
(3)
полезность
(1)
разметки
(2)
роли
(1)
сервер
(1)
сервис
(1)
скрипт
(12)
состояния
(1)
табличный контрол
(3)
уведомления
(1)
attribute
(1)
C#
(11)
DevExpress
(1)
DVCardManager
(2)
DVExplorer
(1)
HowTo
(18)
property
(3)
xml
(1)
XSLT
(1)
Поиск блогу
суббота, 12 февраля 2011 г.
Продолжение рассмотрения пространства имен BusinessCalendar.
Пару постов назад я начал писать про пространство имен DocsVision.BackOffice.Model.BusinessCalendar.Entities. Упоминал, что в нем содержатся 2 перечислимых типа DayType и TimeType.
Для справки: Перечислимый тип - это тип данных, переменные которого могут принимать значения заранее заданные пользователем. Например, можно создать тип "Animals", и возможными значениями у этого типа сделать "Horse, Pig, Cat, Dog, Cow". Тогда переменная типа Animals сможет принять значение Animals.Horse или, к примеру, Animals.Cat.
Ниже приведу значения для типов DayType и TimeType.
Для справки: Перечислимый тип - это тип данных, переменные которого могут принимать значения заранее заданные пользователем. Например, можно создать тип "Animals", и возможными значениями у этого типа сделать "Horse, Pig, Cat, Dog, Cow". Тогда переменная типа Animals сможет принять значение Animals.Horse или, к примеру, Animals.Cat.
Ниже приведу значения для типов DayType и TimeType.
- DayType
- Holiday
- NonWorking
- Working
- TimeType
- Work
- NotWork
пятница, 11 февраля 2011 г.
Просмотр структуры карточки.
Иногда возникает потребность просмотреть, какие свойства содержит та, или иная карточка.
Для этого можно воспользоваться утилитой DVExplorer, входящей в SDK.
После запуска утилиты и подключения к базе выбираем пункт "Card Types..."

Для этого можно воспользоваться утилитой DVExplorer, входящей в SDK.
После запуска утилиты и подключения к базе выбираем пункт "Card Types..."
Темы, поднимаемые в сообщении:
карточки,
DVExplorer,
HowTo,
xml
Обращение к карточке Бизнес-календаря. Примерная структура класса.
Ни для кого не секрет, что существует тип карточек "Бизнес-календарь". Они позволяют задать расписание работы, рабочие часы для подразделений и выполняют подобные этим функции.
Для того, чтобы обратиться к конкретной карточке календаря нужно узнать ее Guid. Проще всего это сделать, кликнув на бизнес-календарь правой кнопкой и зайти в свойства. Внизу будет указан URL карточки, он то и будет содержать легко узнаваемый Guid.

Далее в самой карточке нужно сделать следующее:
В результате выполнения будет создан объект класса Calendar, имеющий весьма сложную структуру. Кроме свойств и методов, унаследованных от класса DomainObject, он включает в себя поле DefaultWorkTime типа IList (как я понял, так же представлены столбцы в табличном контроле). DefaultWorkTime содержит соответственно поля StartTime и EndTime, содержащие границы рабочего дня по-умолчанию. Они используются, если в календаре не приписаны рабочие часы, отличающиеся от них.
Если же рабочие часы заданы индивидуально для каждого дня, то нужно будет обращаться к полю Years (IDictionary), содержащему данные о каждом дне (int DayNumber,enum Type(Working,NonWorking,Holiday),IList WorkTime:(StartTime,EndTime)).
Также для работы с календарем может быть полезен класс WorkTimeCalculator, который содержит два метода: GetDayTimeWorkStatus(DateTime date) и GetDayWorkStatus(DayTime date), возвращающие значения типов TimeType и DayType соответственно.
Создать объект класса WorkTimeCalculator можно следующим способом:
Для того, чтобы обратиться к конкретной карточке календаря нужно узнать ее Guid. Проще всего это сделать, кликнув на бизнес-календарь правой кнопкой и зайти в свойства. Внизу будет указан URL карточки, он то и будет содержать легко узнаваемый Guid.
Далее в самой карточке нужно сделать следующее:
using DocsVision.BackOffice.Model.BusinessCalendar.DataAccess;
using DocsVision.BackOffice.Model.BusinessCalendar.Entities;
/*
.
.
.
*/
Guid calGuid = new Guid("F827960F-6E61-40AD-A7E4-63AF74FAB54A");
Calendar cal = new CalendarMapper(Session).Find(calGuid);
В результате выполнения будет создан объект класса Calendar, имеющий весьма сложную структуру. Кроме свойств и методов, унаследованных от класса DomainObject, он включает в себя поле DefaultWorkTime типа IList (как я понял, так же представлены столбцы в табличном контроле). DefaultWorkTime содержит соответственно поля StartTime и EndTime, содержащие границы рабочего дня по-умолчанию. Они используются, если в календаре не приписаны рабочие часы, отличающиеся от них.
Если же рабочие часы заданы индивидуально для каждого дня, то нужно будет обращаться к полю Years (IDictionary), содержащему данные о каждом дне (int DayNumber,enum Type(Working,NonWorking,Holiday),IList WorkTime:(StartTime,EndTime)).
Также для работы с календарем может быть полезен класс WorkTimeCalculator, который содержит два метода: GetDayTimeWorkStatus(DateTime date) и GetDayWorkStatus(DayTime date), возвращающие значения типов TimeType и DayType соответственно.
Создать объект класса WorkTimeCalculator можно следующим способом:
using DocsVision.BackOffice.Model.BusinessCalendar;
using DocsVision.BackOffice.Model.BusinessCalendar.DataAccess;
using DocsVision.BackOffice.Model.BusinessCalendar.Entities;
/*
.
.
.
*/
Calendar cal = new CalendarMapper(Session).Find(new Guid("00000000-0000-0000-0000-000000000000"));
WorkTimeCalculator calc = new WorkTimeCalculator(cal);Примечание: вместо 00000000-0000-0000-0000-000000000000 укажите нужный Guid.
Темы, поднимаемые в сообщении:
бизнес-календарь,
скрипт,
C#,
HowTo
среда, 9 февраля 2011 г.
Обращение к данным карточки сотрудника. Программирование действий в ответ на клик по кнопке.
Идея такова: мы выбираем сотрудника в соответствующем контроле типа "сотрудник", затем кликаем по контролу "кнопка", в ответ на что в отдельном свойстве появляется, к примеру, Email или Телефон сотрудника.
Эту задачу можно решить двумя способами:
1 способ (в обход объект-модели):
2 способ (через объект-модель):
Эту задачу можно решить двумя способами:
1 способ (в обход объект-модели):
private void Свойство10_Click(System.Object sender, System.EventArgs e) //Свойство10 - у меня имя кнопки
{
Guid? employeeId=(Guid?)PropertyController.GetPropertyValue("Автор"); //employeeId - ключ на карточку по свойству "Автор". "Автор" - имя контрола типа "сотрудник"
if (employeeId.HasValue) //проверка существования значения ключа employeeId
{
var empl=new DocsVision.BackOffice.Model.StaffModel.DataAccess.EmployeeMapper(Session).Find(employeeId.Value); //новая переменная, в которую записываем значение employeeId.Value
PropertyController.UpdateProperty("Свойство12",empl.Email); //Записываем в свойство типа "строка" значение empl.Email. Соответственно мы можем вытащить в качестве значение не только Email, а практически любое свойство карточки сотрудника
PropertyController.RefreshControls(); //обновляем контролы, чтобы отобразилось новое значение
}
else
{
MessageBox.Show("Ошибка"); //сообщение об ошибке, если employeeId не имеет значения
}
}
2 способ (через объект-модель):
private void Свойство10_Click(System.Object sender, System.EventArgs e)
{
Guid? employeeId=(Guid?)PropertyController.GetPropertyValue("Автор");
if (employeeId.HasValue)
{
RowData employeeData=Session.CardManager.GetDictionaryData(new Guid("6710B92A-E148-4363-8A6F-1AA0EB18936C")).Sections[new Guid("DBC8AE9D-C1D2-4D5E-978B-339D22B32482")].GetRow(employeeId.Value);
//RefStaffCardId = 6710B92A-E148-4363-8A6F-1AA0EB18936C (Правой кнопкой на справочник сотрудников, экспорт, XML карточки)
//Employee = DBC8AE9D-C1D2-4D5E-978B-339D22B32482 (C:\Program Files\DocsVision\Platform\4.5\Server\Tools\Database\TakeOffice\RefStaff.xml - строчка с employee)
PropertyController.UpdateProperty("Свойство12",employeeData["Phone"].ToString()); //Phone - стандартное имя ячейки в базе данных, хранящей значение "Телефон" определенного сотрудника
PropertyController.RefreshControls();
}
else
{
MessageBox.Show("Ошибка");
}
}
Скрипт из мануала.
для того, чтобы при открытии карточки,ей присваивался регистрационный номер автоматически, существует след скрипт:
отыскиваете в событиях карточки событие AfterActivate, жмете три точки и открывается скрипт,первая строка генерится автоматически,а далее копируем скрипт)
отыскиваете в событиях карточки событие AfterActivate, жмете три точки и открывается скрипт,первая строка генерится автоматически,а далее копируем скрипт)
private void cardControl_AfterActivate(System.Object sender, System.EventArgs e)
{
var numeratorProperty = GetCardProperty("Нумератор"); //здесь в скобках идет настоящее имя вашего регистратора, у меня "нумератор"
if (numeratorProperty.Value != null)
{
return;
}
var ruleAttribute = numeratorProperty.Description.GetAttribute("Rule"); //обратите внимание,что в этом месте как раз идет НЕ настояшее имя вашего правила для регистратора,а стандартное название Rule
Guid? ruleId = (Guid?)ruleAttribute.Value;
var numeratorMapper = new DocsVision.BackOffice.Model.CardProperties.DataAccess.NumeratorNumberMapper(Session, CardData.Id, DomainObject.NumbersSectionId.Value);
var number = numeratorMapper.Create(ruleId.Value);
numeratorProperty.Value = number;
PropertyController.RefreshControls();
}
private CardProperty GetCardProperty(string propertyName)
{
foreach (CardProperty property in PropertyController.CardProperties)
{
if (property.Name == propertyName)
return property;
}
return null;
}
Пара багов
При написании скрипта наткнулся на следующую ошибку:
Ошибка
Если на карточке лежит контрол "Время", то, если в него не было принудительно записано какое-то значение через скрипт (значение по-умолчанию не в счет), то при попытке считать значение контрола возвращается объект неправильного типа.
Способ решения
Задавать значения по-умолчанию для этого контрола в событии карточки CardInitialized.
Ошибка
Если на карточке есть скрытый контрол, то данные о изменении его значения будут также выводиться в истории.
Способ решения
Пока не придуман.
Ошибка
Если на карточке лежит контрол "Время", то, если в него не было принудительно записано какое-то значение через скрипт (значение по-умолчанию не в счет), то при попытке считать значение контрола возвращается объект неправильного типа.
Способ решения
Задавать значения по-умолчанию для этого контрола в событии карточки CardInitialized.
Ошибка
Если на карточке есть скрытый контрол, то данные о изменении его значения будут также выводиться в истории.
Способ решения
Пока не придуман.
Получение типа значения контрола
Часто при считывании значения свойства карточки может возникнуть вопрос о том, какого типа нужно создать переменную для хранения этого значения.
Для того, чтобы узнать тип значения свойства, можно воспользоваться следующим методом:
Для того, чтобы узнать тип значения свойства, можно воспользоваться следующим методом:
MessageBox.Show(PropertyController.GetPropertyValue("ИмяСвойства").GetType().ToString());
В результате при выполнении скрипта будет показано окно сообщения с названием типа выбранного свойства.
Темы, поднимаемые в сообщении:
конструктор,
скрипт,
C#,
HowTo,
property
Вступление
Всем привет!
Вот и возник наш блог) Дизайн и структура возможно будут дорабатываться по мере необходимости.
В данный момент оставлять сообщения и комментарии могут только участники блога, получившие приглашения, и у блога отключена индексация в поисковых системах.
Вот и возник наш блог) Дизайн и структура возможно будут дорабатываться по мере необходимости.
В данный момент оставлять сообщения и комментарии могут только участники блога, получившие приглашения, и у блога отключена индексация в поисковых системах.
Подписаться на:
Сообщения (Atom)