Я учусь работать с VisualStates, и у меня возникла эта проблема:
У меня есть шаблон Control, в котором есть Grid, а 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 установлены на всю сетку) работает !, но есть некоторые побочные эффекты, которые мне не нравятся, например, прямоугольник «мигает», когда я перемещаю мышь над контроль. Вопросы:
- Почему размещение Grid внутри Rectangle не работает, а Rectangle внутри Grid работает?
- Я вижу, что существует VisualGroup CommonStates, который должен быть где-то предопределен. Как мы узнаем, какие из них предопределены, и их соответствующие имена?
- Какова область применения VisualStateManager? Если я определю его внутри элемента, относится ли он только к этому элементу или ко всему ControlTemplate?
Спасибо.