2009-08-06 6 views
7

У меня самое страшное время, чтобы понять это: скажем, у меня есть две кнопки и три текстовых блока. Я хочу, чтобы любая кнопка запускает простой раскадровки на всех текстовых блоках. В настоящее время я пытаюсь определить общий стиль Textblock, содержащий Storyboard, а затем триггер появляется из любого нажатия кнопки. Это ближайший я пришел, но приложение падает при запуске ... Что я не так здесь:WPF - это должно быть проще, чем я это делаю

<Window.Resources> 

<Style TargetType="TextBlock" > 
    <Setter Property="Foreground" Value="Blue" /> 
    <Style.Resources> 
     <Storyboard x:Key="TextBlockOpacity" Storyboard.TargetProperty="Opacity"> 
      <DoubleAnimation From="0" To="1" /> 
     </Storyboard> 
    </Style.Resources>  
</Style> 

<Window.Triggers> 
    <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button"> 
     <BeginStoryboard Storyboard="{StaticResource TextBlockOpacity}"/> 
    </EventTrigger> 
</Window.Triggers> 


<Grid x:Name="LayoutRoot"> 
    <Button x:Name="button" HorizontalAlignment="Left" Margin="51,54,0,0" VerticalAlignment="Top" Width="96" Height="45" Content="Button"/> 

    <TextBlock x:Name="textBlock1" Margin="228,54,172,0" VerticalAlignment="Top" Height="45" FontSize="26.667" Text="TextBlock" TextWrapping="Wrap" /> 
    <TextBlock x:Name="textBlock2" Margin="228,103,172,0" VerticalAlignment="Top" Height="45" FontSize="26.667" Text="Hello" TextWrapping="Wrap"/> 
</Grid> 
+3

Я чувствую вашу боль –

+0

Не могли бы вы попытаться дать раскадровке имя, а затем, видя, если в код-за вы можете правильно Begin()... это? –

+0

Вы задаете тот же вопрос здесь: http://stackoverflow.com/questions/1238817/wpf-animation-question или вы ищете три кнопки для нажатия кнопки? – SergioL

ответ

4

Основанный на решении Xaml только для kek444, я представляю слегка улучшенную версию, которая не зависит от DataContext кнопки и может иметь несколько триггеров.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    x:Class="WpfApplication1.MainWindow" 
    x:Name="Window" 
    Title="MainWindow" 
    Width="640" Height="480"> 
    <Window.Resources> 
     <UIElement x:Key="OpacityCounter" Opacity="0"/> 
     <Style TargetType="TextBlock"> 
      <Setter Property="Opacity" Value="{Binding Source={StaticResource OpacityCounter}, Path=Opacity}" /> 
     </Style> 
     <Storyboard x:Key="OnClick1"> 
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.Target="{StaticResource OpacityCounter}" Storyboard.TargetProperty="(UIElement.Opacity)"> 
       <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/> 
       <SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/> 
      </DoubleAnimationUsingKeyFrames> 
     </Storyboard> 
    </Window.Resources> 
    <Window.Triggers> 
     <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button1"> 
      <BeginStoryboard Storyboard="{StaticResource OnClick1}"/> 
     </EventTrigger> 
     <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button2"> 
      <BeginStoryboard Storyboard="{StaticResource OnClick1}"/> 
     </EventTrigger> 
    </Window.Triggers> 

    <Grid x:Name="LayoutRoot"> 
     <StackPanel> 
      <StackPanel Orientation="Horizontal"> 
       <Button x:Name="button1" Width="131" Height="37" Content="Button 1" Margin="0,0,0,22"/> 
       <Button x:Name="button2" Width="131" Height="37" Content="Button 2" Margin="0,0,0,22"/> 
      </StackPanel> 
      <TextBlock x:Name="textBlock" Height="27" Text="TextBlock 1" TextWrapping="Wrap" /> 
      <TextBlock x:Name="textBlock1" Height="27" Text="TextBlock 2" TextWrapping="Wrap" /> 
      <TextBlock x:Name="textBlock2" Height="27" Text="TextBlock 3" TextWrapping="Wrap" /> 
      <TextBlock x:Name="textBlock3" Height="27" Text="TextBlock 4" TextWrapping="Wrap" /> 
     </StackPanel> 
    </Grid> 
</Window> 

Чтобы использовать ListBox в качестве пускового механизма (если у вас есть ListBox с именем «listbox1» где-нибудь, добавьте следующие строки в Window.Triggers:

<EventTrigger RoutedEvent="Selector.SelectionChanged" SourceName="listbox1"> 
    <BeginStoryboard Storyboard="{StaticResource OnClick1}"/> 
</EventTrigger> 

или провоцировать конкретный ListBoxItem, вам нужно (где item1 является именованным ListBoxItem):

<EventTrigger RoutedEvent="ListBoxItem.Selected" SourceName="item1"> 
    <BeginStoryboard Storyboard="{StaticResource OnClick1}"/> 
</EventTrigger> 
+0

Это очень приятно! Я хотел избежать создания UIElements в качестве ресурсов, но люди должны идти с тем, что им подходит. Однако использование этого подхода улучшилось в связи с тем, что он не использует DataContext и поддерживает несколько триггеров, будет несколько несправедливым. Использование ресурса UIElement над DataContext - это только вопрос личных предпочтений; и оба решения поддерживают множество триггеров. В противном случае, хорошая работа. ;) –

+0

Хорошо ... теперь, чтобы сделать его немного сложнее ... Я не пытаюсь запускать кнопку, но исключение ListBoxItem из ListBox, находящегося внутри StackPanel, внутри границы, внутри сетка в главном окне. Я пробовал это в течение нескольких часов, но не могу получить правильный RoutedEvent ... все события ListBoxItem дают ошибку о закрытии класса или что-то в этом роде ... – LSTayon

+0

Я только назвал его улучшенным, так как он не требует отдельного DataContext для каждого Механизм триггера (т.е. кнопки). Я не хотел обидеться. – SergioL

6

Если кнопка «посвящаю» изменению opacity, вы можете использовать его DataContext и анимировать его. Тогда просто связать свои элементы Opacity к DataContext:

(Я также реструктурировать свой XAML чуть позже)

<Window x:Class="SomeNamespace.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:System="clr-namespace:System;assembly=mscorlib" 
    Title="Window1" Height="300" Width="300"> 
    <Window.Resources>   
     <Storyboard x:Key="TextBlockOpacity" Storyboard.TargetName="button1" Storyboard.TargetProperty="DataContext" > 
      <DoubleAnimation From="0.1" To="1"/> 
     </Storyboard>   
     <Style TargetType="TextBlock" > 
      <Setter Property="Foreground" Value="Blue" /> 
      <Setter Property="Background" Value="LightGray" /> 
      <Setter Property="FontSize" Value="26.667" /> 
      <Setter Property="TextWrapping" Value="Wrap" /> 
      <Setter Property="Height" Value="45" />    
      <Setter Property="Opacity" Value="{Binding ElementName=button1, Path=DataContext}"/> 
     </Style> 
    </Window.Resources> 

    <Window.Triggers> 
     <EventTrigger RoutedEvent="ButtonBase.Click"> 
      <BeginStoryboard Storyboard="{StaticResource TextBlockOpacity}" > 
      </BeginStoryboard> 
     </EventTrigger> 

     <EventTrigger RoutedEvent="ListBox.SelectionChanged"> 
      <BeginStoryboard Storyboard="{StaticResource TextBlockOpacity}" > 
      </BeginStoryboard> 
     </EventTrigger> 
    </Window.Triggers> 

    <Grid x:Name="LayoutRoot"> 
     <Button x:Name="button1" HorizontalAlignment="Left" Margin="51,54,0,0" VerticalAlignment="Top" Width="96" Height="45" Content="Button"> 
      <Button.DataContext> 
       <System:Double>0</System:Double> 
      </Button.DataContext> 
     </Button> 

     <Button x:Name="button2" HorizontalAlignment="Right" Margin="0,54,29,0" VerticalAlignment="Top" Width="96" Height="45" Content="Button"/> 

     <ListBox x:Name="listBox1" Height="50" VerticalAlignment="Top"> 
      <ListBox.Items> 
       <System:String>Text1</System:String> 
       <System:String>Text2</System:String> 
      </ListBox.Items> 
     </ListBox> 

     <TextBlock x:Name="textBlock1" Margin="51,114,61,0" Text="TextBlock" Height="45" VerticalAlignment="Top" Width="166" /> 
     <TextBlock x:Name="textBlock2" Margin="51,0,74,42" Text="Hello" Height="45" Width="153" VerticalAlignment="Bottom" /> 
    </Grid> 
</Window> 

Также обратите внимание на одну вещь - это подход к использованию, если вы хотите, чтобы минимизировать код, и сделать все это в xaml. Ваш подход будет соответствовать Opacity всего окна. Вот почему в приведенном выше коде TextBlocks привязаны к кнопке DataContext, которая сама анимируется.

Это, конечно, возможно без привязки к общему значению (DataContext), но тогда вам нужно повторить анимацию X (потому что вам нужно установить X TargetNames). Этот подход выше легко расширяем и обслуживаем.

EDIT

Добавлен другая кнопка и ListBox для разнообразия :)

0

В вашем примере вы определяете раскадровку внутри стиля как ресурс, но вы пытаетесь получить доступ к нему, как ресурс окна. Попробуйте переместить объявление раскадровки в Window.Resources, а затем ссылайтесь на раскадровку в стиле.

Я не знаю сразу, если он будет делать то, что вы хотите, но я бы начал там.

+0

Хорошо, я бегал вокруг этого навсегда, но то, что он сводит, - это NameScope.У меня есть ListBox, который я хочу вызвать Animation на TextBlocks, но они не находятся в одном NameScope, поэтому, если я поместил StoryBoard в Windows.Resources, тогда триггер ListBox может найти StoryBoard, но StoryBoard не сможет найти TargetName текстовых блоков. Если я поместил StoryBoard в Grid.Resource (где есть текстовые блоки), тогда триггер смены ListBox не может найти StoryBoard. Есть ли какое-то соглашение об именах, которое я могу использовать для перекрестных меток? Ugh! Благодаря! – LSTayon

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