Woher kommen die Daten?

Eigentlich war es eine einfache Anforderung. Das ausgewählte Item einer Datenliste in SharePoint soll in einem weiteren WebPart auf der Seite dargestellt werden. Die beiden WebParts werden über eine WebPart-Verbindung zusammen gefügt. Eine klassische n:1 Darstellung. Aber wenn es schon so schön dargestellt wird, wollen wir auch gleich Änderungen am Item durchführen können, also ein Update auf das Item ausführen.

Die Darstellung ist schnell gelöst. Das Detail-WebPart fungiert als ConnectionConsumer für ein WebPart welches IWebPartRow implementiert. In der Connection Funktion wird ein Callback auf einen eigene Funktion erstellt und an den Datenprovider übergeben. An die Callback wird ein object mit den Daten übergeben. Dieses Object ist im Falle eines simplen SharePoint Listen WebParts ein DataRowView.

   1:          [ConnectionConsumer("ZeileDetail")]
   2:          public void GetConnectionInterface(IWebPartRow providerPart)
   3:          {
   4:              RowCallback callback = new RowCallback(ReceiveRow);
   5:              
   6:              providerPart.GetRowData(callback);
   7:          }
   8:   
   9:          public void ReceiveRow(object row)
  10:          {
  11:              EnsureChildControls();
  12:              DataRowView rv = (DataRowView)row;
  13:           
  14:              txtTextbox1.Text = rv["Title"].ToString();
  15:          }

Um die Daten zurück schreiben zu können, ist ein SharePoint Item vom Typ SPItem notwendig. Über den DataRowView stehen aber leider nur die Feldinhalte zur Verfügung und kein SPItem. Aber zumindest wird die Id des Items im DataRowView übergeben. Nur leider ist im DataRowView kein Hinweis auf die Liste an die dieses WebPart vom Benutzer gebunden wurde.

Woher bekomme ich die Referenz auf die Liste?

Das übergebene Object in der ConnectionConsumer-Methode,  welches ein IWebPartRow implementiert, ist das Senderwebpart. Binde ich das Detailwebpart an eine SharePoint-Liste so wird hier ein WebPart vom Typ  XsltListViewWebPart übergeben. Und dieses enthält einen Verweis auf das zugrundliegende SPList Element. (Dies gilt für SharePoint 2010 genauso wie für SharePoint 2013)

Die erweiterten Funktionen mit SPList Objekt und Item Id:

   1:          [ConnectionConsumer("ZeileDetail")]
   2:          public void GetConnectionInterface(IWebPartRow providerPart)
   3:          {
   4:              RowCallback callback = new RowCallback(ReceiveRow);
   5:              XsltListViewWebPart wp = (XsltListViewWebPart)providerPart;
   6:   
   7:              SPList liste = wp.View.ParentList;
   8:              ViewState["ListId"] = liste.ID.ToString();
   9:   
  10:              providerPart.GetRowData(callback);
  11:          }
  12:   
  13:          public void ReceiveRow(object row)
  14:          {
  15:              EnsureChildControls();
  16:              DataRowView rv = (DataRowView)row;
  17:   
  18:              int ItemId = int.Parse(rv["ID"].ToString());
  19:              ViewState["ItemId"] = ItemId.ToString();
  20:   
  21:              txtTextbox1.Text = rv["Title"].ToString();
  22:          }

Wie im Source-code sicher aufgefallen ist, es wird die ListID und die Item ID im Viewstate des WebParts gespeichert. Das hat mit dem Timing des Updates zu tun. Der eigentliche Code mit dem Datenupdate steht im Eventhandler des Button-Click Events. Würde das DatenUpdate erst am Ende eines PostBack-Zyklus stattfinden, wie z.B. im ReceiveRow, zeigt das ListenWebpart nicht die aktualisierten Daten sondern “hinkt” einem Postback-Zyklus hinterher.

Zum Zeitpunkt des Aufrufes des Click-Events wurden der ConnectionConsumer und die Callback-Funktion aber noch nicht aufgerufen und somit sind weder ItemId noch Liste bekannt. Daher speichere ich die beiden Werte zunächst im ViewState, um im Button-Click darauf zugreifen zu können.

   1:          void bt_Click(object sender, EventArgs e)
   2:          {
   3:              EnsureChildControls();
   4:              if (ViewState["ListId"] != null)
   5:              {
   6:                  SPList liste = SPContext.Current.Web.Lists[new Guid(ViewState["ListId"].ToString())];
   7:                  SPItem it = liste.GetItemById(int.Parse(ViewState["ItemId"].ToString()));
   8:   
   9:                  it["Title"] = txtTextbox1.Text;
  10:                  it.Update();
  11:              }
  12:          }

Zwecks Vereinfachung des Democodes, wurden alle Prüfungen auf Null-Werte weggelassen. Im Sinne einer “sicheren” Programmierung sind diese im Produktivcode aufzunehmen.

Kommentare sind geschlossen