我正在尝试实现一个控件,其工作方式类似于 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
}