VisualStates в Silverlight или управление состоянием из ViewModel (MVVM) продолжение
WPF, MVVM, Silverlight | создано: 08.01.2011 | опубликовано: 08.01.2011 | обновлено: 13.01.2024 | просмотров: 4496
В прошлой статье я рассказал как можно управлять состоянием представления (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). Вот и всё.