Visual Studio Lightswitch 2010 – Einen Search Screen bei Änderungen automatisch aktualisieren.

Eine Applikation mit Visual Studio Lightswitch zu machen, ist eine spaßige Angelegenheit, man kommt schnell voran weil man sich nicht um die Infrastruktur der Applikation kümmern muss, aber trotzdem eine schöne, mehrschichtige Anwendung bekommt. Der Anfänger kann leicht einfache Use-Cases umsetzen, die Fortgeschrittenen können sich viel anpassen und auch erweitern.

Ein kleines Manko, welches mir bei der Umsetzung einer Anwendung aufgefallen ist (bzw. deren Anwender):

Man hat eine Listenansicht (SearchScreen) die eine bestimmte Menge an Datensätzen anzeigt. Fügt man nun in einen anderen Bildschirm (z.B. einer Detailansicht (Details Screen) oder einer Maske zum Hinzufügen (Add New Screen)) einen neuen Datensatz zu dieser Menge hinzu, schließt den Bildschirm und kehrt wieder zur Listenansicht zurück, so stellt man fest, dass der neue Datensatz nicht angezeigt wird, erst nachdem man auf die standardmäßig vorhandene Schaltfläche „Aktualisieren“ drückt, erscheinen die neuen Daten.

Ich möchte hier einen Weg vorstellen wie das auch automatisch funktioniert, erfunden habe es aber nicht ich, sondern Sheel Shah vom Visual Studio Lightswitch Team. Den Originalbeitrag findet ihr hier. Die Idee daran ist es, das ganze über einen eigenen EventHandler abzuhandeln. Das heisst, die Applikation bekommt einen Eventhandler verpasst, der Search Screen registriert sich für alle Events dieses Handlers. Wird nun in einem anderen Screen ein Datensatz hinzugefügt, oder verändert, so wird beim speichern dieses Event ausgelöst. Der Search Screen bekommt das Event mitgeteilt und kann damit die Datenquelle aktualiseren. Hier greifen dann die normalen Lightswitch-Mechanismen und die GUI wird aktualisiert.

Der einzige zu Sheel’s Beitrag ist, dass ich bei mir einen Search Screen aktualisiere, und kein einzelnes Steuerelement.

Ausgangslage, die Tabelle mit den Namen „Kunden“:

Tabelle Kunden - Übersicht
Tabelle Kunden

Ausgehend von dieser Tabelle gibt es zum Einem den Search Screen „Kunden“ sowie die Eingabemaske zum Anlegen eines neuen Kunden „Neuer Kunde“

Beginnen wir nur nun mit den Adaptionen an der Eingabemaske „Neuer Kunde“, die erste Änderung muss im Code an der Stelle „KundeNeu_CanRun“ vorgenommen werden.

Bearbeiten von "KundeNeu_CanRun"
Bearbeiten von „KundeNeu_CanRun“

Folgende Anpassungen sind dort zu machen: Anlegen eines Delegaten und eines Eventhandlers, sowie einer Methode die das Event „feuert“.

public delegate void RecordAdded();
public event RecordAdded CustomerAdded;

public void RaiseCustomerAdded() {
  if (this.Details.Dispatcher.CheckAccess()) {
    CustomerAdded();
  } else {
    this.Details.Dispatcher.BeginInvoke(delegate() { CustomerAdded(); });
  }
}

Wir bleiben im Detailformular, jetzt wird etwas Code zum Ereignis „KundeNeu_Saved“ hinzugefügt, die Ergänzung ist einfach, es wird einfach das Event „abgefeuert“:

partial void KundeNeu_Saved() {
  this.Close(false);
  Application.RaiseCustomerAdded();
}

So, wir haben nun den Event-Handler definiert, wir haben dafür gesorgt, dass das Event auch ausgelöst wird, nun brauchen wir noch jemanden, der sich für diese Events auch interessiert, und das ist nun das Suchformular „Kunden“. In dieser Ansicht gibt es oben im Ribbon eine Schaltfläche, mit der man einen Kunden neu anlegen kann – hier registriert man sich für das Event:

partial void NewCustomer_Execute() {
  Application.CustomerAdded += new Application.RecordAdded(CustomerAdded);
  Application.ShowKundeNeu();
}

Das ist die Methode, die dann aufgerufen wird, es wird einfach ein Refresh der Datenquelle vorgenommen, die dem Search Screen zugrundeliegt. Der Rest wird dann vom internen Eventsystem abgehandelt, und die GUI initialisiert.

private void CustomerAdded() {
  this.Details.Dispatcher.BeginInvoke(() => this.CustomersByName.Refresh());
}

Zu guterletzt sollte man auch noch aufräumen, ich denke aber, dass diese Lösung hier noch nicht unbedingt sauber ist, das muss ich mir bei Gelegenheit noch genauer ansehen, wenn der Search Screen geschlossen wird, wird der der Eventhandler wieder „deregistriert“:

partial void Kunden_Closing(ref bool cancel) {
  Application.CustomerAdded -= new Application.RecordAdded(CustomerAdded);
}

Kurzes Fazit: Die Implementierung ist doch ein wenig aufwändig, vor allem wenn man die Mechanismen des Event-Handlings noch nicht so gut versteht, aber es ist eine saubere und zuverlässige Umsetzung.