2014-10-13 10 views
1

У меня есть ContentControl, что я стилю с DataTemplate. Я хотел бы иметь возможность определять анимацию за пределами ContentControl, которая анимирует элементы в DataTemplate. Это XAML представляет собой небольшой, упрощенный пример моего сценария:Анимированные элементы в DataTemplate ContentControl

<UserControl x:Class="StoryboardTesting.Stage" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d"> 
    <UserControl.Resources> 
     <DataTemplate x:Key="MyControlTemplate"> 
      <StackPanel> 
       <TextBlock x:Name="TheBlock1" Text="Foo!" /> 
       <TextBlock x:Name="TheBlock2" Text="Bar!" /> 
      </StackPanel> 
     </DataTemplate> 
    </UserControl.Resources> 

    <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup Name="ValueStates"> 
      <VisualState Name="ToState"> 
       <Storyboard> 
        <DoubleAnimation Storyboard.TargetName="MyContentControl" 
            Storyboard.TargetProperty="(UIElement.Opacity)" 
            Duration="0:0:1" 
            To="0" /> 
       </Storyboard> 
      </VisualState> 
      <VisualState Name="FromState" /> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 
    <Grid> 
     <Canvas> 
      <ContentControl x:Name="MyContentControl" 
          ContentTemplate="{StaticResource MyControlTemplate}" /> 
     </Canvas> 
    </Grid> 
</UserControl> 

Я хотел бы анимации, чтобы иметь возможность выбрать либо TextBox в шаблоне (вместо «MyContentControl»), либо позиции или имени. Я начинаю анимацию в UserControl «s кода за вызовом, как это:

VisualStateManager.GoToElementState(this, "ToState", true); 

Когда я запускаю это (замена„MyContentControl“с„TheBlock“), я получаю следующее:

InvalidOperationException: имя «TheBlock1» не может быть найдено в области имен «StoryboardTesting.Stage».

Это имеет смысл. Есть ли способ адресовать любой блок, используя имена свойств? Мне нужно избегать codebehind, поскольку это XAML, который создается во время выполнения.

+0

Вы нашли решение по вашей проблеме? – Aybe

ответ

1

Я бы предложил вам изучить Blend при работе над проектами WPF. В то время как XAML с помощью навыков клавиатуры действительно полезен, Blend также очень полезен. Мне потребовалось около 5 минут, чтобы построить для вас следующий пример: это , в котором есть состояния.

(первый я создал пустой DataTemplate, то я редактировал в смесь)

Пользователь может нажать любую из кнопок 2 на дне и текущее состояние будет изменено.

enter image description here enter image description here

Как вы увидите ниже, поведение оказалось очень полезным для обработки состояний, без кода позади на всех.

XAML:

<Window x:Class="WpfApplication3.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
     xmlns:wpfApplication3="clr-namespace:WpfApplication3" 
     Title="MainWindow" 
     Width="525" 
     Height="350"> 
    <Window.Resources> 
     <wpfApplication3:MyObject x:Key="MyObject1" /> 
     <DataTemplate x:Key="Template1" DataType="wpfApplication3:MyObject"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition /> 
        <ColumnDefinition /> 
       </Grid.ColumnDefinitions> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="37*" /> 
        <RowDefinition Height="13*" /> 
       </Grid.RowDefinitions> 
       <VisualStateManager.VisualStateGroups> 
        <VisualStateGroup x:Name="VisualStateGroup"> 
         <VisualState x:Name="Red"> 
          <Storyboard> 
           <ColorAnimationUsingKeyFrames Storyboard.TargetName="button" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"> 
            <EasingColorKeyFrame KeyTime="0" Value="Red" /> 
           </ColorAnimationUsingKeyFrames> 
          </Storyboard> 
         </VisualState> 
         <VisualState x:Name="Green"> 
          <Storyboard> 
           <ColorAnimationUsingKeyFrames Storyboard.TargetName="button" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"> 
            <EasingColorKeyFrame KeyTime="0" Value="Lime" /> 
           </ColorAnimationUsingKeyFrames> 
          </Storyboard> 
         </VisualState> 
        </VisualStateGroup> 
       </VisualStateManager.VisualStateGroups> 
       <Button x:Name="button" 
         Grid.RowSpan="1" 
         Grid.ColumnSpan="2" 
         Width="100" 
         Height="100" 
         Margin="2" 
         Content="Button" 
         FontSize="26.667" /> 
       <Button Grid.Row="1" 
         Width="Auto" 
         Margin="2" 
         Content="State1"> 
        <i:Interaction.Triggers> 
         <i:EventTrigger EventName="Click"> 
          <ei:GoToStateAction StateName="Red" /> 
         </i:EventTrigger> 
        </i:Interaction.Triggers> 
       </Button> 
       <Button Grid.Row="1" 
         Grid.Column="1" 
         Width="Auto" 
         Margin="2" 
         Content="State2"> 
        <i:Interaction.Triggers> 
         <i:EventTrigger EventName="Click"> 
          <ei:GoToStateAction StateName="Green" /> 
         </i:EventTrigger> 
        </i:Interaction.Triggers> 
       </Button> 
      </Grid> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid> 
     <ContentControl Content="{StaticResource MyObject1}" ContentTemplate="{StaticResource Template1}" /> 
    </Grid> 
</Window> 

Code-за:

namespace WpfApplication3 
{ 
    public partial class MainWindow 
    { 
     public MainWindow() { 
      InitializeComponent(); 
     } 
    } 

    internal class MyObject 
    { 
     public string Category { get; set; } 
     public int Value { get; set; } 
    } 
} 

EDIT

Чтобы ответить на этот пункт вашего вопроса, эти состояния относятся к DataTemplate; определение этих состояний вне его не имеет никакого смысла, и, как вы испытали, это даже невозможно, и это по уважительной причине!

Предположите, что используете этот шаблон в двух разных местах: будут ли они иметь одинаковое состояние? Конечно, нет, поэтому в ней должны быть определены состояния, а не снаружи.

+0

Это не очень подходит для моего вопроса. Я хотел бы, чтобы анимации, определенные вне элемента управления, анимировали дочерние элементы управления внутри него (из шаблона). Это уже возможно, потому что вы можете использовать навигацию свойств в целевых объектах раскадровки. Я думал, что просто не могу понять свойство, чтобы получить элементы управления, созданные шаблоном. –

+0

Я думаю, что вы неправильно понимаете проблему, она связана с типом объекта, который содержит объекты, к которым вы пытаетесь получить доступ. DataTemplate в этом случае является ресурсом, а не объектом, который ** непосредственно ** будет частью визуального дерева объекта, внутри которого вы находитесь. Хотя вы действительно можете получить доступ к элементам, как вы говорите, как в этом примере: http://msdn.microsoft.com/en-us/library/bb613579(v=vs.110).aspx, вы просто неправильно используете, как вещи предназначались для использования. Мой ответ несколько раз затрагивает ваш вопрос, потому что вы указали ** no-code за *. – Aybe

+0

Как вы пытаетесь получить доступ к вещам, возможно, как в этом примере, потому что это FrameworkElement: http://msdn.microsoft.com/en-us/library/system.windows.visualstatemanager(v=vs.110).aspx но не для DataTemplate. Также см. Http://msdn.microsoft.com/en-us/library/system.windows.visualstate(v=vs.110).aspx. Я могу только порекомендовать посмотреть на Blend, чтобы увидеть, как MS создала визуальные состояния своих элементов управления: D – Aybe

Смежные вопросы