среда, 28 декабря 2011 г.

Обновление Менеджера листов

Доброго времени суток всем!
На форуме появился пост с ошибкой, связанной с менеджером листов. Совместными усилиями с  MaxHomeStudio удалось решить эту проблему. Как выяснилось значения скрытого параметра, куда записывается настройка менеджера, обнулились, что привело к ошибке. Новая версия менеджера проверяет правильность синтаксиса значения этого параметра и в случае ошибки предлагает перенастроить менеджер заново (указать ключевые параметры).

Скачать его можно тут.

воскресенье, 11 декабря 2011 г.

Получение и передача значений параметров.

Приветствую!
Недавно мне был задан вопрос по моему дополнению "Копирование параметров". Интересует каким образом получать и передавать параметры из разных объектов. Давайте начнем по порядку.

Прежде всего как нам позволить пользователю выбирать объекты. У нас есть возможность программно запустить процесс выбора объекта или обработать уже выбранные пользователем  до запуска нашей команды объекты. Первый способ выглядит так:


         Element pickedEl;
            try
            {
                var pickedRef = vnuiDocument.Selection.PickObject(ObjectType.Element, "Укажите элемент, чьи параметры будут копироваться(ESC - отмена)");
                pickedEl = vnuiDocument.Document.GetElement(pickedRef);
            }
            catch
            {
                pickedEl = null;
            }
            if (pickedEl == null)
                return Result.Cancelled;
pikedEl в данном контексте является переменной, которой будет присвоен выбранный элемент. Затем используется ключевое слово try и catch. Данные ключевые слова перехватывают исключения, проще говоря ошибки и позволяют нам их обработать. В данном случае я присваиваю нулевое значение pikedEl и в дальнейшем при нулевом значении выбранного элемента отменяю действия команды. При этом выполнение команды заканчивается.
Далее уже идет непосредственно сам метод, который позволяет пользователю сделать выбор объекта в рабочей области.

var pickedRef = vnuiDocument.Selection.PickObject(ObjectType.Element, "Укажите элементчьи параметры будут копироваться(ESC - отмена)");
pickedEl = vnuiDocument.Document.GetElement(pickedRef);

В атрибутах метода указан тип объекта для выбора ObjectType.Element и текст, который будет написан в строке состояния Revit. В качестве результата возвращается объект класса Reference.
Затем с помощью метода 
GetElement мы получаем элемент, который выбран пользователем. vnuiDocument это элемент класса UIDocument который мы получаем в самом начале кода.

UIDocument vnuiDocument = commandData.Application.ActiveUIDocument;

Второй способ выглядит так:
var refer = commandData.Application.ActiveUIDocument.Selection.Elements;

Из данного свойства мы получаем массив выбранных пользователем элементов до старта нашей команды.

Как получить элементы, выбранные пользователем разобрались. Теперь выясним как получить параметры элемента. Для этого достаточно получить массив параметров из свойства .Parameters элемента. Таким образом мы получим все параметры данного элемент. Но очень важный момент. В данном случае мы получим параметры вхождения, так как данный элемент является вхождением типа. Для параметров типа нужно получить элемент типа вхождения. Для этого нужно использовать метод .GetTypeId() и получив ElementId типа забрать его методом vnuiDocument.Document.GetElement(ElementId) Передав туда атрибутом ElementId.  
Для получения строкового значения параметра (то есть так, как оно написано в свойствах) используется вот этот метод:
/// <summary>
        /// Строковое значение параметра.
        /// summary>
        public string ParameterValueString
        {
            get
            {
                switch (Parameter.StorageType)
                {
                    case StorageType.Double:
                return Parameter.AsValueString();
                break;
                    case StorageType.Integer:
                if (Parameter.Definition.ParameterType == ParameterType.YesNo)
                {
                    if (Parameter.AsInteger() == 0)
                        return "false";
                    else
                        return "true";
                   
                }
                return Parameter.AsValueString();
                break;
                    case StorageType.String:
                return Parameter.AsValueString();
                break;
                    case StorageType.ElementId:
                Document doc = Parameter.Element.Document;
                string znachenie = "";
                Element el = doc.get_Element(Parameter.AsElementId());
                if (el != null)
                    znachenie = el.Name;
                else
                    znachenie = Parameter.AsValueString();
                return znachenie;
                break;
                    default:
                        return null;
                        break;
                }
            }
        }

Как видно почти везде используется метод .AsValueString(). Он возвращает строковое значение параметра, так как оно написано в свойствах. Но не все параметры возвращаются корректно. Например значение типа "Да\Нет". Для этого нужно определить тип представления параметра
if (Parameter.Definition.ParameterType == ParameterType.YesNo) 
и затем принудительно задать значение текста в зависимости от числового значения
                    if (Parameter.AsInteger() == 0)
                        return "false";
                    else
                        return "true";
Так же нужно обрабатывать значения параметров, которые содержат типы элементов. Это такие параметры, как например Базовая зависимость, Материал и т.д. Для этого нужно получить ElemenId параметра и затем вытащить элемент из документа а строке присвоить имя этого элемента. Если данный элемент отсутствует, то возвращаем строковое значение этого параметра.
                Document doc = Parameter.Element.Document;
                string znachenie = "";
                Element el = doc.get_Element(Parameter.AsElementId());
                if (el != null)
                    znachenie = el.Name;
                else
                    znachenie = Parameter.AsValueString();
                return znachenie;

Как получать читабельные значения параметров мы разобрались. Теперь разберемся как передавать эти значения. Тут все гораздо проще

        /// <summary>
        /// Копирует значения из параметра в соответствующий по имени параметр элемента
        /// summary>
        /// <param name="par">Параметрparam>
        /// <param name="El">Элемент, в который производится копированиеparam>
        private void CopyParameter(Parameter par, Element El)
        {
            Parameter toPar = El.get_Parameter(par.Definition.Name);
            if (toPar != null)
            {
                switch (par.StorageType)
                {
                    case StorageType.Double:
                        try
                        {
                            toPar.Set(par.AsDouble());
                        }
                        catch
                        { break; }
                        break;
                    case StorageType.String:
                        try
                        {
                            toPar.Set(par.AsString());
                        }
                        catch
                        { break; }
                        break;
                    case StorageType.Integer:
                        try
                        {
                            toPar.Set(par.AsInteger());
                        }
                        catch
                        { break; }
                        break;
                    case StorageType.ElementId:
                        try
                        {
                            toPar.Set(par.AsElementId());
                        }
                        catch
                        { break; }
                        break;
                    default:
                        break;
                }
            }
        }

Получив в качестве исходных данных целевой элемент El и параметр из которого будет копироваться значение par мы из элемента извлекаем параметр со схожим именем в строке
Parameter toPar = El.get_Parameter(par.Definition.Name);
Затем если такой параметр присутствует передаем ему значение из полученного в атрибутах параметра. Но передаем мы его в соответствии с типом переменной целевого элемента. При этом отлавливаем все ошибки передачи, такие как несовпадение типов параметра (имена могут определятся пользователем при создании элемента).



Итак мы рассмотрели:
  • способы получения выбранных пользователем элементов;
  • как получить параметры элемента;
  • как получить читабельное значение параметра;
  • получение параметра по имени;
  • и передачу значения параметра.
Надеюсь статья помогла кому-то разобраться в работе с параметрами элементов. Удачи в освоении Revit API! Пишите комментарии и посещайте форум сообщества. Так же следите за новостями. Может когда-то поблизости пройдет САПРяжение и нам удастся поговорить в живую :)