问题描述
我正在开发 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);
}
}
解决方法
如果要更改在其 ControlTemplate 中使用 VisualStateManager 的控件中的状态,请调用 GoToState 方法。调用 GoToElementState 方法以更改 ControlTemplate 外部元素的状态(例如,如果您在 UserControl 或单个元素中使用 VisualStateManager)。
因此您应该使用 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>