Лучший способ написать собственный элемент управления датчиком в WPF?

Мне нужно написать элемент управления датчиком в WPF для проекта на работе. Под манометром я подразумеваю что-то вроде традиционного автомобильного спидометра: круглая циферблат с цифрами и делениями по окружности и стрелка, указывающая на текущее значение. Хотя я мог бы заставить своего работодателя купить сторонний элемент управления или даже найти где-нибудь бесплатный, я все же хотел бы написать его сам, больше всего ради любопытства.

Моя первая мысль заключалась в том, чтобы «скрыть» существующий элемент управления с помощью шаблона, например, что-то вроде ProgressBar, поскольку он имеет свойства Minimum, Maximum и Value. Однако я не думаю, что это даст мне необходимую гибкость.

Я хотел бы анимировать стрелку, указывающую на текущее значение, чтобы при изменении значения датчика стрелка перемещалась от старого значения к новому значению. Я полагал, что самый простой способ сделать это — иметь какую-то форму или геометрию, представляющую стрелку, а затем применить RotateTransform с соответствующим числом градусов, чтобы стрелка указывала на правильное значение. Свойство To анимации будет установлено на свойство «степени значения» через привязку.

Мне кажется, что есть три основных подхода, которые я мог бы использовать:

Используйте один пользовательский FrameworkElement для представления всего датчика
Я мог бы получить от FrameworkElement, переопределить его метод OnRender, а затем использовать DrawingContext для рисования лицевой стороны датчика и стрелки. Это означало бы, что я больше не мог бы анимировать стрелку напрямую с помощью RotateTransform, а вместо этого должен был бы перерисовывать всю шкалу каждый раз, когда значение изменяется. Мне это кажется неэффективным, так как поверхность датчика представляет собой большую часть кода рисования, но меняется очень редко. Однако этот подход является самым легковесным с точки зрения количества используемых элементов.

Используйте два пользовательских элемента FrameworkElements, один для лица и один для иглы
Сейчас я склоняюсь к этому подходу. Один элемент будет представлять лицо, другой — иглу. Это позволило бы мне нацелить элемент иглы с помощью RotateTransform. В этом случае элемент управления датчиком будет состоять из трех элементов: лица, иглы и контейнера Panel для их хранения (т. е. Canvas, Grid и т. д.). Таким образом, три элемента вместо одного, следовательно, не такие легкие, как первый подход.

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

Любые мысли или советы относительно того, какой подход люди считают лучшим и почему, будут приветствоваться!


person Steve Rands    schedule 23.04.2009    source источник


Ответы (2)


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

person Bryan Anderson    schedule 23.04.2009
comment
Я думаю, что это лучший подход, учитывая мои критерии. Я не смог написать элемент управления таким образом по ряду причин (в основном из-за отсутствия опыта работы с WPF на сегодняшний день), поэтому в конце концов я фактически выбрал подход № 1. - person Steve Rands; 11.05.2009

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

person Lukasz    schedule 24.04.2009
comment
Хотя это сработало бы в некоторых обстоятельствах, это был не тот подход, который я мог бы использовать, учитывая мои требования (которые, возможно, мне следовало уточнить в вопросе). Масштаб датчика должен был быть переменным (т. е. мин/макс диапазон и количество делений изменялись), плюс мне нужны были другие свойства для представления цветных диапазонов на датчике и так далее. Я не верю, что смог бы добиться этого, просто стилизовав существующий элемент управления; Я не видел способа представить что-то подобное в разметке. - person Steve Rands; 11.05.2009