c# - VisualStateManager 似乎无法在 UserControl 的 ControlTemplate 中工作

标签 c# wpf windows-phone-8.1 visualstatemanager visualstategroup

我正在尝试实现一个控件,它的工作方式类似于 Windows Phone 键盘上的按钮:按住时,它应该显示带有附加选项的附加面板。

我在按住按钮后成功显示了附加部分,但现在我正在尝试设置边框样式以响应用户指针的移动。我尝试了我之前使用的方法 - 使用 VisualStateManager - 但由于某种原因它根本不起作用。你能告诉我,为什么吗?

Xaml:

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

    <Style TargetType="local:ExpandKey">
        <Setter Property="BorderBrush" Value="{ThemeResource PhoneForegroundBrush}" />
        <Setter Property="BorderThickness" Value="{ThemeResource PhoneBorderThickness}" />
        <Setter Property="Background" Value="{ThemeResource PhoneBackgroundBrush}" />
        <Setter Property="OverlayBrush" Value="{ThemeResource PhoneAccentBrush}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:ExpandKey">
                    <Grid x:Name="PART_MainGrid">
                        <Border x:Name="PART_MainBorder" 
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="Pressed">

                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="PART_MainBorder">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="PART_MainBorder">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Blue" />
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <TextBlock>Test</TextBlock>
                        </Border>

                        <Grid x:Name="PART_OverlayGrid" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
                              Background="{TemplateBinding OverlayBrush}" Visibility="Collapsed">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="1*" />
                                <RowDefinition Height="1*" />
                            </Grid.RowDefinitions>

                            <Border x:Name="PART_AltBtn" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                                    Background="{TemplateBinding Background}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}" />
                            <Border x:Name="PART_Btn" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                                    Background="{TemplateBinding Background}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}" />
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

代码:

public sealed class ExpandKey : Control
{
    private const int OVERLAY_MARGIN = 10;

    private Grid mainGrid;
    private Border mainBorder;
    private Grid overlayGrid;
    private Border altBtn;
    private Border btn;

    private void AttachEvents()
    {
        if (mainBorder != null)
            mainBorder.Holding += HandleMainBorderHolding;
        if (overlayGrid != null)
            overlayGrid.PointerReleased += HandleOverlayGridPointerReleased;
    }

    private void DetachEvents()
    {
        if (mainBorder != null)
            mainBorder.Holding -= HandleMainBorderHolding;
        if (overlayGrid != null)
            overlayGrid.PointerReleased -= HandleOverlayGridPointerReleased;
    }

    private void MeasureOverlayGrid()
    {
        if (mainGrid == null ||
            mainBorder == null ||
            overlayGrid == null ||
            altBtn == null ||
            btn == null)
            throw new InvalidOperationException("Internal error: missing template parts!");

        var newTopMargin = -(mainGrid.ActualHeight + OVERLAY_MARGIN);
        var newBottomMargin = -OVERLAY_MARGIN;
        var newLeftMargin = -OVERLAY_MARGIN;
        var newRightMargin = -OVERLAY_MARGIN;

        overlayGrid.Margin = new Thickness(newLeftMargin, newTopMargin, newRightMargin, newBottomMargin);

        btn.Margin = new Thickness(OVERLAY_MARGIN, 0, OVERLAY_MARGIN, OVERLAY_MARGIN);
        altBtn.Margin = new Thickness(OVERLAY_MARGIN, OVERLAY_MARGIN, OVERLAY_MARGIN, OVERLAY_MARGIN);
    }

    private void HandleMainBorderHolding(object sender, HoldingRoutedEventArgs e)
    {
        MeasureOverlayGrid();
        overlayGrid.Visibility = Visibility.Visible;
        e.Handled = false;
    }

    private void HandleOverlayGridPointerReleased(object sender, PointerRoutedEventArgs e)
    {
        overlayGrid.Visibility = Visibility.Collapsed;
    }

    protected override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        DetachEvents();

        mainGrid = GetTemplateChild("PART_MainGrid") as Grid;
        mainBorder = GetTemplateChild("PART_MainBorder") as Border;
        overlayGrid = GetTemplateChild("PART_OverlayGrid") as Grid;
        altBtn = GetTemplateChild("PART_AltBtn") as Border;
        btn = GetTemplateChild("PART_Btn") as Border;

        AttachEvents();
    }

    public ExpandKey()
    {
        this.DefaultStyleKey = typeof(ExpandKey);
    }

    #region OverlayBrush dependency property

    public Brush OverlayBrush
    {
        get { return (Brush)GetValue(OverlayBrushProperty); }
        set { SetValue(OverlayBrushProperty, value); }
    }

    // Using a DependencyProperty as the backing store for OverlayBrush.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty OverlayBrushProperty =
        DependencyProperty.Register("OverlayBrush", typeof(Brush), typeof(ExpandKey), new PropertyMetadata(null));

    #endregion
}

最佳答案

我认为你的 TargetProperty 不正确,

我会用

TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"TargetProperty="(Border.Background).(SolidColorBrush.Color)"

<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="PART_MainBorder">
    <DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>

<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="PART_MainBorder">
    <DiscreteObjectKeyFrame KeyTime="0" Value="Blue" />
</ObjectAnimationUsingKeyFrames>

参见 Color Change On List View Item我基本上用 Storyboard对 ListView SelectedItem 做同样的事情以供引用。

关于c# - VisualStateManager 似乎无法在 UserControl 的 ControlTemplate 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26534962/

相关文章:

c# - 如何在 c# windows phone 8.1 应用程序中写入 excel 文件?

c# - 如何在 C# 4 中对 T 执行动态 where lambda?

c# - 将 WebApi 添加到现有 MVC 项目 - 找不到与名为 "x"的 Controller 匹配的类型

wpf - 打印 WPF DataGrid 内容

wpf - 防止在 XAML 中编写大量重复代码

windows-phone-8 - 从 uri 安装 Windows Phone 应用程序

c# - 接口(interface)中的 Property 属性

c# - EntityFramework EF 不让我重新搭建脚手架

c# - 通知ViewModel模型集合已更改