WPF 中的视觉状态管理器不适合我

发布于 2024-08-28 15:13:33 字数 6713 浏览 8 评论 0原文

在 wpf 项目中,我

<Window
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="WpfApplication1.MainWindow"
xmlns:vsm="clr-namespace:System.Windows;assembly=WPFToolkit"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<vsm:VisualStateManager.VisualStateGroups>
    <vsm:VisualStateGroup x:Name="VisualStateGroup">
        <vsm:VisualState x:Name="Loading">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="control" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Visible}"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="button" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Collapsed}"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="button1" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Visible}"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </vsm:VisualState>
        <VisualState x:Name="Normal">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="control" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Collapsed}"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
    </vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Grid x:Name="LayoutRoot">
    <Grid.Resources>
        <ControlTemplate x:Key="loadingAnimation">
            <Image x:Name="content" Opacity="1">
                <Image.Source>
                    <DrawingImage>
                        <DrawingImage.Drawing>
                            <DrawingGroup>
                                <GeometryDrawing Brush="Transparent">
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry Rect="0,0,1,1"/>
                                    </GeometryDrawing.Geometry>
                                </GeometryDrawing>
                                <DrawingGroup>
                                    <DrawingGroup.Transform>
                                        <RotateTransform x:Name="angle" Angle="0" CenterX="0.5" CenterY="0.5"/>
                                    </DrawingGroup.Transform>
                                    <GeometryDrawing Geometry="M0.9,0.5 A0.4,0.4,90,1,1,0.5,0.1">
                                        <GeometryDrawing.Pen>
                                            <Pen Brush="Green" Thickness="0.1"/>
                                        </GeometryDrawing.Pen>
                                    </GeometryDrawing>
                                    <GeometryDrawing Brush="Green" Geometry="M0.5,0 L0.7,0.1 L0.5,0.2"/>
                                </DrawingGroup>
                            </DrawingGroup>
                        </DrawingImage.Drawing>
                    </DrawingImage>
                </Image.Source>
            </Image>
            <ControlTemplate.Triggers>
                <Trigger Property="Visibility" Value="Visible">
                    <Trigger.EnterActions>
                        <BeginStoryboard x:Name="animation">
                            <Storyboard>
                                <DoubleAnimation From="0" To="359" Duration="0:0:1.5" RepeatBehavior="Forever"
                                    Storyboard.TargetName="angle" Storyboard.TargetProperty="Angle"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <StopStoryboard BeginStoryboardName="animation"/>
                    </Trigger.ExitActions>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Grid.Resources>
    <Grid.ColumnDefinitions>
        <ColumnDefinition MinWidth="76.128" Width="Auto"/>
        <ColumnDefinition MinWidth="547.872" Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="0.05*"/>
        <RowDefinition Height="0.95*"/>
    </Grid.RowDefinitions>
    <Button x:Name="button" Margin="0,0,1,0.04" Width="100" Content="Load" d:LayoutOverrides="Height" Click="Button1_Click"/>
    <Button x:Name="button1" HorizontalAlignment="Left" Margin="0,0,0,0.04" Width="100" Content="Stop" Grid.Column="1" d:LayoutOverrides="Height" Click="Button2_Click" Visibility="Collapsed"/>
    <Control x:Name="control" Margin="10" Height="100" Grid.Row="1" Grid.ColumnSpan="2" Width="100" Template="{DynamicResource loadingAnimation}" Visibility="Collapsed"/>
</Grid>
</Window>

在窗口后面有此 XAML 代码和以下代码

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();

        }


        private void Button1_Click(object sender, System.Windows.RoutedEventArgs e)
        {
                VisualStateManager.GoToState(this, "Loading", true);
        }

        private void Button2_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            VisualStateManager.GoToState(this, "Normal", true);
        }
    }

但是,当我单击第一个按钮 (button1) 时,不会触发状态更改。 我做错了什么?

提前致谢

In a wpf project I have this XAML code

<Window
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="WpfApplication1.MainWindow"
xmlns:vsm="clr-namespace:System.Windows;assembly=WPFToolkit"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<vsm:VisualStateManager.VisualStateGroups>
    <vsm:VisualStateGroup x:Name="VisualStateGroup">
        <vsm:VisualState x:Name="Loading">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="control" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Visible}"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="button" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Collapsed}"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="button1" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Visible}"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </vsm:VisualState>
        <VisualState x:Name="Normal">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="control" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Collapsed}"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
    </vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Grid x:Name="LayoutRoot">
    <Grid.Resources>
        <ControlTemplate x:Key="loadingAnimation">
            <Image x:Name="content" Opacity="1">
                <Image.Source>
                    <DrawingImage>
                        <DrawingImage.Drawing>
                            <DrawingGroup>
                                <GeometryDrawing Brush="Transparent">
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry Rect="0,0,1,1"/>
                                    </GeometryDrawing.Geometry>
                                </GeometryDrawing>
                                <DrawingGroup>
                                    <DrawingGroup.Transform>
                                        <RotateTransform x:Name="angle" Angle="0" CenterX="0.5" CenterY="0.5"/>
                                    </DrawingGroup.Transform>
                                    <GeometryDrawing Geometry="M0.9,0.5 A0.4,0.4,90,1,1,0.5,0.1">
                                        <GeometryDrawing.Pen>
                                            <Pen Brush="Green" Thickness="0.1"/>
                                        </GeometryDrawing.Pen>
                                    </GeometryDrawing>
                                    <GeometryDrawing Brush="Green" Geometry="M0.5,0 L0.7,0.1 L0.5,0.2"/>
                                </DrawingGroup>
                            </DrawingGroup>
                        </DrawingImage.Drawing>
                    </DrawingImage>
                </Image.Source>
            </Image>
            <ControlTemplate.Triggers>
                <Trigger Property="Visibility" Value="Visible">
                    <Trigger.EnterActions>
                        <BeginStoryboard x:Name="animation">
                            <Storyboard>
                                <DoubleAnimation From="0" To="359" Duration="0:0:1.5" RepeatBehavior="Forever"
                                    Storyboard.TargetName="angle" Storyboard.TargetProperty="Angle"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <StopStoryboard BeginStoryboardName="animation"/>
                    </Trigger.ExitActions>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Grid.Resources>
    <Grid.ColumnDefinitions>
        <ColumnDefinition MinWidth="76.128" Width="Auto"/>
        <ColumnDefinition MinWidth="547.872" Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="0.05*"/>
        <RowDefinition Height="0.95*"/>
    </Grid.RowDefinitions>
    <Button x:Name="button" Margin="0,0,1,0.04" Width="100" Content="Load" d:LayoutOverrides="Height" Click="Button1_Click"/>
    <Button x:Name="button1" HorizontalAlignment="Left" Margin="0,0,0,0.04" Width="100" Content="Stop" Grid.Column="1" d:LayoutOverrides="Height" Click="Button2_Click" Visibility="Collapsed"/>
    <Control x:Name="control" Margin="10" Height="100" Grid.Row="1" Grid.ColumnSpan="2" Width="100" Template="{DynamicResource loadingAnimation}" Visibility="Collapsed"/>
</Grid>
</Window>

and the following code behind on the window

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();

        }


        private void Button1_Click(object sender, System.Windows.RoutedEventArgs e)
        {
                VisualStateManager.GoToState(this, "Loading", true);
        }

        private void Button2_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            VisualStateManager.GoToState(this, "Normal", true);
        }
    }

However, when I click the first button (button1) the state change is not being triggered.
What am I doing wrong?

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

意犹 2024-09-04 15:13:34

事实上,它是 .net 3.5 上设计的。 这个人有一个解决方法。

In fact, it is by design on .net 3.5. This guy has a workaround.

不如归去 2024-09-04 15:13:34

我尝试了你的代码,但在设计器(VS2008 SP1)中出现错误:

值不能为空。
参数名称:值

每当我编辑故事板代码时, 。重新加载 xaml 可以暂时“修复”该问题。代码仍然可以构建并运行,但我怀疑此错误的原因可能与您的问题有关。

DiscreteObjectKeyFrame 的定义对我来说有点奇怪。我过去看到的唯一方法是如 此页面是这样完成的:

<vsm:VisualState x:Name="Focused">
  <Storyboard>
    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement"
                          Storyboard.TargetProperty="Visibility" Duration="0">
      <DiscreteObjectKeyFrame KeyTime="0">
        <DiscreteObjectKeyFrame.Value>
          <Visibility>Visible</Visibility>
        </DiscreteObjectKeyFrame.Value>
      </DiscreteObjectKeyFrame>
    </ObjectAnimationUsingKeyFrames>
  </Storyboard>
</vsm:VisualState>

但是,我用你的代码尝试过,但仍然无法让它工作,所以我即使是这样
一个问题并不是问题的全部。

I tried your code and got an error in the designer (VS2008 SP1):

Value cannot be null.
Parameter name: value

whenever I edit the storyboard code. Reloading the xaml "fixes" the problem temporarily. The code still builds and runs, but I suspect that the cause of this error might have a bearing on your problem.

The definition of the DiscreteObjectKeyFrame looks a little off to me. The only way I've seen it done in the past is as described on this page where it's done like this:

<vsm:VisualState x:Name="Focused">
  <Storyboard>
    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement"
                          Storyboard.TargetProperty="Visibility" Duration="0">
      <DiscreteObjectKeyFrame KeyTime="0">
        <DiscreteObjectKeyFrame.Value>
          <Visibility>Visible</Visibility>
        </DiscreteObjectKeyFrame.Value>
      </DiscreteObjectKeyFrame>
    </ObjectAnimationUsingKeyFrames>
  </Storyboard>
</vsm:VisualState>

However, I tried that with your code and still couldn't get it to work, so I even if that is
a problem it's not the whole problem.

你不是我要的菜∠ 2024-09-04 15:13:34

创建一个附加属性来更改视觉状态。这对你有用

  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);
                               }));
        }

Create one attached property to change the visual state. This will work for you

  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);
                               }));
        }
一袭白衣梦中忆 2024-09-04 15:13:33

根据 MSDN,当您在控件模板外部使用视觉状态管理器,您应该使用 GoToElementState 方法,而不是 GoToState 方法。不过我还没有测试过。

According to MSDN, when you use the Visual State Manager outside of a control template, you should use the GoToElementState method, not the GoToState method. I have not tested it, though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文