为什么 VisualStateManager.GoToState 不能处理 WPF 中的控件?
Why doesn't VisualStateManager.GoToState work on a control in WPF?
我正在开发一个 WPF 应用程序,并尝试使用 Visual State Manager 制作响应式 UI,正如 MSDN 建议的 UWP 响应式设计,它适用于 UWP 但不适用于 WPF。
这是我在 WPF 上测试的示例。它应该在启动时将 StackPanel
的背景更改为 Red
。
XAML:
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultState">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="WideState">
<Storyboard >
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Menu" Storyboard.TargetProperty="StackPanel.Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="*"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Grid x:Name="StackPanelCenetrofPage" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="MenuColumnWidth" Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="Menu"
Orientation="Vertical"
Background="AliceBlue"
HorizontalAlignment="Stretch"
Grid.Column="0">
<Button Content="Hey"/>
</StackPanel>
<Frame Grid.Column="1"/>
</Grid>
</Grid>
C# 代码:
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.PreviousSize.Width < 1024)
{
VisualStateManager.GoToState(this, "WideState", true);
}
else
{
VisualStateManager.GoToState(this, "DefaultState", false);
}
}
根据 documentation:
Call the GoToState method if you are changing states in a control that uses the VisualStateManager in its ControlTemplate. Call the GoToElementState method to change states on an element outside of a ControlTemplate (for example, if you use a VisualStateManager in a UserControl or in a single element).
所以你应该使用 GoToElementState
而不是 GoToState
。 GoToElementState
的第一个参数是拥有 VisualStateManager
的控件,因此您应该将 VisualStateManager
移动到 Window
以继续在代码隐藏中使用 this
。
private void Window_SizeChanged(object sender, SizeChangedEventArgs e) {
if (e.PreviousSize.Width < 1024) {
var result = VisualStateManager.GoToElementState(this, "WideState", true); // <- Here
} else {
VisualStateManager.GoToElementState(this, "DefaultState", false);
}
}
附带说明一下,您不能像这样为 Background
设置动画。您需要定义 Value
是 Brush
而不仅仅是 Color
:
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Red"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
我正在开发一个 WPF 应用程序,并尝试使用 Visual State Manager 制作响应式 UI,正如 MSDN 建议的 UWP 响应式设计,它适用于 UWP 但不适用于 WPF。
这是我在 WPF 上测试的示例。它应该在启动时将 StackPanel
的背景更改为 Red
。
XAML:
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultState">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="WideState">
<Storyboard >
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Menu" Storyboard.TargetProperty="StackPanel.Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="*"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Grid x:Name="StackPanelCenetrofPage" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="MenuColumnWidth" Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="Menu"
Orientation="Vertical"
Background="AliceBlue"
HorizontalAlignment="Stretch"
Grid.Column="0">
<Button Content="Hey"/>
</StackPanel>
<Frame Grid.Column="1"/>
</Grid>
</Grid>
C# 代码:
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.PreviousSize.Width < 1024)
{
VisualStateManager.GoToState(this, "WideState", true);
}
else
{
VisualStateManager.GoToState(this, "DefaultState", false);
}
}
根据 documentation:
Call the GoToState method if you are changing states in a control that uses the VisualStateManager in its ControlTemplate. Call the GoToElementState method to change states on an element outside of a ControlTemplate (for example, if you use a VisualStateManager in a UserControl or in a single element).
所以你应该使用 GoToElementState
而不是 GoToState
。 GoToElementState
的第一个参数是拥有 VisualStateManager
的控件,因此您应该将 VisualStateManager
移动到 Window
以继续在代码隐藏中使用 this
。
private void Window_SizeChanged(object sender, SizeChangedEventArgs e) {
if (e.PreviousSize.Width < 1024) {
var result = VisualStateManager.GoToElementState(this, "WideState", true); // <- Here
} else {
VisualStateManager.GoToElementState(this, "DefaultState", false);
}
}
附带说明一下,您不能像这样为 Background
设置动画。您需要定义 Value
是 Brush
而不仅仅是 Color
:
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Red"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>