将视觉状态应用于Border元素

时间:2012-02-28 15:21:55

标签: wpf silverlight xaml

我正在学习如何使用VisualStates,并遇到这个问题:

我有一个Control模板,里面有Grid,网格包含图像和两个TextBlocks。我希望每当鼠标放在一个控件上时放置一个矩形。互联网上的大多数例子都使用了Blend,我目前还没有这个例子,而且我也想学习如何手动完成。这是一个简单的模板(我使用了常量颜色使其更简单):

<ControlTemplate x:Key="MyControlTemplate" TargetType="SomeControl">
    <Grid Cursor="Hand" Width="Auto">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Image Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" Stretch="None" Source="{Binding ImageUrl}" />
        <TextBlock x:Name="TitleElement" Grid.Column="1" Margin="4" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Content}" Foreground="{StaticRecource TitleForegroundBrush}" />
        <TextBlock x:Name="DescriptionElement" Grid.Row="1" Grid.Column="1" Margin="4,0,4,4" MaxWidth="200" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Description}" Foreground="{StaticResource DescriptionElementForeground}" />
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Unfocused"/>
                <VisualState x:Name="Focused">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames  Storyboard.TargetName="TitleElement" Storyboard.TargetProperty="Foreground">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{StaticResource TitleElementFocusedForeground}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
         </VisualStateManager.VisualStateGroups>
    </Grid>
</ControlTemplate>

鼠标悬停时更改TitleElement的前景正在运行。现在我想在鼠标悬停上完全控制边框(不仅仅是它的一部分)。我尝试的第一件事是将Border作为网格容器并将StoryBoard放在VisualStateGroup中:

<Border x:Name="ControlBorder" BorderBrush="{StaticResource ControlBorderBrush}" BorderThickness="0">
    <Grid Cursor="Hand" Width="Auto">
....
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Unfocused"/>
            <VisualState x:Name="Focused">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames  Storyboard.TargetName="TitleElement" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{StaticResource TitleElementFocusedForeground}" />
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ControlBorder" Storyboard.TargetProperty="BorderThickness">
                        <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="1" />
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
     </VisualStateManager.VisualStateGroups>

这不起作用,事实上,现在TitleElement甚至没有像过去那样改变前景色。但是,在网格中添加Border作为第4个元素(RowSpan和ColumnSpan设置为整个网格)可以工作!但是有一些副作用我不喜欢,例如,当我移动鼠标时矩形是“闪烁”控制。问题:

  1. 为什么将Grid放在Rectangle中不起作用,但将Rectangle放在网格中?
  2. 我看到有一个CommonStates VisualGroup,必须在某处预定义。我们如何知道哪些是预定义的,以及它们各自的名称?
  3. VisualStateManager的范围是什么?如果我在一个元素中定义它,它只属于那个元素,还是整个ControlTemplate?
  4. 感谢。

1 个答案:

答案 0 :(得分:2)

  1. 需要在控件模板的根元素上管理视觉状态,如果在根周围放置一个元素,它们将被忽略,您需要将它们移动。< / p>

  2. 在控件的styles and templates页面上列出了特定的状态,所有普通状态应该是相同的(因为它们是“常见的”),所支持的状态也列在控件的页面。 (例如ButtonNormalPressedMouseOverDisabled

  3. 适用于整个模板(参见1.)