Laden...

[erledigt] Binding-Error vermeiden

Erstellt von Lector vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.941 Views
L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 13 Jahren
[erledigt] Binding-Error vermeiden

Hallo,

Ich habe in meiner GUI eine ListBox, welche mehrere Objekte anzeigt, die asyncron geladen werden. Die Objekte (ViewModels) sind immer vorhandeln. Allerdings werden sie erst leicht verzögert mit Daten bestückt damit die GUI nicht blockiert.

Jedes ListBox-Element in der GUI soll nun ein Vorschaubild anzeigen. Das mache ich mit einen Binding in einem DataTemplate:


<l:PictureViewer Source={Binding Picture.Thumbnail}/>

Im Prinzip funktioniert das auch wunderbar allerdings ist die Picture-Eigenschaft meines ViewModels ganz am Anfang noch null was zu einem Binding-Error in der Studio-Ausgabe führt. Dadurch dass sehr viele Items angezeigt werden vermute ich auch dass es die Performance verschlechtert. Nachdem die Vorschau geladen wurde wird alles richtig angezeigt. Ich möchte jedoch solche Binding-Errors vermeiden:

System.Windows.Data Error: 16 : Cannot get 'Thumbnail' value (type 'ImageSource') from 'Picture' (type 'PreviewSetViewModel'). BindingExpression:Path=Picture.Thumbnail; DataItem='PictureViewer' (Name='pictureViewer'); target element is 'PictureViewer' (Name='pictureViewer'); target property is 'NoTarget' (type 'Object') TargetInvocationException:'System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.

Das ist nicht der einzige Binding-Error in meinen Programm. Ich habe bereits an mehreren Stellen solche Szenarien an denen der Binding-Pfad nicht komplett aufgelöst werden kann da irgendein Element in der Kette null ist. Wobei null durchaus ein legaler Wert ist da bei mir alles asyncron geladen wird und erst angezeigt wird wenn es da ist.

Wie kann ich solche Fehler vermeiden?

U
1.688 Beiträge seit 2007
vor 13 Jahren

Wie kann ich solche Fehler vermeiden?

Vielleicht mit einem sinnvollen Startwert? Bspw. einem leeren Bild?

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 13 Jahren

Das möchte ich ungern machen. Es gibt auch Szenarien bei denen komplexere Typen zum Einsatz kommen die ich nicht einfach auf einen Dummy-Wert setzen kann.

Es muss doch möglich sein soetwas in der GUI zu handhaben. Schließlich ist es doch völlig legal dass ein Wert einmal null sein kann.

Wenn ich ein solches Szenario im Code habe schreibe ich normalerweise if(irgendwas != null) davor. Soetwas sollte im Binding auch möglich sein...

U
1.688 Beiträge seit 2007
vor 13 Jahren

Wenn ich ein solches Szenario im Code habe schreibe ich normalerweise if(irgendwas != null) davor. Soetwas sollte im Binding auch möglich sein...

Es gibt FallbackValue und TargetNullValue und Möglichkeiten der Exception-Behandlung (http://msdn.microsoft.com/de-de/library/ms613500.aspx). Vielleicht hilft davon etwas?

1.378 Beiträge seit 2006
vor 13 Jahren

Tritt der Fehler auch auf, wenn du das Picture als DataContext Bindest und dann nur mehr Thumbnail als ImageSource?

<l:PictureViewer DataContext="{Binding Picture}" Source="{Binding Thumbnail}"/>

Lg XXX

5.657 Beiträge seit 2006
vor 13 Jahren

Eine andere Möglichkeit, du könntest einen Converter erstellen, der den Wert null in ein Standard-Bitmap konvertiert. Z.B. könntest du damit auch ein "Bild nicht gefunden"-Bild zurückgeben, also mit einem roten Kreuz drauf wie im Internet Explorer.

Weeks of programming can save you hours of planning

6.862 Beiträge seit 2003
vor 13 Jahren

Hallo,

sowas würd ich eher mit dem PriorityBinding lösen. Nen Platzhalterbild aus den Ressourcen als am schnellsten verfügbare Quelle und dann die eigentlichen Nutzbilder als langsames Binding.

Baka wa shinanakya naoranai.

Mein XING Profil.

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 13 Jahren

Hallo,

Das mit dem Priority-Binding bzw. FallbackValue ist nicht nötig da im Falle eines Null-Werts auch Null übertragen wird. Für den Fall dass kein Bild vorhanden ist zeigt mein PictureViewer eine Default-Grafik an:


<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=DisplayedPicture.Picture}" Value="{x:Null}">
   <Setter Property="Template">
        <Setter.Value>
               <!--Hier steht eine Default-Grafik drin-->
        </Setter.Value>
   </Setter>
</DataTrigger>

Auch in diesem Beispiel gilt: Sowohl DisplayedPicture als auch Picture kann null sein. Und auch hier wird ein Binding-Error erzeugt wenn DisplayedPicture null ist weil die Binding-Klasse versucht auf die Picture-Eigenschaft zuzugreifen was zu einer NullReference-Exception führt. In diesem Fall wird vom Binding dann auch der Wert null zurückgeliefert. Das führt dazu dass der DataTrigger wie gewollt ausgelöst wird udn die Default-Grafik einblendet.

Der Vorschlag von xxxprod scheint zu keiner NullReferenceException zu führen. Offenbar prüft das Binding intern ob die Bindingsquelle null ist. Wenn jedoch beim Auflösen des Binding-Paths irgendwo ein Wert null ist wird ein Binding-Error ausgelöst. Nur wie gehe ich beim oben genannten DataTrigger vor?
Im Code würde ich einfach folgendes hinschreiben:


if(DisplayedPicture != null && DisplayedPicture.Picture != null)

Durch die logische Und-Verknüpfung würde der hintere Teil nur ausgeführt werden wenn der vordere Teil passt. Ich habe mal versucht einen MultiDataTrigger zu verwenden um auf beide Bedingungen zu prüfen. Allerdings erlaubt es die Condition-Klasse nicht auf null-Werte zu prüfen. Das funktioniert nur mit einem einfachen Trigger.

Wäre toll wenn mir jemand helfen könnte. Ich habe heute gelesen dass die Binding-Errors ziemlich viel Laufzeit kosten: http://www.wpftutorial.net/10PerformanceTips.html

5.299 Beiträge seit 2008
vor 13 Jahren

Wenn jedoch beim Auflösen des Binding-Paths irgendwo ein Wert null ist wird ein Binding-Error ausgelöst. Nur wie gehe ich beim oben genannten DataTrigger vor? Kann man da nicht einen zusätzlichen DataTrigger dran machen, der eben dann matcht?

Der frühe Apfel fängt den Wurm.

1.378 Beiträge seit 2006
vor 13 Jahren

So nebenbei kann ich dein Problem sowieso nicht nachvollziehen. Ich entwickel meine GUI's ausschließlich im XML Editor und nicht im Designer weswegen mir sowas nicht auffallen würde aber auch bei einem kleinen TestProjekt wo ich jetzt den Designer geöffnet habe, ist mir das Problem nicht untergekommen. Kannst du vielleicht ein kleines Beispielprojekt posten?

Lg XXX

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 13 Jahren

Habe gerade ein kleines Beispielprojekt gemacht und konnte den Fehler nicht reproduzieren. Ich habe dann in meinem Projekt nochmal genauer gedebuggt und festgestellt dass in meinem ViewModel der getter eine Exception wirft wenn der Wert noch nicht belegt ist. Ursache ist eine kleine Typumwandlung. Da ich an diesem Fehler wohl selbst Schuld war wiederrufe ich meine Theorie zur fehlerhaften Pfadauflösung von Bindings. Die funktionieren jetzt alle wunderbar auch wenn irgendwo im Binding-Path der Wert null vorkommt.

Trotzdem danke für die viele Vorschläge.