c# - XAML 样式/基类中 VisualStateGroup/VisualState 的继承
问题描述
- 我有一个
SecurePage
继承自UserControl
. - 应用程序内部的每个“页面”都继承自
SecurePage
. - 我想在默认
Style
的SecurePage
a中定义VisualStateGroup
一些VisualState
s。
问题是,在派生类中这些VisualState
s 都不可用。
var states = VisualStateManager.GetVisualStateGroups(this);
返回一个空列表。
如果我复制我的XAML
VisualState
定义并将其粘贴到我的DerivadedFooSecurePage
中,我可以轻松进入状态:
VisualStateManager.GoToState(this, "Blink", false);
与此处描述的问题相同:抽象控件中的 VisualState
更多细节
安全页面
[TemplateVisualState(GroupName = "State", Name = "Normal")]
[TemplateVisualState(GroupName = "State", Name = "Blink")]
public class SecurePage: UserControl
{
public SecurePage()
{
DefaultStyleKey = typeof(HtSecurePage);
}
}
<Style TargetType="basic:SecurePage">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="basic:SecurePage">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Signals">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Blink">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="border">
<EasingColorKeyFrame KeyTime="0:0:0.4" Value="#FF3AFF00">
<EasingColorKeyFrame.EasingFunction>
<BounceEase EasingMode="EaseIn" Bounciness="3" Bounces="4"/>
</EasingColorKeyFrame.EasingFunction>
</EasingColorKeyFrame>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Content="{TemplateBinding Content}"/>
<Border
x:Name="border"
BorderThickness="5"
BorderBrush="Transparent"
IsHitTestVisible="False"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
信息页
信息.xaml.cs
namespace Views.General
{
public partial class Info
{
public Info()
{
InitializeComponent();
}
}
}
信息.xaml
<basic:SecurePage
x:Class="Views.General.Info"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:basic="clr-namespace:Foo.PlcFramework.Controls.Basic;assembly=Foo"
FontSize="14">
<Grid>
<TextBlock Text="HelloWorld"/>
</Grid>
</basic:SecurePage>
实时调试
states = 0
- 调用后没有任何反应
VisualStateManager.GoToState(this, "Blink", false);
states = 0
- 调用后没有任何反应
VisualStateManager.GoToState(this, "Blink", false);
将 VisualState 复制到派生类中
namespace Views.General
{
[TemplateVisualState(GroupName = "State", Name = "Normal")]
[TemplateVisualState(GroupName = "State", Name = "Blink")]
public partial class Info
{
public Info()
{
InitializeComponent();
var states = VisualStateManager.GetVisualStateGroups(this);
VisualStateManager.GoToState(this, "Blink", false);
}
}
}
<basic:SecurePage
x:Class="Views.General.Info"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:basic="clr-namespace:Foo.PlcFramework.Controls.Basic;assembly=Foo"
FontSize="14">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Signals">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Blink">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="border">
<EasingColorKeyFrame KeyTime="0:0:0.4" Value="#FF3AFF00">
<EasingColorKeyFrame.EasingFunction>
<BounceEase EasingMode="EaseIn" Bounciness="3" Bounces="4"/>
</EasingColorKeyFrame.EasingFunction>
</EasingColorKeyFrame>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock Text="HelloWorld"/>
<Border
x:Name="border"
BorderThickness="5"
BorderBrush="Transparent"
IsHitTestVisible="False"/>
</Grid>
</basic:SecurePage >
states = 0
- 调用后
VisualStateManager.GoToState(this, "Blink", false);
状态变了!!
我只想在定义中定义状态XAML Style
并SecurePage
进入任何派生类中的状态!
解决方案
诊断
经过一番摸索,我终于找到了罪魁祸首——它UserControl
本身。更准确地说 -方法使用的覆盖StateGroupsRoot
属性VisualStateManager.GoToState
。通常,它返回控件模板的根元素,但如果UserControl
它返回UserControl.Content
属性的值。所以发生的情况是,当您调用 时GoToState
,模板中定义的状态不会被考虑在内。
解决方案
这个问题至少有两种解决方案。
第一个解决方案是从而不是派生您的基类 ( SecurePage
) 。后者并没有太大的不同——它的默认值和属性为、和。此外,除了覆盖提到的属性之外,它还提供自己的(a ),但我认为您不必担心这一点。ContentControl
UserControl
Focusable
IsTabStop
false
HorizontanContentAlignment
VerticalContentAlignment
Stretch
StateGroupsRoot
AutomationPeer
UserControlAutomationPeer
第二种解决方案是VisualStateManager.GoToElementState
在模板根目录上使用。例如:
public class SecurePage : UserControl
{
//Your code here...
private FrameworkElement TemplateRoot { get; set; }
public override void OnApplyTemplate()
{
if (Template != null)
TemplateRoot = GetVisualChild(0) as FrameworkElement;
else
TemplateRoot = null;
}
public bool GoToVisualState(string name, bool useTransitions)
{
if (TemplateRoot is null)
return false;
return VisualStateManager.GoToElementState(TemplateRoot, name, useTransitions);
}
}
其他注意事项
调用VisualStateManager.GetVisualStateGroups
您的控件会产生一个空列表,因为它只是一个普通的附加依赖属性访问器,并且您没有在控件上设置1该属性。要获取您在模板中定义的组,您应该调用它并将模板根作为参数传递。根据相同的原则,您不希望Grid.GetColumn
在您的控件上调用返回您在模板中某处设置的值。
关于调用GoToState
控件的构造函数 - 它很可能不起作用,因为您的控件只是被实例化,并且很可能它Templtate
是 null (记住您在模板中定义了视觉状态)。最好将该逻辑移动到OnApplyTemplate
覆盖。
1因为VisualStateManager.VisualStateGroupsProperty
是只读的,所以我的意思是把项目添加到返回的列表中VisualStateManager.GetVisualStateGroups
推荐阅读
- asp.net-core - ASP.NET Core 3.1 Web 应用程序在 ISS 上的 ANCM 进程内启动失败
- go - Golang 将文本翻译到下一行
- ios - 在 react-native 开发环境中测试和记录“Device Offline”
- r - 如果我的当前文件夹存在于目录中,如何添加参数
- html - 创建新的 HTML 文件时如何解决错误
- python - 试图返回 3x3 棋盘的所有行、列和对角线
- python - 在终端中运行 python 时控制终端大小
- python - finplot 作为布局中的小部件
- c - 为什么这个 scanf() 语句不起作用?
- python - 从 conda 中选择 atom 中的虚拟环境