自定义控件中的VisualStateGroup无法正常工作

时间:2020-01-14 09:13:10

标签: c# xaml uwp

在我的VisualStateGroup中,使用ControlTemplate通用状态名称对UI没有影响。

在其他样式示例中,正如我在github上的Microsoft Toolkit源代码中看到的那样,相同的状态名称都可以完美地工作,所以我认为这是因为我使用了自定义目标控件。

TargetType =“ local:VolumetricButton

是否可以修复此代码?
如果没有,如何在您的ControlTemplate中正确添加和处理“ CommonStates”?

Generic.xaml


<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Components">

    <Style TargetType="local:VolumetricButton">
        <Setter Property="Template" Value="{StaticResource VolumetricButtonTemplate}" />
    </Style>

    <ControlTemplate x:Key="VolumetricButtonTemplate" TargetType="local:VolumetricButton">
        <Grid x:Name="RootGrid">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualStateGroup.Transitions>
                        <VisualTransition To="PointerOver" 
                                          GeneratedDuration="0:0:0.5"/>
                    </VisualStateGroup.Transitions>

                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="PointerOver">
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetName="BackBrush" 
                                            Storyboard.TargetProperty="Color" To="Red" />
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Rectangle x:Name="BackgroundRectangle" RadiusX="2" RadiusY="2">
                <Rectangle.Fill>
                    <SolidColorBrush x:Name="BackBrush" Color="Green"/>
                </Rectangle.Fill>
            </Rectangle>
        </Grid>
    </ControlTemplate>
</ResourceDictionary>


VolumetricButton.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Documents;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;

// The Templated Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234235

namespace Components
{
    [TemplatePart(Name = BackgroundRectangleName, Type = typeof(Rectangle))]
    [TemplatePart(Name = RootGridName, Type = typeof(Grid))]
    public sealed class VolumetricButton : Control
    {
        private const string BackgroundRectangleName = "BackgroundRectangle";
        private const string RootGridName = "RootGrid";

        private Rectangle BackgroundRectangle;
        private Grid RootGrid;

        public VolumetricButton()
        {
            this.DefaultStyleKey = typeof(VolumetricButton);

            // 
            // Set core events
            //
            this.SizeChanged += OnThisSizeChanged;
        }

        /// <inheritdoc/>
        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            //
            // New code here
            // 

            // Find and set RootGrid
            RootGrid = GetTemplateChild(RootGridName) as Grid;

            // Find and set BackgroundRectangle
            BackgroundRectangle = GetTemplateChild(BackgroundRectangleName) as Rectangle;
        }

        private void OnThisSizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (BackgroundRectangle != null
                && RootGrid != null)
            {
                BackgroundRectangle.Width = RootGrid.ActualWidth;
                BackgroundRectangle.Height = RootGrid.ActualHeight;
            }
        }
    }
}

Best regards,

Roman

1 个答案:

答案 0 :(得分:1)

您目前仅定义PointerOver的状态,但尚未定义如何触发状态。

尝试一下:

  1. OnApplyTemplate中添加与指针相关的事件
protected override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    // ...

    RootGrid.PointerEntered += RootGrid_PointerEntered;
    RootGrid.PointerExited += RootGrid_PointerExited;
}
  1. 事件处理方法中的完整状态切换
private void RootGrid_PointerExited(object sender, PointerRoutedEventArgs e)
{
    VisualStateManager.GoToState(this, "Normal", true);
}

private void RootGrid_PointerEntered(object sender, PointerRoutedEventArgs e)
{
    VisualStateManager.GoToState(this, "PointerOver", true);
}

最诚挚的问候。