- 我有一个继承自
UserControl
的基类SecurePage
。 - 应用内的每个“页面”都继承自
SecurePage
。 - 我想在
SecurePage
的默认Style
中定义一个带有一些VisualState
的VisualStateGroup
。
问题是,在派生类中,这些 VisualState
都不可用。
var states = VisualStateManager.GetVisualStateGroups(this);
返回一个空列表。
如果我复制 XAML
VisualState
定义并将其粘贴到我的 DerivadedFooSecurePage
中,我可以轻松转到状态:
VisualStateManager.GoToState(this, "Blink", false);
与此处描述的问题相同:VisualState in abstract control
更多详细信息
安全页面
[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>
信息页面
Info.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>
实时调试
状态 = 0
- 调用
VisualStateManager.GoToState(this, "Blink", false);
后没有任何反应
状态 = 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 >
状态 = 0
- 调用
VisualStateManager.GoToState(this, "Blink", false);
后状态发生更改!!
我只想在 SecurePage
的 XAML 样式
定义中定义状态,并转到任何派生类中的状态!
最佳答案
诊断
经过一番摸索,我终于找到了罪魁祸首 - 它是 UserControl
本身。更准确地说 - overridden StateGroupsRoot
property ,由 VisualStateManager.GoToState
使用方法。通常,它返回控件模板的根元素,但在 UserControl
的情况下它返回值 UserControl.Content
属性(property)。那么当你调用 GoToState
时会发生什么? ,不考虑模板中定义的状态。
解决方案
这个问题至少有两种解决方案。
第一个解决方案是从 SecurePage
派生基类 ( ContentControl
)而不是UserControl
。后者没有太大不同 - 它默认 Focusable
和IsTabStop
属性为false
,和HorizontanContentAlignment
和VerticalContentAlignment
至Stretch
。另外,除了提到的重写 StateGroupsRoot
属性,它提供自己的AutomationPeer
(a 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
是只读的,通过 set 我的意思是将项目添加到 VisualStateManager.GetVisualStateGroups
返回的列表中
关于c# - XAML 样式/基类中 VisualStateGroup/VisualState 的继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51246313/