Silverlight и WPF: VisualStateManager в ControlTemplate не работает - PullRequest
0 голосов
/ 01 июня 2011

Итак, всем привет.

Я создал две тестовые программы для создания собственного элемента управления. Один в Silverlight, другой в WPF. Я создал своего рода RangeSlider. Этот слайдер имеет две ориентации: горизонтальную и вертикальную. Сначала я использовал два разных метода для создания RangeSlider. В WPF я использовал триггеры, в Silverlight (вы знаете, триггеров нет) я изменил видимость горизонтального и вертикального шаблона в CodeBehind. Это выполняется.

Сейчас: Я пытаюсь использовать одну технику для Silverlight и WPF. Поэтому я использую VisualStateManager.

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

...
<ControlTemplate>
  <Grid x:Name="PART_Content">
    <!-- VSM: See following code sequence -->
    <Grid x:Name="PART_HorizontalTemplate">
      <Slider x:Name="PART_HorizontalSliderLeft"
              Template="{StaticResource HorizontalSliderTemplate}"
              Orientation="{TemplateBinding Orientation}" />
      ...
    </Grid>
    <Grid x:Name="PART_VerticalTemplate">
      ...
    </Grid>
  </Grid>
</ControlTemplate>

Дополнительно имеется VSM для переключения между горизонтальным и вертикальным видом:

<VisualStateManager.VisualStateGroups>
  <VisualStateGroup>
    <VisualState x:Name="Vertical">
      <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_HorizontalTemplate"
                                       Storyboard.TargetProperty="Visibility">
          <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" KeyTime="0"/>
        </ObjectAnimationUsingKeyFrames>
      </Storyboard>
    </VisualState>
    <VisualState x:Name="Horizontal" />
  </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Это все еще работает.

Как вы видите в кодовой последовательности, визуал Slider определяется шаблоном, здесь HorizontalSliderTemplate (я снова сокращаю код):

<ControlTemplate x:Key="HorizontalSliderTemplate" TargetType="{x:Type Slider}">
  <Border x:Name="Border" ...>
    <!-- VSM here. Like above. -->
    <Grid x:Name="Grid">
      <Rectangle x:Name="PART_SelectionRange"/>
      <Track x:Name="PART_Track">
        ...
      </Track>
    </Grid>
  </Border>
</ControlTemplate>

На самом деле существует также шаблон VerticalSliderTemplate. Но я хочу объединить оба ControlTemplate в один шаблон и использовать VSM. Вот мы и подошли к моей проблеме:

Я не запускаю VSM во «внутреннем» шаблоне ControlTemplate. Это почти тот же код, что и в работающей VSM-части, только TargetName изменяется. Я не знаю, как отлаживать то, что работает на GoToState, но я полагаю, что VSM в шаблоне никогда не будет найден и оттуда никогда не выполнится.

Я могу представить, что пропущена лишь небольшая деталь, но я «не вижу дерева для деревьев». Может быть, есть важная вещь, которую я не знаю о шаблонах или о VSM, и я не в курсе. Или мне нужно запускать «внутренний» VSM извне, или есть возможность доступа к элементам из «внешнего VSM»? Или нет доступа к VSM во «внутренних» шаблонах?

Я надеюсь, что смогу объяснить свою проблему достаточно хорошо, и есть кто-то, кто знает решение или, может быть, ключевое слово, которое я могу найти. Просто ввод ключевых слов VSM, ControlTemplate, Storyboard и т. Д. В Google не помогает.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 03 июня 2011

Итак, у меня есть решение. Во «внутреннем» шаблоне я добавил элемент, который хочу переключить DataTrigger. Этот DataTrigger связан с видимостью PART_HorizontTemplate и содержит раскадровку, которая выполняет необходимое действие.

Может быть, это не совсем то решение, которое я искал, потому что оно сильно растягивает код и делает его более сложным. Но - и это самое главное - он работает хорошо.

0 голосов
/ 01 июня 2011

Я не думаю, что вы можете иметь несколько VSM внутри одного ControlTemplate.

Почему бы вам не использовать один VSM для переключения обоих.

<ControlTemplate>
  <Grid x:Name="PART_Content">
    <Grid x:Name="PART_HorizontalTemplate">
      ...
    </Grid>
    <Grid x:Name="PART_VerticalTemplate">
      ...
    </Grid>
<VisualStateManager.VisualStateGroups>
  <VisualStateGroup>
    <VisualState x:Name="Vertical">
      <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_HorizontalTemplate"
                                       Storyboard.TargetProperty="Visibility">
          <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" KeyTime="0"/>
        </ObjectAnimationUsingKeyFrames>
      </Storyboard>
    </VisualState>
    <VisualState x:Name="Horizontal">
<Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_VerticalTemplate"
                                       Storyboard.TargetProperty="Visibility">
          <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" KeyTime="0"/>
        </ObjectAnimationUsingKeyFrames>
      </Storyboard>
    </VisualState>
  </VisualStateGroup>
</VisualStateManager.VisualStateGroups>
  </Grid>
</ControlTemplate>
...