【问题标题】:Silverlight: Switching VisualStates of CustomVisualStateManager in code-behindSilverlight:在代码隐藏中切换 CustomVisualStateManager 的 VisualStates
【发布时间】:2009-11-26 18:10:34
【问题描述】:

我一直在尝试处理以下问题: 在 Expression Blend 3 中为不同的视觉状态创建自定义动画时,它会更改网格上多个元素的大小/不透明度,它会在网格本身而不是控件样式中创建视觉状态组,并将其定义为 CustomVisualStateManager。

<Grid x:Name="LayoutRoot" Background="White" Height="500" HorizontalAlignment="Left" VerticalAlignment="Top" Width="500">       
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MyVisualStateGroup">
    <VisualStateGroup.Transitions>
    <VisualTransition GeneratedDuration="00:00:00.3000000">
        <VisualTransition.GeneratedEasingFunction>
            <CircleEase EasingMode="EaseIn"/>
    </VisualTransition.GeneratedEasingFunction>
    </VisualTransition>
    </VisualStateGroup.Transitions>
    <VisualState x:Name="State1"/>
    <VisualState x:Name="State2">
        <Storyboard>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="myBox" Storyboard.TargetProperty="(FrameworkElement.Height)">
            <EasingDoubleKeyFrame KeyTime="00:00:00" Value="360"/>
<!-- omitting other storyboard animations here for clarity -->                      
                </Storyboard>
    </VisualState>
    </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
    <ic:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>

<!-- omitting other grid elements here for clarity -->

</Grid>

我没问题,但问题是,当我尝试时,我无法在代码隐藏中切换状态

VisualStateManager.GoToState(this, "State1", true);

什么都没有发生,因为控件本身没有定义这些视觉状态,如

所示
VisualStateManager.GetVisualStateGroups(this);

如果我尝试

VisualStateManager.GetVisualStateGroups(LayoutRoot);

它准确地显示了我的需要。但是我不能将 LayoutRoot 传递给 VisualStateManager,因为它需要一个 Control 类型的参数,而 Grid 不是。 我的问题是 - 我如何在代码隐藏中访问/更改此 CustomVisualStateManager 的状态?

【问题讨论】:

    标签: c# silverlight silverlight-3.0 expression-blend visualstatemanager


    【解决方案1】:

    当您启用 FluidLayout 时,CustomVisualStateManager 就在那里。除非您的项目中涉及布局变形(即您尝试使用状态从一种布局平滑地动画到另一种布局),否则您可以将其关闭。自定义 VSM 的存在不会对 VSM 的使用产生任何影响。

    视觉状态标记总是在顶级容器内,所以这是完全正常的。顺便说一句,这可能只是您的示例中的一个错字,但您显示的代码实际上试图设置一个没有任何内容的状态,因此这可能不是预期的结果。

    否则,在 UserControl 上调用 VisualStateManager.GoToState 应该可以工作。这是我刚刚制作的一个示例:

    这是一个简单的 Silverlight 示例应用程序,有一个主页和一个我添加到主页的用户控件。主页真的很简单:

    <UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SLStateTest"
    x:Class="SLStateTest.MainPage"
    Width="640" Height="480">
    
    <Grid x:Name="LayoutRoot" Background="White">
        <local:UserControl1 x:Name="TestControl" Height="100" HorizontalAlignment="Left" Margin="24,32,0,0" VerticalAlignment="Top" Width="100"/>
        <Button Height="40" HorizontalAlignment="Left" Margin="192,32,0,0" VerticalAlignment="Top" Width="104" Content="State 1" Click="OnClick"/>
        <Button Height="40" HorizontalAlignment="Left" Margin="192,76,0,0" VerticalAlignment="Top" Width="104" Content="State 2" Click="OnClickState2"/>
    </Grid></UserControl>
    

    我的用户控件有一个实例,还有两个按钮。我们稍后会看看按钮的作用。先来看一下UserControl(UserControl1):

    <UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
    x:Class="SLStateTest.UserControl1"
    d:DesignWidth="280" d:DesignHeight="264">
    
    <Grid x:Name="LayoutRoot" Background="#FF6FFE22">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="Test" ic:ExtendedVisualStateManager.UseFluidLayout="True">
                <VisualState x:Name="State1">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                            <EasingColorKeyFrame KeyTime="00:00:00" Value="#FF003AFF"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="State2">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                            <EasingColorKeyFrame KeyTime="00:00:00" Value="#FFFF0202"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <VisualStateManager.CustomVisualStateManager>
            <ic:ExtendedVisualStateManager/>
        </VisualStateManager.CustomVisualStateManager>
    </Grid></UserControl>
    

    如您所见,在一个视觉状态组中定义了两种视觉状态,它们只是在用户控件的布局根上设置了一种颜色。

    主页上的两个按钮连接到如下所示的事件处理程序:

    private void OnClick(object sender, System.Windows.RoutedEventArgs e)
        {
            // TODO: Add event handler implementation here.
            VisualStateManager.GoToState(TestControl, "State1", true);
        }
    
        private void OnClickState2(object sender, System.Windows.RoutedEventArgs e)
        {
            // TODO: Add event handler implementation here.
            TestControl.SetState();
        }
    

    第一个只是在页面上的 UserControl 上调用 VisualStateManager.GoToState。第二个调用在用户控件旁边执行相同操作的函数。我只是使用这两种方法来表明这两个选项都可用 - 您可以从 UC 外部或内部调用 VSM.GoToState。用户控件的 SetState() 方法如下所示:

    public void SetState()
        {
            VisualStateManager.GoToState(this, "State2", true);
        }
    

    当您运行应用程序时,用户控件将首先显示为其基本状态,即绿色。当您按下 State 1 按钮时,它会转到 State1,通过从外部调用 VSM.GoToState() 将 UC 设置为蓝色。当您按下状态 2 按钮时,它会通过从内部调用 VSM 切换为红色。

    从您发布的 sn-ps 中,除了我在开头提到的一个问题之外,我看不出出了什么问题。不过,我的小样本可能会帮助您了解您的情况有何不同。

    希望对你有帮助……

    【讨论】:

    • 在我的示例中,State1 的情节提要是空的,是的,但这不是最初的问题,因为在主程序中,这两个状态都包含转换。嗯,问题是要在网格“LayoutRoot”本身上应用一些转换,并且它不能传递给 VisualStateManager.GotoState,因为它不是控件。最后,我没有将 VSM 用于动画,而是将它们移动到自定义故事板中,我可以从代码隐藏中触发。感谢您的回答,我会将其标记为已接受。
    猜你喜欢
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 2014-11-16
    • 2012-08-29
    相关资源
    最近更新 更多