Построение элемента управления WPF - PullRequest
0 голосов
/ 21 октября 2018

Я реализовал элемент управления в качестве пользовательского в WPF.Он работает очень хорошо, но я столкнулся с проблемой, которая заставляет меня усомниться в правильности его структуры.

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

Элемент управления верхнего уровня содержит два набора диапазонов и указателей.

Диапазон определяет цветную область на шкале.Это простой объект с несколькими свойствами.

Указатель, довольно очевидно, определяет указатель на датчике.Измеритель может иметь несколько указателей, а указатели могут иметь разные стили, например, иглу, цветной блок или ползунок (который пользователь может перетаскивать).

Это пример конфигурации:

<gauge:Gauge MinValue="0"
             MaxValue="350"
             MajorDivisions="7"
             MinorDivisions="5"
             Caption="Bar"
             Background="White"
             LabelOrientation="Horizontal"
             BorderThickness="3"
             StartAngle="-180"
             EndAngle="135"
             MinorTickMarkColor="Black"
             MajorTickMarkColor="Black"
             LabelsOnTicks="Even"
             LabelRadiusRelative="0.65"
             Template="{StaticResource DefaultRotaryGauge}" >
  <gauge:Gauge.Ranges>
    <gauge:Range MinValue="200"  MaxValue="350" Color="Green"/>
  </gauge:Gauge.Ranges>
  <gauge:Gauge.Pointers>
    <gauge:Pointer Position="{Binding Position1}" ShowNumericValue="Visible" Color="LightGray"/>
    <gauge:Pointer Position="{Binding Position2}" ShowNumericValue="Visible" Color="Red"/>
  </gauge:Gauge.Pointers>
  <gauge:Gauge.LabelStyle>
    <Style TargetType="TextBlock">
      <Setter Property="FontSize" Value="10"/>
      <Setter Property="Foreground" Value="Black"/>
    </Style>
  </gauge:Gauge.LabelStyle>
</gauge:Gauge>

Как показано выше, позиция указателя должна работать с привязкой, поэтому она должна быть свойством зависимости и, насколько я понимаю, должна находиться в дереве визуалов.

Для этой цели класс указателя определяется как элемент управления.

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

Например, мой шаблон управления для термометра поддерживает два указателястили, которые выбираются следующим образом.

<ItemsControl ItemsSource="{TemplateBinding Pointers}"
                            Grid.Row="2"
                            Grid.Column="3"
                            ItemsPanel="{StaticResource GridTemplate}">
  <ItemsControl.ItemContainerStyle>
    <Style TargetType="local:Pointer">
      <Setter Property="Control.Template" Value="{StaticResource ThermometerPointer}"/>
      <Style.Triggers>
        <Trigger Property="DisplayStyle" Value="Block">
          <Setter Property="Control.Template" Value="{StaticResource ThermometerBlock}"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </ItemsControl.ItemContainerStyle>
</ItemsControl>

Пока все хорошо.

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

<gauge:Pointer Position="{Binding Position1}" DisplayStyle="Block">
  <gauge:Pointer.Style>
    <Style TargetType="gauge:Pointer">
      <Setter Property="Color" Value="Red"/>
      <Style.Triggers>
        <DataTrigger Value="True">
          <DataTrigger.Binding>
            <MultiBinding Converter="{StaticResource GreaterThanConverter}">
              <Binding Path="Position1"/>
              <Binding Source="200.0"/>
            </MultiBinding>
          </DataTrigger.Binding>
          <Setter Property="Color" Value="Blue"/>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </gauge:Pointer.Style>
</gauge:Pointer>

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

Я смог исправить это, указавControl.Template в дополнение к DataTrigger.

<gauge:Pointer Position="{Binding Position1}" DisplayStyle="Block">
  <gauge:Pointer.Style>
    <Style TargetType="gauge:Pointer">
      <Setter Property="Control.Template" Value="{StaticResource ThermometerBlock}"/>
      <Setter Property="Color" Value="Red"/>
      <Style.Triggers>
        <DataTrigger Value="True">
          <DataTrigger.Binding>
            <MultiBinding Converter="{StaticResource GreaterThanConverter}">
              <Binding Path="Position1"/>
              <Binding Source="200.0"/>
            </MultiBinding>
          </DataTrigger.Binding>
          <Setter Property="Color" Value="Blue"/>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </gauge:Pointer.Style>
</gauge:Pointer>

Это работает, но я не доволен этим.Пользователь элемента управления Guage не может знать эту деталь о внутреннем имполентации.

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

Я подумал, что мог бы выбрать шаблон элемента управления с помощью конвертера (преобразование моего свойства DisplayStyle в ControlTemplate), но я могу видеть, где я мог бы применить конвертер.

Моя единственная другая идея - избавиться от свойства DisplayStyle и вместо этого определить несколько классов указателей, которые являются производными от общего базового класса указателей.Затем я могу определить отдельные шаблоны элементов управления для каждого класса производных указателей.

У меня есть несколько вопросов.

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

Во-вторых, есть ли способ выбрать шаблон элемента управления для указателя, не требуя определения стиля?

Если нет, то подходит ли идея с производными классами?

...