我有一个继承自SecurePage
的基类UserControl
。
应用程序内的每个“页面”都继承自SecurePage
。
我想在Style
的默认SecurePage
中定义一个带有某些VisualStateGroup
的VisualState
。
问题是,在派生类中没有这些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();
}
}
}
信息文件
<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
本身。更精确地说-overridden StateGroupsRoot
property,由VisualStateManager.GoToState
方法使用。通常,它返回控件模板的根元素,但是在UserControl
的情况下,它返回UserControl.Content
属性的值。因此,发生的情况是,当您调用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
会产生一个空列表,因为它只是一个普通的附加依赖项属性访问器,而您并未在控件上设置该属性。为了掌握您在模板中定义的组,您应该通过模板根作为参数来调用它。按照相同的原则,您不希望控件上调用Grid.GetColumn
返回在模板中某个位置设置的值。关于在控件的构造函数中调用
GoToState
,它很可能无法正常工作,因为您的控件仅被实例化,并且很可能其Templtate
为null(请记住,您在模板内定义了视觉状态)。最好将逻辑移至OnApplyTemplate
覆盖。1因为
VisualStateManager.VisualStateGroupsProperty
是只读的,所以我的意思是将项目添加到VisualStateManager.GetVisualStateGroups
返回的列表中关于c# - XAML样式/基类中VisualStateGroup/VisualState的继承,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51246313/