0
votes

So, hello everybody.

I've made two test programs for creating a own control. One in Silverlight, one in WPF. I created a kind of RangeSlider. This Slider has of course two Orientations, Horizontal and Vertical. First I used two different techniques to create my RangeSlider. In WPF I used Triggers, in Silverlight (u know there arent Triggers) I changed the Visibility of the Horizontal and Vertical Template in CodeBehind.This runs.

Now: I'm trying to use one technique for both, Silverlight and WPF. Therefore I use VisualStateManager.

I've a Template defining two Sliders (one for left value, the other for right value). Simplified on the important values it looks like that:

...
<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>

Additionally there is the VSM to switch between Horizontal and Vertical look:

<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>

This still runs.

As you see in the code sequence, the visual of Slider is defined by a Template, here HorizontalSliderTemplate (I reduce code again):

<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>

Actually there is also a VerticalSliderTemplate. But I want to combine both ControlTemplate in one Template and use VSM. Here we come to my problem:

I do not get running the VSM in the 'inner' ControlTemplate. It's nearly the same code as the running VSM-Part, just the TargetName is changed. I do not know how to debug what's running on GoToState, but I believe the VSM in the template is never found and from there never execute.

I can imagine that there's just a little detail missing, but I 'cant see the wood for the trees'. Maybe there is an important thing what I do not know about Templates or about VSM, and I'm off the track. Or do I have to trigger the 'inner' VSM from outside, or there's a possibility to access onto Elements from 'outside VSM'? Or is there no access on VSM in 'inner' Templates?

I hope I could explain my problem good enough and there is someone, who knows a solution or maybe a keyword what I can look for. Just entering keywords VSM, ControlTemplate, Storyboard, etc. in google gives no helping hand.

Thanks in advance.

2

2 Answers

0
votes

I don't think you can have multiple VSMs inside one ControlTemplate.

Why don't you just use one VSM to toggle both.

<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>
0
votes

So, I got a solution on it. In the 'inner' template I added to the element I want to toggle a DataTrigger. This DataTrigger is bound to the PART_HorizontalTemplate Visibility and contains a Storyboard that do the action I need.

Maybe it's not really the kind of solution I was looking for, because it stretches the code a lot and makes it therefore looking more complex. But - and thats most important - it runs well.