2009-07-13 16 views
6

Jest to sytuacja, która często pojawia się:Jaki jest najlepszy sposób rozpoczęcia animacji po zmianie wartości wiązania?

W widoku masz kontrolę powiązaną z właściwością ViewModel (wspieraną przez INotifyPropertyChanged). Na przykład:

<TextBlock Text="{Binding Path=Subtotal}"/> 

Po zmianie właściwości należy zwrócić uwagę użytkownika na pewne animacje. Jak mogę wykorzystać fakt, że widok jest już podłączony do powiadomienia i uniknąć tworzenia znacznej ilości dodatkowego kodu (lub przynajmniej utworzyć go raz i ponownie użyć). Wyzwalacze danych są prawdopodobnie najlepszym wyborem, ale nie wiem, jak je wywołać w przypadku jakiejkolwiek zmiany wartości w stosunku do konkretnej wartości.

następujące opcje przychodzą na myśl:

  • podbicie dodatkowym wydarzeniem w ViewModel, zapisz w widoku kodu źródłowego.
  • utworzyć datatrigger związany z właściwością wspomnianą za pomocą konwertera, który zwróci wartość true, jeśli wartość się zmienia.
  • utworzyć datatrigger związany z nową właściwością boolean w ViewModel, który jest używany do "sygnalizowania" zmiany.
  • Utwórz zachowanie dołączone do formantu, który zasubskrybuje zmianę właściwości zależności obiektu sterującego i rozpocznie animację.

Którego lubisz/używasz? Czy przegapiłem jakieś opcje?

P.S. Byłoby miło (ale nie krytycznie), gdyby rozwiązanie dało możliwość rozpoczęcia animacji jako pierwszej i odzwierciedlenia zmiany wartości po jej zakończeniu.

Odpowiedz

3

OK, oto, do czego doszedłem po kilku eksperymentach.

Utworzono wyzwalacz Expression Blend 3 z właściwością zależności (nazwałem to Subskrypcja). Wiążę subskrypcję na tę samą wartość, że mój TextBlock jest związany i to wyzwalacz jest dołączony do ControlStoryboardAction od Expression Blend 3.

Oto spust:

public class DataTriggerPlus : TriggerBase<DependencyObject> 
{ 
    public static readonly DependencyProperty SubscriptionProperty = 
     DependencyProperty.Register("Subscription", 
      typeof(string), 
      typeof(DataTriggerPlus), 
      new FrameworkPropertyMetadata("", 
       new PropertyChangedCallback(OnSubscriptionChanged))); 

    public string Subscription 
    { 
     get { return (string)GetValue(SubscriptionProperty); } 
     set { SetValue(SubscriptionProperty, value); } 
    } 

    private static void OnSubscriptionChanged(DependencyObject d, 
     DependencyPropertyChangedEventArgs e) 
    { 
     ((DataTriggerPlus)d).InvokeActions(null); 
    } 
} 

Oto jak to jest dołączony do serii ujęć :

<TextBlock x:Name="textBlock" Text="{Binding TestProp}" Background="White"> 
    <i:Interaction.Triggers> 
     <local:DataTriggerPlus Subscription="{Binding TestProp}"> 
      <im:ControlStoryboardAction 
       Storyboard="{StaticResource Storyboard1}"/> 
     </local:DataTriggerPlus> 
    </i:Interaction.Triggers> 
</TextBlock> 

Bardzo lubię to podejście, świetna robota Mieszaj 3 projektantów!

Edit: odpowiadając komentarz Drew ...

Tak, to statki z mieszanki. Możesz po prostu włączyć Microsoft.Expression.Interactions.dll i System.Windows.Interactivity do swojego projektu.

I tak, to jest gadatliwe (zapytałem, czy ktoś wymyślił dobry sposób na stosowanie zachowań za pomocą stylów in this question), ale jest też korzyść z elastyczności. Na przykład można nie tylko uruchomić scenorys, ale także przełączyć stan lub wykonać inną akcję z tego samego wyzwalacza.

+1

Skąd pochodzi ""? Zgaduję, że jest dostarczany z Blendem. Czy jest on dostępny dla użytkowników, którzy nie są w stanie mieszać? Chcę osiągnąć to samo w moim kodzie, ale mam nadzieję, że istnieje rozwiązanie, które jest mniej szczegółowe, ponieważ mam wiele takich przypadków, które tego wymagają. Może to możliwe dzięki Style ... –

2

Można utworzyć wyzwalacz, który uruchomi animację.

coś takiego:

<Style> 
    <Style.Triggers> 
     <Trigger 
      Property="ViewModelProperty" 
      Value="True"> 
      <Trigger.EnterActions> 
       <BeginStoryboard Storyboard="YourStoryBoard" /> 
      </Trigger.EnterActions> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

Co do kwestii wystawiania ustawiając wartość po ukończeniu animacji, jest to trochę uciążliwe. O ile wiem, musisz użyć ukończonego wydarzenia w scenorysie, to wymaga kodu, który jest czymś, czego chcesz uniknąć w MVVM.

Próbowałem używać EventTriggers do powiązania z zakończonymi zdarzeniami, ale to również wprowadza pewne komplikacje. Aby uzyskać więcej informacji, patrz here.

+0

Co jeszcze, jeśli właściwość nie jest typu boolowskiego lub zestawu opcji, ale dowolny ciąg lub liczba? –

+0

Następnie należy użyć ValueConverter. To samo rozwiązanie, tylko z wartościąConverter –

+0

W jaki sposób konwerter wartości wiedziałby, że wartość się zmieniła, chyba że stworzyłeś konwerter wartości dla każdego pojedynczego wiązania? –

Powiązane problemy