4

我在 MainWindow 的 LayoutRoot Grid 中定义了两个视觉状态,如下所示:

<Grid x:Name="LayoutRoot" Background="#FF434343" ShowGridLines="True">

<Grid.RowDefinitions>
    <RowDefinition Height="100"/>
    <RowDefinition Height="*"/>
</Grid.RowDefinitions>


    <VisualStateManager.CustomVisualStateManager>
        <ic:ExtendedVisualStateManager/>
    </VisualStateManager.CustomVisualStateManager>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateLogin">
            <VisualStateGroup.Transitions>
                <VisualTransition GeneratedDuration="00:00:00.6000000"/>
            </VisualStateGroup.Transitions>
            <VisualState x:Name="LoggedOn">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="{x:Null}" Storyboard.TargetProperty="(Window.WindowStyle)">
                        <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static WindowStyle.None}"/>
                    </ObjectAnimationUsingKeyFrames>
                    <BooleanAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="{x:Null}" Storyboard.TargetProperty="(Window.AllowsTransparency)">
                        <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True"/>
                    </BooleanAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="LoggedOff">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="brdContent" Storyboard.TargetProperty="(UIElement.Opacity)">
                        <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.1"/>
                    </DoubleAnimationUsingKeyFrames>
                    <BooleanAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="brdContent" Storyboard.TargetProperty="(UIElement.IsEnabled)">
                        <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"/>
                    </BooleanAnimationUsingKeyFrames>
                    <BooleanAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ucTabButtons" Storyboard.TargetProperty="(UIElement.IsEnabled)">
                        <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"/>
                    </BooleanAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ucTabButtons" Storyboard.TargetProperty="(UIElement.Opacity)">
                        <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.4"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

考虑到 MainWindow 代码隐藏,它可以很好地从一种状态切换到另一种状态,如下所示:

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        //ExtendedVisualStateManager.GoToElementState(this.LayoutRoot as FrameworkElement, "LoggedOff", false);        
    }

但是现在,我需要能够从 MainWindow 内的用户控件切换状态......

我试过了:

    private void btnOk_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        MainWindow parent = new MainWindow();
        Grid root = new Grid();
        root = (Grid)parent.FindName("LayoutRoot");
        ExtendedVisualStateManager.GoToElementState(root as FrameworkElement, "LoggedOn", true);
    }

它给了我以下例外:

System.NullReferenceException 未处理 Message="对象引用未设置为对象的实例。" 来源="WPFToolkit"

有人知道如何从用户控件切换状态吗?

谢谢你,

乔西

4

2 回答 2

1

我建议定义一个用于在状态之间切换的接口。表单可以实现接口,它可以显式地将接口传递给控件,​​或者控件可以查询其父级以查看接口是否已实现。这样,用户控件就不会与其容器紧密耦合,而只会与其期望容器提供的行为紧密耦合。

附带说明一下,让用户控件修改其容器的状态是一种不寻常的设计。您可能需要考虑是否有另一种方法来构建需求。

一个可能的接口:

public interface IStateChanger
{
    void GoToElementState(string state);    
}

你可以让你的 MainWindow 实现这个接口:

    void IStateChanger.GoToElementState(string state)
    {
        ExtendedVisualStateManager.GoToElementState(this.LayoutRoot as FrameworkElement, state, false);        
    }

然后你的控制,按照你的例子,可以做到这一点:

    private void btnOk_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        MainWindow parent = new MainWindow();
        if (parent is IStateChanger)
            ((IStateChanger)parent).GoToElementState("LoggedOn");
    }
于 2010-03-07T13:37:53.670 回答
0

在您的用户控件上创建一个父级可以订阅的公共事件;然后可以将该事件用作状态转换的触发器。

于 2010-03-08T02:26:49.407 回答