Hallo, tu mir im Moment gerade schwer. Ich verwende MVVM, das zuerst auch soweit funktionierte. Ich öffne in meiner WPF-Anwendung ein Window, in dem per XAML die Controls bestückt sind. Die Bindings an den DataContext sind dort auch schon gesetzt. Die Klasse mit den Feldern die an die Controls gebunden sind hat eben die Schnittstelle INotifyPropertyChanged, und die IDataErrorInfo für Fehlermeldung.
Nun ist es so, das ein paar Felder der Klasse die an die Controls gebunden werden, den Datentyp mit dem "?" versehen bekommen, damit sie "NULL" sein dürfen. Das mache ich deswegen so, damit der User neue gültige Werte eintragen kann. Ansonsten wären ja Vorgabedaten drin, und das möchte ich nicht, der User muss dort neue Daten eingeben. Und das kann ich nur feststellen, wenn zuvor nichts eingegeben war. Deswegen die NULL-Fahigkeit.
Ich prüfen dann bei der Datenübernahme (erfolgt durch Button-Click), ob die NULL-fähigen Variablen gesetzt sind, ansonsten kommt Fehlermeldung (IDataErrorInfo).
Damit das aber nicht sofort anspricht wenn das WPF-Window geöffnet wird, löse ich von diesen Controls das DataBinding und reagiere beim Button-Click der Datenübernahme mit der neuen Zuordnung der DataBindings für diese Controls. Es handelt sich um TextBoxen.
Hier mal der Code:
//// Binding der TextBoxen entfernen, damit keine Fehlermeldung kommt, wenn Window aufgebaut wird
BindingOperations.ClearBinding(tbx_Kantenradius, TextBox.TextProperty);
BindingOperations.ClearBinding(tbx_Winkel1, TextBox.TextProperty);
BindingOperations.ClearBinding(tbx_Breite1, TextBox.TextProperty);
Hier mal der Vorgang für die erste TextBox, wenn über Button die Eingabedaten übernommen werden sollen:
btn_Datenübernahme.Click += (o, eventArgs) =>
{
DatenUebenehmenAktiv = true;
//// Binding wieder an Feld "Kantenradius" herstellen
Binding binding = new Binding("Kantenradius");
binding.NotifyOnSourceUpdated = true;
binding.NotifyOnTargetUpdated = true;
//// Test für Explizite Aktualisierung
binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
binding.Mode = BindingMode.TwoWay;
binding.ValidatesOnDataErrors = true;
////binding.NotifyOnValidationError = true;
////binding.ValidatesOnExceptions = true;
//// Control wieder binden ==> Leider steht aber in tbx_Kantenradius.Text = "" drin, obwohl etwas eingegeben wurde.
tbx_Kantenradius.SetBinding(TextBox.TextProperty, binding);
//// Explizite Aktualisierung lostreten
tbx_Kantenradius.GetBindingExpression(TextBox.TextProperty).UpdateSource();
Wo mache ich den Fehler, das die Bindung nicht mehr funktioniert?
Hallo oehrle,
warum machst du das ganze Binding im Code Behind ?
das kannst Du alles auch per XAML machen, dein Click Event wäre auch besser mit einem Command realisiert.
auch das mit dem Nullable, ist mir noch nicht besonders klar und macht in meinen Augen keinen Sinn.
Viele Grüße
Lars
Ich verwende MVVM
Nein, das tust du nicht. Du hast immernoch CodeBehind bei dir. Dies wäre zu 99,999 % nicht vorhanden, wenn du MVVM richtig einsetzen würdest.
Ich stimme Lars Schmitt zu. Benutze Commands für deine Sachen und mach die bindings im XAML.
Weiter verstehe ich deine Frage nicht. Gibts überhaupt eine? Was ist denn nun das Problem?
Bitte beachte: [Hinweis] Wie poste ich richtig? Punkt 5
Gruss
Coffeebean
Microsoft MVP // Me // Blog // GitHub // @Egghead // All my talks // Speakerdeck
Sorry, Commands verwende ich hier nicht, wird auch noch ein Punkt werden. Zuerst aber das Problem mit dem BindingExpression. Das lösen der BindingExpresssion und erneute binden kann doch selbstverständlich immer wieder vorkommen. Habe das bei Galileo Computing gesehen (ziemlich unten Lissting 24.14 ist der Code):
Visual C# 2012 von Andreas Kühnel - Das umfassende Handbuch
Dort ist das Problem mit dem zufügen neuer Personen, bei mir ist das Problem, das manche Felder double-Werte enthalten die "nullfähig" sind, und deswegen mit "double ?" angelegt sind. Diese Felder müssen belegt werden und machen den Datensatz eindeutig (Pimarykeys), welche beim übernehmen der Daten über den Button sofoort in einer Datenbank das vorhandensein überprüft wird. Wenn ich bei den Feldern keine nullfähigkeit verwende, dann musss ich da sofort einen "Vorgabewert" einstellen oder es steht einfach "0" drin, was ich nicht möchte, und die Felder mit einer negativen Zahl belegen, das meine Prüfung erst mal so genehmigen würde geht nicht,weil die werte durchaus negativ sein können.
Meine Idee oder Vorgehen sieht so aus:
So, das nochmal zu meinem Problem. Habt ihr eine Idee an was es liegen könnte? UpdateSourceTrigger.Explizit setzen hatte ich auch schon bei einer TExtbox probiert. aber ohne Erfolg. Ich muss die Bindung irgenwie besser untersuchen können, was zuvor war und wie die neue Bindung ist.
Hallo oehrle,
auch nach deiner Erklärung, macht dein Vorgehen keinen Sinn.
Ich vermute mal, dass Du deine Klasse entweder im Loaded Event vom Window oder nachdem dein Fenster angezeigt wird, an den DataContext vom Window übergibst.
Der Rote Rahmen, kommt Da deine Klasse für die Validation des jeweiligen Properties ein Fehler zurück gibt.
Wenn Du also beim initialen Anzeigen keinen Fehler angezeigt haben möchtest, warum baust Du deine Validation nicht so um, dass beim erstmaligen Anzeigen kein Fehler zurück gegeben wird.
zb. mit einem
private bool _isInitialized;
und in der Validation prüfst Du dieses Field einfach mit ab
Viele Grüße
Lars
Ja, das Model wird im Konstruktor übergeben. Wie kann ich das mit dem ersten mal der Validierung einbauen? Muss ich das BindingExpression manipulieren?
Das Field wird erst nach der Initialisierung oder zb. im Loaded Event auf true gesetzt
Viele Grüße
Lars
Hallo, Problem vorerst gelöst. Habe was gutes dazu gefunden, und dazu noch die Idee mit der boolschen Property. Hier habe ich auch was gutes für einen Tooltip gefunden (mittlerer Bereich in der Website):
Nur dazu noch etwas, wie kann ich im code behind den Tooltip mit ToolTipService ändern? das habe ich krampfhaft versucht und jetzt tut mir alles weh 😉. Tipp??
Hallo oehrle,
auch dieses Problem kann ohne Code Behind realisiert werden
schau Dir doch mal die Thematik rund ums ErrorTemplate an
Validation.ErrorTemplate (angefügte Eigenschaft)
das ErrorTemplate kannst Du so anpassen, dass dein Fehler im ToolTip angezeigt wird.
Viele Grüße
Lars