2

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

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

xml:

<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
}
4

1 回答 1

0

我认为您的 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>

请参阅List View Item 上的颜色更改,其中我基本上用 Storyboard 对 ListView SelectedItem 做同样的事情以供参考。

于 2014-10-24T00:38:57.083 回答