VisualStates в Silverlight или управление состоянием из ViewModel (MVVM) продолжение
WPF, MVVM, Silverlight | создано: 08.01.2011 | опубликовано: 08.01.2011 | обновлено: 13.01.2024 | просмотров: 4761
В прошлой статье я рассказал как можно управлять состоянием представления (View) из кода (ViewModel). В этой статье хочется показать еще один способ.
Речь пойдет на этот раз об Expression Studio 4.0, которая не так давно увидела свет, привнеся с собой кучу разных полезных нововведений и улучшений. Одним из таких нововведений стал класс, а точнее элемент управления поведением (behavior) который называется DataStateBehavior.
Этот класс позволяет декларативно (в XAML) выполнить привязку (binding) к визуальному представлению (View) из модели представления (ViewModel).
Для начала надо подключить необходимые для работы namespace:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Пусть есть ViewModel, который имеет следующий вид... Хотя нет. На этот раз буду использовать библиотеки Prism вместо свой библиотеки. Просто для разнообразия. Добавляем сборку Microsoft.Practices.Prism к проекту, чтобы реализовать паттерн MVVM. Подключим необходимые простраства имен:
using Microsoft.Practices.Prism.ViewModel; using Microsoft.Practices.Prism.Commands;
А теперь приведу код простейшего класса:
public class MainPageViewModel: NotificationObject
{
#region свойство IsRectangle
/// <summary>
/// поле для хранения значений свойства <see cref="IsRectangle"/>
/// </summary>
private bool isRectangle;
/// <summary>
/// свойство информирует о видимости квадрата.
/// </summary>
public bool IsRectangle
{
get
{
return isRectangle;
}
set
{
isRectangle = value;
RaisePropertyChanged(() => this.IsRectangle);
}
}
#endregion свойство IsRectangle
#region команда ChangeStateCommand
/// <summary>
/// Команда ChangeStateCommand
/// </summary>
public DelegateCommand ChangeStateCommand
{
get
{
return new DelegateCommand(() => this.ChangeStateCommandExecute());
}
}
/// <summary>
/// Процедура выполняет команды ChangeStateCommand
/// </summary>
private void ChangeStateCommandExecute()
{
// выполнение команды ChangeState
this.IsRectangle = !this.IsRectangle;
}
#endregion // end команда ChangeStateCommand
}
А теперь подключим этот ViewModel к нашему представлению. Подключение можно осуществить многими способами, а я на этот раз выберу способ, который "дружит" с понятием blendability. В файле MainPage.xaml потребуется добавить namespace текущего приложения:
xmlns:vm="clr-namespace:SilverlightApplication3"
А теперь используем его:
<UserControl.DataContext>
<vm:MainPageViewModel />
</UserControl.DataContext>
Настал черед показать как выглядят два состояния, которые мы будем менять при нажатии на (Button) кнопку или CheckBox:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup
x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition
GeneratedDuration="0:0:0.4" />
</VisualStateGroup.Transitions>
<VisualState
x:Name="EllipseState" />
<VisualState
x:Name="RectangleState">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame
KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Duration="0"
To="-214.5"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="ellipse"
d:IsOptimized="True" />
<DoubleAnimation
Duration="0"
To="-214.5"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="rectangle"
d:IsOptimized="True" />
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="ellipse">
<DiscreteObjectKeyFrame
KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Названия состояний, как видно из кода: EllipseState и RectangleState. А вот теперь то, ради чего была задумана эта статья. Воспользуемся классом DataStateBehavior, который довершит начатое:
<i:Interaction.Behaviors>
<ei:DataStateBehavior
Binding="{Binding IsRectangle}"
Value="True"
TrueState="RectangleState"
FalseState="EllipseState" />
</i:Interaction.Behaviors>
Этот класс выбирает (устанавливает) одно из двух состояний на основании значения (value), выбранного свойства (IsRectangle). Вот и всё.