Полезный вспомогательный класс для выбора двух элементов
Вчера мы обсуждали как создать размер между центрами семейств. Код команды, переведённый в том примере, довольно небольшой.
Это обусловлено тем, что я использовал новый вспомогательный класс JtPairPicker, который помогает выбрать два элемента в модели.
Его можно использовать везде, где вам нужно автоматически или интерактивно в модели выбрать два элемента одного типа.
Класс довольно гибок в использовании и поддерживает три различных варианта выбора элементов:
- Если в модели содержится только два элемента заданного типа, они автоматически будут выбраны.
- Если в модели отсутствует два элемента заданного типа, выполнение команды будет прервано.
- Если в модели больше чем два элемента заданного типа, то предварительно происходит проверка, не выделены ли элементы этого типа перед запуском команды. Если элементы были выделены, то используются первые два.
- В любом другом случае пользователю предлагается выбрать два элемента требуемого типа.
Реализация класса основана на коде из статьи явное создание отводов при создании наклонного сегмента трубопровода, в котором выбор код по выбору труб занимал значительную часть кода.
Выделив выбор объектов в отдельный класс, код команды стал гораздо компактнее.
Реализованный класс – типизированный. В примере с размерами для выбора элементов был задан тип FamiliyInstance.
Вот полная реализация класса:
- /// <summary>
- /// Выбор двух элементов заданного типа.
- /// Если в модели только два объекта заданного типа, берем их.
- /// Если элементов меньше чем два, прерываем выполнение.
- /// Если перед запуском команды элементы были уже выделены, используем их.
- /// В противном случае предлагаем выбрать элементы пользователю
- /// </summary>
- class JtPairPicker<T> where T : Element
- {
- UIDocument _uidoc;
- Document _doc;
- List<T> _a;
- /// <summary>
- /// Разрешаем только выбор элементов типа T2.
- /// </summary>
- class ElementsOfClassSelectionFilter<T2> : ISelectionFilter
- {
- public bool AllowElement( Element e )
- {
- return e is T2;
- }
- public bool AllowReference( Reference r, XYZ p )
- {
- return true;
- }
- }
- public JtPairPicker( UIDocument uidoc )
- {
- _uidoc = uidoc;
- _doc = _uidoc.Document;
- }
- /// <summary>
- /// Возвращает результат выделения
- /// </summary>
- public IList<T> Selected
- {
- get
- {
- return _a;
- }
- }
- /// <summary>
- /// Запуск автоматического или интерактивного
- /// процесса выделения.
- /// </summary>
- public Result Pick()
- {
- // Извлекаем из модели все элементы типа T
- _a = new List<T>(
- new FilteredElementCollector( _doc )
- .OfClass( typeof( T ) )
- .ToElements()
- .Cast<T>() );
- int n = _a.Count;
- // Если элементов в модели меньше чем два,
- // то продолжать безссмысленно.
- if( 2 > n )
- {
- return Result.Failed;
- }
- // Если элементов всего два – берем их.
- if( 2 == n )
- {
- return Result.Succeeded;
- }
- // Если элементов больше чем два.
- // Проверяем не выбраны ли они перед запуском команды.
- _a.Clear();
- Selection sel = _uidoc.Selection;
- ICollection<ElementId> ids
- = sel.GetElementIds();
- n = ids.Count;
- Debug.Print( "{0} pre-selected elements.", n );
- // Если было выбрано два или более элементов типа T -
- // берем первые два.
- if( 1 < n )
- {
- foreach( ElementId id in ids )
- {
- T e = _doc.GetElement( id ) as T;
- Debug.Assert( null != e,
- "Могут быть выбраны элементы только типа T" );
- _a.Add( e );
- if( 2 == _a.Count )
- {
- Debug.Print( "Нашли два элемента заданного типа. Игнорируем все остальное");
- break;
- }
- }
- }
- // Если ничего не выбрано или выбрано меньше чем два элемента
- // предлагаем пользователю выбрать элементы
- if( 2 != _a.Count )
- {
- _a.Clear();
- // Выбираем первый элемент.
- try
- {
- Reference r = sel.PickObject(
- ObjectType.Element,
- new ElementsOfClassSelectionFilter<T>(),
- "Выберите первый элемент." );
- _a.Add( _doc.GetElement( r.ElementId )
- as T );
- }
- catch( Autodesk.Revit.Exceptions
- .OperationCanceledException )
- {
- return Result.Cancelled;
- }
- // Выбираем второй элемент.
- try
- {
- Reference r = sel.PickObject(
- ObjectType.Element,
- new ElementsOfClassSelectionFilter<T>(),
- " Выберите второй элемент." );
- _a.Add( _doc.GetElement( r.ElementId )
- as T );
- }
- catch( Autodesk.Revit.Exceptions
- .OperationCanceledException )
- {
- return Result.Cancelled;
- }
- }
- return Result.Succeeded;
- }
- }
Обсуждение: http://adn-cis.org/forum/index.php?topic=1699
Опубликовано 14.12.2014Отредактировано 27.12.2014 в 15:18:43