Question

If I define VisualStates from within a control template, is it possible to change the properties of the templated control itself from a storyboard? Here's a quick example:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Window.Template>
    <ControlTemplate TargetType="{x:Type Window}">
      <Grid>
        <VisualStateManager.VisualStateGroups>
          <VisualStateGroup x:Name="WindowStyleStates"
                            x:Uid="WindowStyleStates">
            <Storyboard x:Uid="Storyboard_1">
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="?????"
                                             Storyboard.TargetProperty="ResizeMode">
                <DiscreteObjectKeyFrame KeyTime="0"
                                        Value="CanResizeWithGrip" />
              </ObjectAnimationUsingKeyFrames>
            </Storyboard>
          </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
      </Grid>
    </ControlTemplate>
  </Window.Template>
</Window>

The problem is that the storyboards only have access to the objects defined within the grid. If I'm defining a controltemplate for a Window, why can't I change values on the Window I'm templating.

Was it helpful?

Solution

You don't need the ControlTemplate to access the VisualStateManager. This should do the trick, although I didn't try it.

<Window x:Name="YourWindow" ...>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="WindowStyleStates" x:Uid="WindowStyleStates">
            <Storyboard x:Uid="Storyboard_1">
                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="YourWindow"
                                               Storyboard.TargetProperty="ResizeMode">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="CanResizeWithGrip"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Window>

But there seems to be an issue with VisualStateManager.GoToState(...) in code behind, at least for .Net 3.5. But there is a workaround. I don't know if this is important for you.

To answer the question in your title: I think you missunderstood a bit the concept behind the templating of a control. A small example...

<!-- A simple button with round corners -->
<Button>
  <Button.Template>
    <ControlTemplate>
      <Border x:Name="ButtonBorder"
              CornerRadius="10"
              BorderBrush="{TemplateBinding BorderBrush}"
              BorderThickness="{TemplateBinding BorderThickness}">
        <Grid>
          <ContentPresenter x:Name="ButtonContent"
                            Content="{TemplateBinding Content}" />
          <Border x:Name="ButtonBackground"
                  Background="{TemplateBinding Background}"
                  BorderBrush="{x:Null}"
                  BorderThickness="0" />
        </Grid>
      </Border>
    </ControlTemplate>
  </Button.Template>
</Button>

As you can see, the template gives the Button a new appearance. Additionally the visual behavior is also overridden. Well in this case there is no visual behavior, although the button will work as expected.
To define the visual behavior you can use the VisualStateManager and the predefined states or your custom states. But you can only modify the elements in the template which is reasonable since you want to reimplement the look and feel of the button. Therefore you would add a VisualStateManager to ButtonBorder.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top