#c# #.net #wpf #silverlight #silverlight-4.0
#c# #.net #wpf #silverlight #silverlight-4.0
Вопрос:
В моем примере я использую элементы управления Telerik.
<telerik:RadPanelBarItem Collapsed="RadPanelBarItem_Collapsed"
DropPosition="Inside"
Header="Searching for Clients"
IsExpanded="false"
IsTabStop="True"
TabNavigation="Once">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Expanded">
<i:InvokeCommandAction Command="{Binding ExpandedComand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadPanelBarItem>
Я хотел бы запускать код в ViewModel всякий раз, когда запускается расширенное событие. Пока все хорошо, но мне также нужно запустить анимацию после ее расширения. Но это невозможно из ViewModel, но оно должно выполняться в представлении:
ArrowStoryboard.Begin();
Итак, как мне это сделать?
Обновить:
Позвольте мне подробнее остановиться, поскольку, похоже, это вызвало некоторую путаницу. Мне не нужно выполнять анимацию, связанную с представлением, из ViewModel. Но я должен выполнить две вещи при событии расширения. 1) Запустите анимацию и 2) запустите набор кода в ViewModel.
Единственный известный мне способ, но он не очень хорош, поскольку он добавляет код к исходному коду, заключается в следующем: приведение DataContext к ViewModel и запуск соответствующего метода в ViewModel сразу после начала анимации.
Спасибо,
Комментарии:
1. afaik вы можете запускать раскадровки из datatriggers, поэтому изменение состояния виртуальной машины может запустить раскадровку…
2. @Kave, вы можете использовать стиль, который я дал для запуска анимации, также вы можете создать свойство viewmodel с именем Expanded и привязать его к свойству IsExpanded RadPanelBarItem (сделайте режим TwoWay). Затем каждый раз, когда значение Expanded изменяется и устанавливается в true, запускайте свой код. Будет ли это работать для вас?
Ответ №1:
Почему бы не добавить другое поведение ControlStoryboardAction
помимо вашего InvokeCommandAction
?
xmlns:eim="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions"
<i:Interaction.Triggers>
<i:EventTrigger EventName="Expanded">
<i:InvokeCommandAction Command="{Binding ExpandedComand}" />
<eim:ControlStoryboardAction Storyboard="{StaticResource YourStoryBoard}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Обновить
На самом деле не так уж много работы для создания такого рода анимации внутри стиля с использованием Blend.
В основном, что я здесь сделал, так это то, что я использовал Blend для создания стиля RadPanelBarItem по умолчанию, затем в расширенном визуальном состоянии я создал анимацию, которая выводит стрелку, и заставил ее работать вечно.
Это не совсем та анимация, которую вы хотите (стрелка идет вверх, а не вправо), но это может дать вам некоторые идеи. Надеюсь, это поможет. 🙂
Просто примените имя стиля AnimatedRadPanelBarItemStyle
.
<LinearGradientBrush x:Key="ControlItem_Background_Normal" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White"/>
<GradientStop Color="Gainsboro" Offset="0.43"/>
<GradientStop Color="#FFADADAD" Offset="0.44"/>
<GradientStop Color="#FFD4D4D4" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ControlItem_OuterBorder_Normal" Color="#FF848484"/>
<SolidColorBrush x:Key="ControlForeground_Normal" Color="#FF000000"/>
<SolidColorBrush x:Key="ControlItem_InnerBorder_Normal" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="ControlItem_OuterBorder_MouseOver" Color="#FFFFC92B"/>
<SolidColorBrush x:Key="ControlItem_InnerBorder_MouseOver" Color="#FFFFFFFF"/>
<LinearGradientBrush x:Key="ControlItem_Background_MouseOver" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFBA3" Offset="1"/>
<GradientStop Color="#FFFFFBDA" Offset="0"/>
<GradientStop Color="#FFFFD25A" Offset="0.43"/>
<GradientStop Color="#FFFEEBAE" Offset="0.42"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="ControlItem_OuterBorder_Selected" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF282828"/>
<GradientStop Color="#FF5F5F5F" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="ControlItem_InnerBorder_Selected" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFB69A78"/>
<GradientStop Color="#FFFFE17A" Offset="0.126"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="ControlItem_Background_Selected" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFD74E" Offset="0.996"/>
<GradientStop Color="#FFFFDCAB" Offset="0.17"/>
<GradientStop Color="#FFFFB062" Offset="0.57"/>
<GradientStop Color="#FFFFD18F" Offset="0.56"/>
<GradientStop Color="#FFFFBA74"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ControlOuterBorder_Disabled" Color="#FF989898"/>
<SolidColorBrush x:Key="ControlInnerBorder_Disabled" Color="Transparent"/>
<SolidColorBrush x:Key="ControlBackground_Disabled" Color="#FFE0E0E0"/>
<SolidColorBrush x:Key="ControlElement_Normal" Color="#FF000000"/>
<SolidColorBrush x:Key="FocusBrushBlack" Color="#FF000000"/>
<ControlTemplate x:Key="PanelBarItemTopLevelTemplate" TargetType="telerik:RadPanelBarItem">
<Grid x:Name="RootElement">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="NormalVisual"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisual"/>
<DoubleAnimation Duration="0" To="0.5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Header"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="arrow">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MouseOverVisual"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOut"/>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectVisual"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ExpandStates">
<VisualState x:Name="Expanded">
<Storyboard RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ItemsContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Duration="0:0:0.2" From="0.0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ItemsContainer"/>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="arrow">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-6"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="arrow">
<EasingDoubleKeyFrame KeyTime="0" Value="180"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="180"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="180"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="180"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="arrow">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="HeaderRow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border x:Name="NormalVisual" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.ColumnSpan="5">
<Border BorderBrush="{StaticResource ControlItem_InnerBorder_Normal}" BorderThickness="1" Background="{TemplateBinding Background}"/>
</Border>
<Border x:Name="MouseOverVisual" BorderBrush="{StaticResource ControlItem_OuterBorder_MouseOver}" BorderThickness="1" Grid.ColumnSpan="5" Opacity="0">
<Border BorderBrush="{StaticResource ControlItem_InnerBorder_MouseOver}" BorderThickness="1" Background="{StaticResource ControlItem_Background_MouseOver}"/>
</Border>
<Border x:Name="SelectVisual" BorderBrush="{StaticResource ControlItem_OuterBorder_Selected}" BorderThickness="1" Grid.ColumnSpan="5" Opacity="0">
<Border BorderBrush="{StaticResource ControlItem_InnerBorder_Selected}" BorderThickness="1" Background="{StaticResource ControlItem_Background_Selected}"/>
</Border>
<Border x:Name="DisabledVisual" BorderBrush="{StaticResource ControlOuterBorder_Disabled}" BorderThickness="1" Grid.ColumnSpan="5" Opacity="0">
<Border BorderBrush="{StaticResource ControlInnerBorder_Disabled}" BorderThickness="1" Background="{StaticResource ControlBackground_Disabled}"/>
</Border>
<Path x:Name="arrow" Grid.Column="5" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Right" Margin="7 0" Opacity="1" RenderTransformOrigin="0.5 0.5" Stretch="None" Stroke="{StaticResource ControlElement_Normal}" StrokeThickness="2" VerticalAlignment="Center">
<Path.RenderTransform>
<CompositeTransform Rotation="0"/>
</Path.RenderTransform>
</Path>
<ContentPresenter x:Name="Header" Grid.ColumnSpan="4" ContentTemplate="{TemplateBinding HeaderTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle x:Name="FocusVisual" Grid.ColumnSpan="5" Grid.Column="0" IsHitTestVisible="False" Stroke="{StaticResource FocusBrushBlack}" StrokeThickness="1" StrokeDashArray="1 2" Visibility="Collapsed"/>
</Grid>
<Grid x:Name="ItemsContainer" Grid.Row="1" Visibility="Collapsed">
<telerik:LayoutTransformControl x:Name="transformationRoot">
<ItemsPresenter/>
</telerik:LayoutTransformControl>
</Grid>
</Grid>
</ControlTemplate>
<SolidColorBrush x:Key="ControlSubItem_OuterBorder_MouseOver" Color="#FFFFC92B"/>
<Thickness x:Key="ControlSubItem_OuterBorderThickness">1</Thickness>
<SolidColorBrush x:Key="ControlSubItem_InnerBorder_MouseOver" Color="#FFFFFFFF"/>
<Thickness x:Key="ControlSubItem_InnerBorderThickness">1</Thickness>
<LinearGradientBrush x:Key="ControlSubItem_Background_MouseOver" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFBA3" Offset="1"/>
<GradientStop Color="#FFFFFBDA" Offset="0"/>
</LinearGradientBrush>
<CornerRadius x:Key="ControlSubItem_InnerCornerRadius">0</CornerRadius>
<CornerRadius x:Key="ControlSubItem_OuterCornerRadius">1</CornerRadius>
<SolidColorBrush x:Key="ControlSubItem_OuterBorder_Selected" Color="#FFFFC92B"/>
<SolidColorBrush x:Key="ControlSubItem_InnerBorder_Selected" Color="#FFFFFFFF"/>
<LinearGradientBrush x:Key="ControlSubItem_Background_Selected" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFCE79F" Offset="1"/>
<GradientStop Color="#FFFDD3A8"/>
</LinearGradientBrush>
<ControlTemplate x:Key="PanelBarItemSecondLevelTemplate" TargetType="telerik:RadPanelBarItem">
<Grid x:Name="RootElement">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisual"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MouseOverVisual"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOut">
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="0.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MouseOverVisual"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionVisual"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ExpandStates">
<VisualState x:Name="Expanded">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ItemsContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Duration="0:0:0.2" From="0.0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ItemsContainer"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="HeaderRow" Background="Transparent">
<Border x:Name="MouseOverVisual" BorderBrush="{StaticResource ControlSubItem_OuterBorder_MouseOver}" BorderThickness="{StaticResource ControlSubItem_OuterBorderThickness}" CornerRadius="{StaticResource ControlSubItem_OuterCornerRadius}" Opacity="0">
<Border BorderBrush="{StaticResource ControlSubItem_InnerBorder_MouseOver}" BorderThickness="{StaticResource ControlSubItem_InnerBorderThickness}" Background="{StaticResource ControlSubItem_Background_MouseOver}" CornerRadius="{StaticResource ControlSubItem_InnerCornerRadius}"/>
</Border>
<Border x:Name="SelectionVisual" BorderBrush="{StaticResource ControlSubItem_OuterBorder_Selected}" BorderThickness="{StaticResource ControlSubItem_OuterBorderThickness}" CornerRadius="{StaticResource ControlSubItem_OuterCornerRadius}" Opacity="0">
<Border BorderBrush="{StaticResource ControlSubItem_InnerBorder_Selected}" BorderThickness="{StaticResource ControlSubItem_InnerBorderThickness}" Background="{StaticResource ControlSubItem_Background_Selected}" CornerRadius="{StaticResource ControlSubItem_InnerCornerRadius}"/>
</Border>
<Border x:Name="DisabledVisual" BorderBrush="{StaticResource ControlOuterBorder_Disabled}" BorderThickness="{StaticResource ControlSubItem_OuterBorderThickness}" CornerRadius="{StaticResource ControlSubItem_OuterCornerRadius}" Opacity="0">
<Border BorderBrush="{StaticResource ControlInnerBorder_Disabled}" BorderThickness="{StaticResource ControlSubItem_InnerBorderThickness}" Background="{StaticResource ControlBackground_Disabled}" CornerRadius="{StaticResource ControlSubItem_InnerCornerRadius}"/>
</Border>
<ContentPresenter x:Name="Header" ContentTemplate="{TemplateBinding HeaderTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle x:Name="FocusVisual" IsHitTestVisible="False" RadiusY="2" RadiusX="2" Stroke="{StaticResource FocusBrushBlack}" StrokeThickness="1" StrokeDashArray="1 2" Visibility="Collapsed"/>
</Grid>
<Grid x:Name="ItemsContainer" Grid.Row="1" Visibility="Collapsed">
<ItemsPresenter/>
</Grid>
</Grid>
</ControlTemplate>
<Style x:Key="AnimatedRadPanelBarItemStyle" TargetType="telerik:RadPanelBarItem">
<Setter Property="Background" Value="{StaticResource ControlItem_Background_Normal}"/>
<Setter Property="BorderBrush" Value="{StaticResource ControlItem_OuterBorder_Normal}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{StaticResource ControlForeground_Normal}"/>
<Setter Property="TabNavigation" Value="Once"/>
<Setter Property="IsTabStop" Value="True"/>
<Setter Property="Template" Value="{StaticResource PanelBarItemTopLevelTemplate}"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="ChildItemsTemplate" Value="{StaticResource PanelBarItemSecondLevelTemplate}"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<telerik:PanelBarPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Комментарии:
1. Большое спасибо за совет. Это решение выглядит почти идеально. И как мне остановить анимацию ArrowStoryboard.Stop(); когда она рухнула? Я, конечно, могу добавить еще одно действие для свернутого события, но как остановить раскадровку из XAML?
2. эта раскадровка выполняется вечно? если нет, то вам, вероятно, не нужно это останавливать?
3. кроме того, вы пытаетесь анимировать стрелку вверх / вниз на RadPanelBarItem?
4. Да, Синь, он работает вечно. Я думаю, что нашел это. Пожалуйста, поправьте меня, если я ошибаюсь: <i:EventTrigger eventName=»Свернутый»> <i:Команда InvokeCommandAction=»{Привязка свернутой команды}» /> <ei:ControlStoryboardAction Storyboard=»{StaticResource ArrowStoryboard}» IsEnabled=»False» /> </i:EventTrigger>
5. Лучшим способом было бы создать визуальную группу состояний, которая содержит два состояния, одно использует ArrowStoryboard, другое в основном просто отключает его, затем вы можете использовать два поведения GoToAction (одна подписка расширена, другая свернута), чтобы вызвать их соответствующим образом. Однако, мой вопрос в том, похоже, что вы пытаетесь анимировать стрелку, почему бы не отредактировать ExpandStates в стиле, а не создавать свои собственные раскадровки / визуальные состояния?
Ответ №2:
Плохая идея вызывать действие, специфичное для ViewModel, из ViewModel, поскольку раскадровка не имеет ничего общего с view model. Есть два способа добиться того, что вы хотите сделать.
- Вы можете ввести View в ViewModel, но мне действительно не нравится эта идея, поскольку MVVM пытается сделать View и ViewModel менее связанными.
- Используйте службу сообщений для отправки и получения данных между View и ViewModel таким образом, чтобы они не знали друг друга. Я использую MVVMLight в своем проекте и использую его класс Messenger. MVVMLight очень прост в использовании.