VisualStateManager, кажется, не работает внутри ControlTemplate UserControl

Я пытаюсь реализовать элемент управления, который работает аналогично кнопке на клавиатуре 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
}

1 ответ

Я думаю, что ваш 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>

См. Изменение цвета в элементе списка, где я в основном делаю то же самое с раскадровкой для элемента ListView SelectedItem для справки.

Другие вопросы по тегам