2009-08-06 15 views
7

Mam najszczęśliwszy czas na zastanowienie się: powiedzmy, że mam dwa przyciski i trzy blokady tekstu. Chcę, aby którykolwiek z przycisków uruchamiał prosty Storyboard na ALL TextBlocks. Obecnie próbuję zdefiniować ogólny styl Textblock zawierający Storyboard, a następnie wyzwalacz pochodzi z dowolnego kliknięcia przycisku. Jest to najbliżej Doszedłem jednak awarii aplikacji na starcie ... Co ja nie źle tutaj:WPF - to musi być łatwiejsze niż robię to

<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

czuję ból –

+0

można spróbować dając scenorysie nazwę, a następnie sprawdzając, czy w kodu źródłowego można prawidłowo Begin()... to? –

+0

Czy zadajesz to samo pytanie: http://stackoverflow.com/questions/1238817/wpf-animation-question czy szukasz 2-przyciskowych wyzwalaczy kliknięć? – SergioL

Odpowiedz

4

Na podstawie rozwiązania Xaml tylko kek444 przedstawiam nieco ulepszoną wersję, która nie opiera się na DataContext przycisku i może mieć wiele wyzwalaczy.

<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> 

Aby używać ListBox jako mechanizmu spustowego (pod warunkiem, że masz ListBox o nazwie „listbox1” gdzieś, dodać następujące Window.Triggers:

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

lub wywołać konkretną ListBoxItem, trzeba (gdzie item1 jest nazwany ListBoxItem):

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

To całkiem miłe! Chciałem uniknąć tworzenia UIElements jako zasobów, ale ludzie powinni pójść z tym, co im bardziej odpowiada. Jednak nazywanie tego podejścia poprawiło się w oparciu o fakt, że nie korzysta on z DataContext i obsługuje wiele wyzwalaczy, co byłoby niesprawiedliwe. Używanie zasobu UIElement przez DataContext jest tylko kwestią osobistych preferencji; i oba rozwiązania obsługują wiele wyzwalaczy. W przeciwnym razie, miła praca. ;) –

+0

Ok ... teraz, aby uczynić go nieco bardziej skomplikowanym ... Tak naprawdę nie próbuję wyzwalać przycisku, ale poza zmianą ListBoxItem z ListBox, który jest wewnątrz StackPanel, wewnątrz obramowania, wewnątrz siatka w głównym oknie. Próbuję to od wielu godzin, ale nie mogę uzyskać poprawne RoutedEvent ... wszystkie zdarzenia ListBoxItem dają błąd o zamknięciu klasy lub coś ... – LSTayon

+0

I tylko o nazwie to ulepszone, ponieważ nie wymaga oddzielnego DataContext dla każdego Mechanizm spustowy (tj. Przyciski). Nie chciałem urazić. – SergioL

6

Jeśli „poświęcić” przycisk do zmieniania nieprzezroczystość, możesz wykorzystać jego DataContext i ożywić. Wtedy po prostu powiązać elementy Opacity do DataContext:

(Ja również refactored swoją XAML nieco)

<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> 

Należy również pamiętać o jednej rzeczy - jest to podejście do wykorzystania, jeśli chcesz, aby zminimalizować kod, i sprawiają, że wszystko dzieje się w Xaml. Twoje podejście pomściłoby Opacity całego okna. Dlatego w powyższym kodzie TextBlocks wiąże się z DataContext przycisku, który sam jest animowany.

Jest to oczywiście wykonalne bez wiązania do wspólnej wartości (DataContext), ale musisz powtórzyć animacje X (ponieważ musisz ustawić X TargetNames). Powyższe podejście jest łatwiejsze do rozszerzenia i konserwacji.

EDIT

Dodany inny przycisk i ListBox dla odmiany :)

0

W swojej próby, definiowanej serii ujęć wewnątrz Style jako zasób, ale potem próbujesz uzyskać do niego dostęp za Zasób Window. Spróbuj przenieść deklarację Storyboard do Window.Resources, a następnie odwołaj się do Storyboard w stylu.

Nie wiem od razu, czy zrobi to, co chcesz, ale zacznę od tego.

+0

W porządku, biegałem od tego wieczora, ale to, do czego się odnosi, to NameScope.Mam ListBox, który chcę wywołać Animation na TextBlocks, ale nie są one w tym samym NameScope, więc jeśli umieścić StoryBoard w Windows.Resources, to wyzwalacz ListBox może znaleźć StoryBoard, ale StoryBoard nie może znaleźć TargetName of TextBlocks. Jeśli umieściłem StoryBoard w Grid.Resource (gdzie są TextBlocks), to wyzwalacz zmian ListBox nie może odnaleźć StoryBoard. Czy jest jakaś konwencja nazewnictwa, której mogę użyć do przekroczenia Namescopes? Uch! Dzięki! – LSTayon

Powiązane problemy