Silverlight: переключение визуальных состояний CustomVisualStateManager в коде
Я пытался решить следующую проблему: при создании пользовательских анимаций для различных визуальных состояний в Expression Blend 3, которые изменяют размер / непрозрачность нескольких элементов в сетке, он создает группы визуальных состояний в самой сетке, а не в стиле элемента управления и определяет его как CustomVisualStateManager.
<Grid x:Name="LayoutRoot" Background="White" Height="500" HorizontalAlignment="Left" VerticalAlignment="Top" Width="500">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MyVisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.3000000">
<VisualTransition.GeneratedEasingFunction>
<CircleEase EasingMode="EaseIn"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="State1"/>
<VisualState x:Name="State2">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="myBox" Storyboard.TargetProperty="(FrameworkElement.Height)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="360"/>
<!-- omitting other storyboard animations here for clarity -->
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
<ic:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<!-- omitting other grid elements here for clarity -->
</Grid>
Со мной все в порядке, но проблема в том, что я не могу переключать состояния в коде, когда пытаюсь
VisualStateManager.GoToState(this, "State1", true);
ничего не происходит, потому что сам элемент управления не определил эти визуальные состояния, как показано
VisualStateManager.GetVisualStateGroups(this);
Если я попробую
VisualStateManager.GetVisualStateGroups(LayoutRoot);
это показывает именно то, что мне нужно. Но я не могу передать LayoutRoot VisualStateManager, потому что ему нужен аргумент типа Control, а Grid - нет. Мой вопрос - как я могу получить доступ / изменить состояния этого CustomVisualStateManager в коде позади?
1 ответ
CustomVisualStateManager только там, когда вы включаете FluidLayout. Если в вашем проекте не используется морфинг макета (т. Е. Вы пытаетесь использовать состояния для плавной анимации из одного макета в другой), вы можете отключить его. Наличие собственного VSM не должно иметь никакого значения в использовании VSM.
Разметка визуального состояния всегда находится внутри контейнера верхнего уровня, так что это совершенно нормально. Кстати, это может быть просто опечатка в вашем образце, но код, который вы показываете, на самом деле пытается установить состояние, в котором ничего нет, так что это может не быть желаемым результатом.
В противном случае вызов VisualStateManager.GoToState в UserControl должен работать. Вот пример, который я только что сделал, который работает:
Это простой пример приложения Silverlight с главной страницей и пользовательским элементом управления, который я добавил на главную страницу. Главная страница действительно проста:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SLStateTest"
x:Class="SLStateTest.MainPage"
Width="640" Height="480">
<Grid x:Name="LayoutRoot" Background="White">
<local:UserControl1 x:Name="TestControl" Height="100" HorizontalAlignment="Left" Margin="24,32,0,0" VerticalAlignment="Top" Width="100"/>
<Button Height="40" HorizontalAlignment="Left" Margin="192,32,0,0" VerticalAlignment="Top" Width="104" Content="State 1" Click="OnClick"/>
<Button Height="40" HorizontalAlignment="Left" Margin="192,76,0,0" VerticalAlignment="Top" Width="104" Content="State 2" Click="OnClickState2"/>
</Grid></UserControl>
Есть экземпляр моего пользовательского контроля и две кнопки. Посмотрим, что кнопки делают через секунду. Сначала давайте посмотрим на UserControl (UserControl1):
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
x:Class="SLStateTest.UserControl1"
d:DesignWidth="280" d:DesignHeight="264">
<Grid x:Name="LayoutRoot" Background="#FF6FFE22">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Test" ic:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualState x:Name="State1">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="#FF003AFF"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="State2">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="#FFFF0202"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
<ic:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
</Grid></UserControl>
Как видите, в одной группе визуальных состояний определены два визуальных состояния, которые просто устанавливают цвет в корне макета пользовательского элемента управления.
Две кнопки на главной странице связаны с обработчиками событий, которые выглядят следующим образом:
private void OnClick(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
VisualStateManager.GoToState(TestControl, "State1", true);
}
private void OnClickState2(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
TestControl.SetState();
}
Первый просто вызывает VisualStateManager.GoToState в UserControl на странице. Второй вызывает функцию iside пользовательского элемента управления, которая делает то же самое. Я просто использовал оба метода, чтобы показать, что оба варианта доступны - вы можете вызвать VSM.GoToState снаружи или изнутри UC. Метод SetState() пользовательского элемента управления выглядит следующим образом:
public void SetState()
{
VisualStateManager.GoToState(this, "State2", true);
}
Когда вы запустите приложение, пользовательский элемент управления сначала будет отображаться в его базовом состоянии, которое зеленого цвета. Когда вы нажимаете кнопку State1, она переходит в State1, который устанавливает UC в синий цвет, вызывая VSM.GoToState() снаружи. Когда вы нажимаете кнопку State 2, она становится красной, вызывая VSM изнутри.
Из отрывков, которые вы разместили, я не вижу, что идет не так, если не считать одной проблемы, о которой я упоминал в начале. Тем не менее, мой маленький образец может помочь вам увидеть, что отличается в вашем случае.
Надеюсь, это поможет...