访问样式的按钮故事板

时间:2011-03-12 09:18:24

标签: wpf button styles storyboard visualstates

我的问题是我有一个Button我希望访问Storyboard,这是指定样式的一部分。

<Button x:Name="pictureFolderButton" Content="Pictures" Style="{StaticResource ImageTileButtonStyle}" Click="pictureFolderButton_Click" />

风格非常全面,所以我只发布一部分内容:

<Style x:Key="ImageTileButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="OnLoaded1"/>
                        </ControlTemplate.Resources>
                        <Grid>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal"/>
                                    ...
                                </VisualStateGroup>
                                <VisualStateGroup x:Name="AnimationStates">
                                    <VisualStateGroup.Transitions>
                                        <VisualTransition GeneratedDuration="0:0:1">
                                            <VisualTransition.GeneratedEasingFunction>
                                                <CircleEase EasingMode="EaseOut"/>
                                            </VisualTransition.GeneratedEasingFunction>
                                        </VisualTransition>
                                    </VisualStateGroup.Transitions>

                                    <VisualState x:Name="ExpandedFull">
                                        <Storyboard x:Name="expandStoryBoard" >
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="border1">

                                                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="130"/>
                                                <EasingDoubleKeyFrame KeyTime="0:0:3" Value="130"/>
                                                <EasingDoubleKeyFrame KeyTime="0:0:4" Value="47"/>
                                                <EasingDoubleKeyFrame KeyTime="0:0:8" Value="47"/>
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>

                            <ContentPresenter RecognizesAccessKey="True" VerticalAlignment="Stretch" Margin="0,47,0,0" />

                        </Grid>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

我只想在“ExpandedFull”动画结束时收到通知。因此,我认为我必须以编程方式获取“expandStoryBoard”并添加 Completed 事件处理程序。

我唯一能做的就是在运行时访问按钮的样式:

Style style = pictureFolderButton.FindResource("ImageTileButtonStyle") as Style;

我该怎么办? 非常感谢你!

3 个答案:

答案 0 :(得分:2)

尝试使用StoryBoard名称“OnLoaded1”:

 <Button Height="75" Width="120" Style="{StaticResource ImageTileButtonStyle}" Click="Button_Click" >Hello</Button>


  private void Button_Click(object sender, RoutedEventArgs e)
    {
        Button btn=(Button)sender;

        Storyboard stb = btn.TryFindResource("OnLoaded1") as Storyboard;

    }

答案 1 :(得分:2)

理论上你应该能够按下按钮的视觉和逻辑树来进入故事板,但是如果你在模板“grid”中命名Grid,那就相当繁琐了。以下可能工作:

Grid grid = pictureFolderButton.FindName("grid") as Grid;
IList groups = VisualStateManager.GetVisualStateGroups(grid);
VisualStateGroup targetGroup = null;
foreach (var group in groups)
{
    if (group is VisualStateGroup && (group as VisualStateGroup).Name == "AnimationStates")
    {
        targetGroup = group as VisualStateGroup;
        break;
    }
}
if (targetGroup != null)
{
    IList states = targetGroup.States;
    VisualState targetState = null;
    foreach (var state in states)
    {
        if (state is VisualState && (state as VisualState).Name == "ExpandedFull")
        {
            targetState = state as VisualState;
            break;
        }
    }
    if (targetState != null)
    {
        targetState.Storyboard.Completed += new EventHandler(Expansion_Completed);
    }
    else throw new Exception("VisualState not found.");
}
else throw new Exception("VisualStateGroup not found.");

另一种想到的方法是将故事板提取到资源中,但我不确定这是否会产生任何副作用,即:

<ControlTemplate.Resources>
    ...
    <Storyboard x:Key="expandStoryBoard" x:Name="expandStoryBoard">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="border1">
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="130"/>
            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="130"/>
            <EasingDoubleKeyFrame KeyTime="0:0:4" Value="47"/>
            <EasingDoubleKeyFrame KeyTime="0:0:8" Value="47"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</ControlTemplate.Resources>
...
<VisualState x:Name="ExpandedFull" Storyboard="{StaticResource expandStoryBoard}"/>

然后您应该可以使用按钮上的FindResource来获取故事板。

希望其中一些可行或至少有所帮助。

答案 2 :(得分:0)

如果将Storyboard添加到资源,则可以在XAML文件中为Timeline.Completed事件设置事件处理程序,并在相应的类中实现处理程序。

在控件的“资源”部分中定义Storyboard,如下所示:

<UserControl.Resources>
  <Storyboard x:Key="expandStoryBoard" Completed="OnExpandCompleted"> ... </Storyboard>
  ...
</UserControl.Resources>

Storyboard引用为静态资源:

<VisualState x:Name="ExpandedFull" Storyboard="{StaticResource expandStoryBoard}" />

在相应的类中实现Completed事件处理程序:

void OnExpandCompleted(object sender, EventArgs e)
{
   ...
}