none
Storyboard von C# nach XAML, Binding verursacht AccessViolationException RRS feed

  • Frage

  • Hallo zusammen,

    ich habe in meinem Projekt ein Grid mit 3 ColumnDefinitions.

    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="column0" Width="*"/>
        <ColumnDefinition x:Name="column1" Width="Auto"/>
        <ColumnDefinition x:Name="column2" Width="Auto"/>
    </Grid.ColumnDefinitions>

    In column2 ist ein weiteres Grid. Dieses Grid soll als Sidebar fungieren und ein- und ausblendbar sein.
    Genau da liegt nun das Problem.
    Um die Sidebar auszublenden könnte ich zwei Dinge tun: a) Die Breite der ColumnDefinition verändern b) Die Breite des Grid verändern.

    Ich habe mich für b) entschieden.
    Nun wollte ich ein Storyboard zusammenbauen, was genau dies tut. Dabei habe ich mir gedacht, dass ich einfach eine DoubleAnimation nehme und den From Wert auf Grid.ActualWidth binde. Als To Wert habe ich 0 eingesetzt.

    <Storyboard x:Key="content2Collapse">
        <DoubleAnimation Duration="0:0:0.3"
                         Storyboard.TargetName="content2"
                         Storyboard.TargetProperty="Width"
                         From="{Binding ElementName=content2, Path=ActualWidth}"
                         To="0"
                         EnableDependentAnimation="True" />
    </Storyboard>

    Bei einem Button ClickEvent lade ich dieses Storyboard aus den Resources (Storyboard befindet sich in Page.Resources) und starte es:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Storyboard sb = Resources["content2Collapse"] as Storyboard;
        sb.Begin();
    }

    (Ich gehe hierbei von aus, dass sb nicht null ist oder sonst eine Exception geschmissen wird, im Production Code sähe das hier natürlich etwas anders aus.)

    Wenn ich das Ganze ausführe, dann bekomme ich nur eine AccessViolationException.
    Daraufhin habe ich die Bindung weggelassen und einen festen Wert 100 eingetragen und siehe da, es funktioniert.

    Auf Stackoverflow wurde mir eine Lösung vorgeschlagen, dass ich das Ganze in C# mache statt in XAML.

    var sb = new Storyboard();
    var anim = new DoubleAnimation()
    {
        Duration = TimeSpan.FromMilliseconds(1000),
        From = content2.ActualWidth,
        To = 0,
        EnableDependentAnimation = true
    };
    
    Storyboard.SetTarget(anim, content2);
    Storyboard.SetTargetProperty(anim, "Width");
    sb.Children.Add(anim);
    
    sb.Begin();

    Das funktioniert auch alles ganz toll, aber die Ursache für den Fehler geh ich damit nur aus dem Weg.
    Ich würde gerne so weit es geht die GUI in XAML machen und dazu gehört für mich auch sowas.
    Ich möchte nicht in meinem Code Horden von Storyboards etc. rumfliegen haben. In XAML ist es einfach besser verständlich.

    Ich würde nun gerne wissen, ob es möglich ist, den C# Code in XAML Code umzuwandeln und vorallem würde ich gerne wissen, warum mein Versuch nicht funktioniert.
    Grid.ActualWidth gibt ja einen double zurück, von daher ist der Fehler für mich nicht ganz ersichtlich.

    Ich bedanke mich schonmal im Vorraus für alle die mir helfen können :)

    Freitag, 3. Januar 2014 14:33

Antworten

  • Hallo,
    das Problem besteht darin, wie XAML die einzelnen Elemente verarbeitet.

    Das Storyboard ist eine Resource von normalerweise statisch, also nach dem kompilierne nicht veränderbar. Die Bindung dagegen hängt vo andeen Faktoren ab, beispielsweise ob das Zielelement überhaupt gefunden wird. Der Compiler lässt noch alles durch gehen, beim ausführen scheitert es dann aber.

    Ohne es nochmal getestet zu haben, versuche mal die From-Eigenschaft weg zu lassen. Denn von x auf 0 funktionierte unter WPF. Spätestetns beim wieder ausklappen brauchst du aber sowieso feste Werte, da ActualWidth nicht mehr gültig ist.

    Eventuell kannst du es doch nochmal versuchen die Breite der ganzen Spalte zu ändern. Ob das aber unter Windows 8 funktioniert kann ich dir nicht sagen. Unter WPF würde es gehen.

    Wenn du häufiger dynamische Storyboards erstellen musst, kann es ielleicht hilfreich sein eine Klasse mit statischen Erstell-Methoden zu implementieren. Dadurch kannst du dir sicher einige Codezeilen sparren.
    Du kannst aber auch das Storyboard aus den Resourcen laden und die dynamischen Werte erst im Code setzen und danach das Storyboard ausführen.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert Torben Jonas Samstag, 4. Januar 2014 20:34
    Freitag, 3. Januar 2014 14:48