Frage

Ich habe erstellt eine angefügte Abhängigkeitseigenschaft für Storyboards, mit der Absicht, damit, mich zu rufen Sie eine Methode auf meinem ViewModel, wenn Sie ein Storyboard Abgeschlossen-Ereignis ausgelöst wird:

public static class StoryboardExtensions
{
    public static ICommand GetCompletedCommand(DependencyObject target)
    {
        return (ICommand)target.GetValue(CompletedCommandProperty);
    }

    public static void SetCompletedCommand(DependencyObject target, ICommand value)
    {
        target.SetValue(CompletedCommandProperty, value);
    }

    public static readonly DependencyProperty CompletedCommandProperty =
        DependencyProperty.RegisterAttached(
            "CompletedCommand",
            typeof(ICommand),
            typeof(StoryboardExtensions),
            new FrameworkPropertyMetadata(null, OnCompletedCommandChanged));

    static void OnCompletedCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        Storyboard storyboard = target as Storyboard;
        if (storyboard == null) throw new InvalidOperationException("This behavior can be attached to Storyboard item only.");
        storyboard.Completed += new EventHandler(OnStoryboardCompleted);
    }

    static void OnStoryboardCompleted(object sender, EventArgs e)
    {                        
        Storyboard item = ... // snip
        ICommand command = GetCompletedCommand(item);
        command.Execute(null);
    }
}

dann versuche ich, es in XAML, mit einer Verbindlichen syntax:

<Grid>
    <Grid.Resources>
        <Storyboard x:Key="myStoryboard" my:StoryboardExtensions.CompletedCommand="{Binding AnimationCompleted}">
            <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:5" />
        </Storyboard>

        <Style x:Key="myStyle" TargetType="{x:Type Label}">
            <Style.Triggers>
                <DataTrigger 
                 Binding="{Binding Path=QuestionState}" Value="Correct">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard Storyboard="{StaticResource myStoryboard}" />
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>

    </Grid.Resources>
    <Label x:Name="labelHello" Grid.Row="0" Style="{StaticResource myStyle}">Hello</Label>
</Grid>

Dies schlägt mit der folgenden Ausnahme:

System.Windows.Markup.XamlParseException occurred Message="Cannot konvertieren Sie den Wert in das Attribut 'Style' in Objekt des Typs 'System.Windows.Style'.Nicht einfrieren können dieses Storyboard, timeline-Struktur für die Verwendung in threads.Error in object 'labelHello' in der markup-Datei 'TestWpfApp;component/window1.xaml'

Gibt es eine Möglichkeit, um die Bindung syntax arbeiten mit einem angeschlossenen ICommand-Eigenschaft für ein Storyboard?

War es hilfreich?

Lösung 3

Um dieses problem zu umgehen, habe ich eine Reihe von Angefügten Eigenschaften, namens Storyboard Helfer (source code hier).Ich gab den Versuch auf, befestigen Sie Sie in das Storyboard selbst, und nun befestigen Sie an jeder (beliebige) - framework-element zu nennen, eine ICommand auf meinem ViewModel, wenn das storyboard ist abgeschlossen, ebenso wie die Bindung an ein bestimmtes Ereignis in meinem ViewModel zu starten Sie das Storyboard.Eine Dritte angefügte Eigenschaft gibt an, das Storyboard, wir sind Umgang mit:

<FrameworkElement
   my:StoryboardHelpers.Storyboard="{StaticResource rightAnswerAnimation}"
   my:StoryboardHelpers.Completed="{Binding CompletedCommand}"
   my:StoryboardHelpers.BeginEvent="{Binding StartCorrectAnswer}" />

Andere Tipps

Dies ist etwas von design.Wenn Sie eine freezable-Objekt, das in einem Stil, der Stil wird eingefroren, um einen cross-thread-Zugriff.Aber Sie verbindlich ist im wesentlichen ein Ausdruck, der bedeutet, es kann nicht eingefroren werden, wie die Datenbindung ist single threaded.

Wenn Sie brauchen, um dies zu tun, legen Sie die trigger außerhalb der Stil unter einem Rahmen-element, statt in einem Stil.Sie können dies tun, in Ihrem Raster.Trigger-Abschnitt.Dies gilt saugen ein wenig, als Ihr Stil ist nicht mehr vollständig und man verdoppeln müssen, der ausgelöst wurde, aber es ist "by design" - Funktion in WPF.

Die vollständige Antwort auf Soziale MSDN Foren hier.

Sie können eine neue Freezable-abgeleitete Klasse zu starten, ein storyboard als shim.Binden Sie eine Eigenschaft auf, dass shim-Objekt, um die storyboard-Namen.So, Sie nicht haben, um doppelten Trigger oder speichern Sie Sie außerhalb der Stil.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top