Какой смысл в украшениях WPF? - PullRequest
4 голосов
/ 14 июня 2011

Недавно я разработал компонент для рисования для своей компании, в котором есть холст, на котором вы можете рисовать определенные фигуры, используя щелчок и перетаскивание.Для каждой фигуры я поместил два украшателя на его слой AdornerLayer: один для увеличенного обнаружения попаданий (в основном прозрачный прямоугольник, который будет превышать границы фигуры на несколько пикселей), а другой для изменения размера (четыре элемента управления Thumb по углам).

Но я столкнулся с множеством проблем при реализации некоторых функций компонента, связанных с рекламой.

  • Они захватили все события предварительного просмотра, поскольку находились в другом визуальном дереве, чемСам холст, это было неожиданно, но я нашел обходной путь, даже если он мне не очень понравился.Использование AdornerDecorator не решило эту проблему, а создатель выбора, который я реализовал, является черной дырой для событий предварительного просмотра.

  • Когда я реализовал манипулирование z-индексами фигур на Canvas (отправить вназад, перенести на передний план и т. д.), все работало нормально, используя Panel.SetZIndex, как и следовало ожидать.Но украшатели в другом визуальном дереве!таким образом, они не были затронуты, и украшения выбора были ВСЕ ЕЩЕ поверх всех других форм, даже если эти формы были сверху той, для которой владелец выбора обнаруживал попадания.Например: Shape1, SelectionAdorner1.Shape2, SelectionAdorner2.Shape1 находится сверху (добавлен позже на холст) Shape2, поэтому перекрывает его.Таким образом, щелчок по нему будет обнаружен SelectionAdorner1.Я манипулировал ZIndex, чтобы отправить его обратно, теперь Shape2 находится сверху и перекрывает Shape1.Я щелкаю сверху Shape2, но щелчок обнаруживается SelectionAdorner1 вместо SelectionAdorner2.Это было особенно раздражающим.Так что, очевидно, поскольку Adorners находятся на другом визуальном дереве, они не уважают ZIndexes.Я попытался решить эту проблему, создав DataBinding (а также вручную установив) между ZIndex фигуры и ZIndex его SelectionAdorner.Но это не решило проблему.Изменение ZIndex of Adorners не повлияло на то, как они отображались на экране, возможно, я что-то упустил, но это не должно быть так сложно, поскольку Adorners должны быть сделаны, чтобы упростить ситуацию.Единственное решение, которое я мог придумать, - это вручную удалить все украшения и добавить их вручную, один за другим, добавив, наконец, тот, который должен был быть сверху.Это было отсталым, но это сработало.

  • Далее, Adorners не уважают ClipToBounds!Я установил ClipToBounds = true на холсте, на котором я рисовал, и он работал нормально, но чертовы украшения все равно будут работать!Решение этой проблемы было относительно безболезненным, я просто добавил AdornerDecorator поверх каждой фигуры.Не идеальное решение IMO, но достаточно простое.

  • Украсители не всегда хорошо реагируют на преобразования LayoutTransformation, выполняемые на их украшенных элементах.У меня есть панель поверх холста, которая реализует функции масштабирования и панорамирования.Он использовал анимацию, чтобы сделать масштабирование более плавным.Но использование анимации привело к тому, что мои Adorners перестали существовать!При первом увеличении они просто игнорируют изменение размера и сохраняют тот же размер и положение, а при втором увеличении они масштабируются до предыдущего размера украшенного элемента.Это не имеет никакого смысла!Единственное решение, которое я смог найти, было отключить анимацию, которая, к счастью, работала

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

Итак, кто-нибудь может сказать мне, что может быть плюсом в использовании этих, казалось бы, полезных, ноневероятно раздражающие вещи?

Спасибо.

1 Ответ

8 голосов
/ 14 июня 2011

Я думаю, вы уже знаете ответ на свой вопрос.Они экономят время в одних аспектах и ​​вызывают проблемы в других.Если бы вам пришлось кодировать это поведение дизайнера с помощью множества пользовательских элементов управления, вы бы написали множество шаблонных управляющих классов, чтобы обернуть элементы, которые вы на самом деле хотели редактировать.Если, с другой стороны, вы пытались написать отдельные элементы управления для редактирования и интеллектуально наложить их, вы бы писали стандартный код, чтобы синхронизировать их позиции и размеры.Подход, использованный вами с использованием украшателей, привел к появлению большого количества (довольно стандартного) кода для управления событиями.

Хотя украшатели могут быть не лучшим средством для этой конкретной задачи, они все еще остаютсяполезный инструмент для других, более простых задач.Недавно я написал подобный вид «поверхности дизайна», и украшения были находкой для двух частей:

  1. Поведение перетаскивания.Когда я перетаскивал разные элементы, они должны были иметь разные визуальные превью;это было удивительно легко сделать, используя пользовательский шаблон и шаблоны данных.
  2. Прямоугольник выбора или «лассо».Вы можете увидеть нечто подобное, когда вы удерживаете левую кнопку мыши на рабочем столе Windows и перетаскиваете указатель мыши.Он создает полупрозрачный блок, в котором можно выбрать несколько элементов.Я смог почти мгновенно создать это поведение со слоем adorner, тогда как создание собственного пользовательского элемента управления привело к большому количеству ненужного учета.

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

...