GoToState 不适用于 UserControl 中的 ControlTemplate

发布于 2024-09-12 22:22:24 字数 2699 浏览 1 评论 0原文

我完全迷失了,我非常感谢你对此的帮助。

我的最终目标是创建一个包含两个控件模板的用户控件。正方形和圆形。根据类型,控件将显示其中一种。当鼠标进入形状时,不透明度将更改为 0.2。

第一部分有效,但不透明度没有改变。该事件被触发并调用 GoToState,但没有结果。不透明度保持为 1。

我的 XAML:

<UserControl.Resources>

    <ControlTemplate x:Key="TemplateSquare" TargetType="{x:Type local:KeyControl}">

        <Canvas x:Name="MainCanvas" VerticalAlignment="Center" HorizontalAlignment="Center">

            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="MouseOver">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="CenterRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0" To=".2"/>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <Rectangle x:Name="CenterRectangle" Fill="Red" Width="100" Height="100"></Rectangle>

        </Canvas>

    </ControlTemplate>    
</UserControl.Resources> 
<!-- IF I MOVE THE CANVAS HERE THE OPACITY CHANGES ON MOUSE OVER -->

代码隐藏:

public partial class KeyControl : UserControl
{
    private bool _isPressed = false;
    private bool _isMouseOver = false;

    public KeyControl()
    {
        InitializeComponent();

        this.Loaded += new RoutedEventHandler(KeyControl_Loaded);
    }


    private void KeyControl_Loaded(object sender, RoutedEventArgs e)
    {
        //this will be set in the Type setter
        this.Template = this.FindResource("TemplateSquare") as ControlTemplate;

        this.MouseEnter += new MouseEventHandler(CorePart_MouseEnter);
        this.MouseLeave += new MouseEventHandler(CorePart_MouseLeave);

        GoToState(false);
    }

    private void GoToState(bool useTransitions)
    {
        if (_isPressed)
            VisualStateManager.GoToState(this, "Pressed", useTransitions);
        else if (_isMouseOver)
            VisualStateManager.GoToState(this, "MouseOver", useTransitions);
        else
            VisualStateManager.GoToState(this, "Normal", useTransitions);
    }

    private void CorePart_MouseLeave(object sender, MouseEventArgs e)
    {
        _isMouseOver = false;
        GoToState(true);
    }

    private void CorePart_MouseEnter(object sender, MouseEventArgs e)
    {
        _isMouseOver = true;
        GoToState(true);
    }
}

有人可以告诉我问题可能出在哪里吗?

谢谢

I am totally lost and I would really appreciate your help on this.

My final goal is to create a user control that will contain two control templates. Square and a Circle. Based on a type the control will display one or the other. When the mouse enters the shape the Opacity will change to 0.2.

The first part works but the Opacity does not change. The event is triggered and a GoToState is called, but with no result. The Opacity stays 1.

My XAML:

<UserControl.Resources>

    <ControlTemplate x:Key="TemplateSquare" TargetType="{x:Type local:KeyControl}">

        <Canvas x:Name="MainCanvas" VerticalAlignment="Center" HorizontalAlignment="Center">

            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="MouseOver">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="CenterRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0" To=".2"/>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <Rectangle x:Name="CenterRectangle" Fill="Red" Width="100" Height="100"></Rectangle>

        </Canvas>

    </ControlTemplate>    
</UserControl.Resources> 
<!-- IF I MOVE THE CANVAS HERE THE OPACITY CHANGES ON MOUSE OVER -->

Codebehind:

public partial class KeyControl : UserControl
{
    private bool _isPressed = false;
    private bool _isMouseOver = false;

    public KeyControl()
    {
        InitializeComponent();

        this.Loaded += new RoutedEventHandler(KeyControl_Loaded);
    }


    private void KeyControl_Loaded(object sender, RoutedEventArgs e)
    {
        //this will be set in the Type setter
        this.Template = this.FindResource("TemplateSquare") as ControlTemplate;

        this.MouseEnter += new MouseEventHandler(CorePart_MouseEnter);
        this.MouseLeave += new MouseEventHandler(CorePart_MouseLeave);

        GoToState(false);
    }

    private void GoToState(bool useTransitions)
    {
        if (_isPressed)
            VisualStateManager.GoToState(this, "Pressed", useTransitions);
        else if (_isMouseOver)
            VisualStateManager.GoToState(this, "MouseOver", useTransitions);
        else
            VisualStateManager.GoToState(this, "Normal", useTransitions);
    }

    private void CorePart_MouseLeave(object sender, MouseEventArgs e)
    {
        _isMouseOver = false;
        GoToState(true);
    }

    private void CorePart_MouseEnter(object sender, MouseEventArgs e)
    {
        _isMouseOver = true;
        GoToState(true);
    }
}

Can somebody please tell me where the problem could be?

Thank You

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

说谎友 2024-09-19 22:22:24

UserControl 使其内容成为“根”元素,用于定位 VisualStateGroups。如果您使用 Reflector 并查看 UserControl.StateGroupsRoot,您会看到它看起来像:

internal override FrameworkElement StateGroupsRoot {
    get {
        return (base.Content as FrameworkElement);
    }
}

虽然 FrameworkElement(以及大多数其他元素)使用:

internal virtual FrameworkElement StateGroupsRoot {
    get {
        return (this._templateChild as FrameworkElement);
    }
}

设置 Template 属性时,Content 属性仍将为 null。当您将画布移动到资源下方时,您正在设置内容属性。所以在这种情况下可以找到视觉状态组。

您可以通过更改直接从 ContentControl 派生的控件并绕过 UserControl 来解决此问题。只需在 XAML 和代码隐藏中将 UserControl 引用更改为 ContentControl 即可。

The UserControl makes it's Content the "root" element, which is used to locate the VisualStateGroups. If you use Reflector and look at UserControl.StateGroupsRoot, you'd see it looks like:

internal override FrameworkElement StateGroupsRoot {
    get {
        return (base.Content as FrameworkElement);
    }
}

While FrameworkElement (and thus most other elements) use:

internal virtual FrameworkElement StateGroupsRoot {
    get {
        return (this._templateChild as FrameworkElement);
    }
}

When setting the Template property, the Content property will still be null. When you move the Canvas to be below Resources, you are setting the Content property. So the visual state groups can be found in that case.

You can work around this by changing your control derive from ContentControl directly, and bypass UserControl. Simply change UserControl references to ContentControl in your XAML and code-behind.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文