在WPF中设置初始的视觉状态

6
在WPF中使用VisualStateManager时,可能需要在控件初始化时转换到一个VisualState。据我所知,在Xaml中没有声明初始状态的方法,因此你只能在初始化后的代码中转换到所需的状态,这种选择往往是有限的。
使用代码不总是理想的,如果你正在使用绑定来控制VisualStates,则不一定可行。
那么问题来了:如何在不使用代码后台的情况下设置WPF中的初始VisualState呢?

我不确定我是否理解正确,但您是否试图在不使用代码后台的情况下转换到启动状态?如果是这样,您可以使用GoToStateAction http://msdn.microsoft.com/en-us/library/ff723953(v=expression.40).aspx,并将事件触发器设置为“Loaded”,然后选择相应的状态。这是您想要的吗? - Viv
这是我正在尝试做的事情,但为了增加一些复杂性,初始状态取决于一个绑定属性。你给出的解决方案使用了Blend,而我没有使用过也不熟悉它。如果不必要,我真的不想使用它。不过还是谢谢你的建议。 - Richard E
2个回答

3

过长,不适合做评论。

数据绑定应该不会有什么影响。如果从代码后台正常工作,那么从xaml也一定能够正常工作,除非绑定上有一些奇怪的问题。

所有Blend的操作都可以被视为XAML助手工具。最终结果是你得到了Blend为你创建的一些XAML代码。如果你不想使用Blend,只需在VS中自己添加XAML代码即可。

对于这个问题,GoToStateAction可以像下面这样编写:

<Window ...
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        ...>
...
<Button x:Name="button"
        Style="{DynamicResource ButtonStyle1}">
  <i:Interaction.Triggers>
    <i:EventTrigger>
      <ei:GoToStateAction StateName="YourState"
                          TargetObject="{Binding ElementName=button}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

您还需要在项目中添加相应的引用。

顺便提一下,尝试使用 Blend 工具。它在特定场合有其优势。您可能不会完全取代直接编写 XAML,但它可以作为一个很好的辅助工具。我认为完全忽略它是没有意义的,除非被迫这样做。


谢谢。我已经在VS中引用了Expression程序集,我认为这是一个不错的折衷方案。 - Richard E

0

在XAML的初始化过程中,您可以直接将任何控件与可视状态绑定。您需要创建一个依赖属性来更改状态。希望下面的代码能够帮助您。

<Grid  model:StateManager.VisualStateProperty="{Binding VisibilityState}" >
        <Grid.RowDefinitions>
            <RowDefinition Height="48" />
            <RowDefinition Height="97" />
            <RowDefinition Height="65" />
            <RowDefinition Height="297" />
        </Grid.RowDefinitions>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisibleStateGroup">
                <VisualState x:Name="VisibleState">
                    <Storyboard Duration="0:0:0">
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="myGrid" Storyboard.TargetProperty="(UIElement.Visibility)">
                            <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Visible</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>

                    </Storyboard>
                </VisualState>
                <VisualState x:Name="CollapsedState">
                    <Storyboard Duration="0:0:0">
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="myGrid" Storyboard.TargetProperty="(UIElement.Visibility)">
                            <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Collapsed</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Grid Name="myGrid" Grid.Row="0" Grid.ColumnSpan="2" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="383*" />
                <ColumnDefinition Width="383*" />
            </Grid.ColumnDefinitions>
            <StackPanel Grid.Column="0" Orientation="Horizontal" Margin="0,0,15,0" HorizontalAlignment="Right" VerticalAlignment="Center">


                <Label Content="MyName"></Label>
            </StackPanel>
        </Grid>

用于可视状态更改的依赖属性代码

public class StateManager : DependencyObject
    {
        public static string GetVisualStateProperty(DependencyObject obj)
        {
            return (string)obj.GetValue(VisualStatePropertyProperty);
        }

        public static void SetVisualStateProperty(DependencyObject obj, string value)
        {
            obj.SetValue(VisualStatePropertyProperty, value);
        }

        public static readonly DependencyProperty VisualStatePropertyProperty =
          DependencyProperty.RegisterAttached(
          "VisualStateProperty",
          typeof(string),
          typeof(StateManager),
          new PropertyMetadata((s, e) =>
          {
              var propertyName = (string)e.NewValue;
              var ctrl = s as Grid;  
              if (ctrl == null)
                  throw new InvalidOperationException("This attached property only supports types derived from FrameworkElement.");
              var transitionWorked = System.Windows.VisualStateManager.GoToElementState(ctrl, (string)e.NewValue, true);
              //MessageBox.Show(transitionWorked.ToString());
          }));
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接