Eigener Button zum Dateidownload

Folgende Situation: man hat ein selbstentwickeltes Webpart, das über einen Button eine Datei erstellt und dem Benutzer zum Download anbietet. Ein Benutzer klickt den Button und alles funktioniert, d.h. er bekommt die gewünschte Datei. Wenn er jetzt wieder in den Browser wechselt, reagiert kein Button mehr – auch der eigene nicht.

Die Ursache ist eine JavaScript-Variable von SharePoint, die beim Absenden des Formulars auf true gesetzt wird (um zu signalisieren, daß das Formular bereits gesendet wurde). Wenn der Code hinter einem eigenen Button jetzt eine Datei in den ResponseStream schreibt, bleibt dieser Variablenwert erhalten und verhindert weitere Postbacks. Man muß also nur diese Variable wieder auf false setzen und alles funktioniert wie gewünscht.

Getestet habe ich das mit folgendem einfachen Code in einem Webpart, der beim Klick auf einen Button eine einfache Textdatei an den Browser schickt. Der Browser reagiert mit seinem Download-Dialog darauf:

private void Button_Click(object sender, EventArgs e) {

  string text = "Hallo Welt";

  HttpResponse response = this.Page.Response;

  response.Clear();

  response.AddHeader("content-disposition", "attachment;filename=myfile.txt");

  response.ContentType = "application/text";

  response.Output.Write(text);

  response.End();

}

Der Button wurde dabei ebenso einfach erzeugt:

protected override void CreateChildControls() {

  Button btn = new Button();

  this.Controls.Add(btn);

  btn.ID = "myButton";

  btn.Text = "Download";

  btn.Click += Button_Click;

}

Man muß dem Button jetzt einfach noch ein wenig clientseitiges JavaScript mitgeben, das (nach einer kurzen Verzögerung) die SharePoint-Variable zurücksetzt und man kann auf den Button klicken so oft man möchte. Und auf alle anderen auch. Erreicht wird das durch eine weitere Zeile Code:

btn.OnClientClick = "window.setTimeout(function(){_spFormOnSubmitCalled=false;},10);";

Dynamische Titel bei benutzerdefinierten Formularen

Wenn man mit SharePoint Designer benutzerdefinierte Formulare anlegt, wird für den Titel, also für den Namen der Spalten, immer der aktuelle Wert fest eingetragen. Für den eigentlichen Feldwert, also für den Teil mit dem die Benutzer später interagieren (z.B. eine Textbox oder Checkbox) wird ein FieldControl eingefügt. Ebenso für den Beschreibungstext einer Spalte. Wenn man dann später etwas ändert, indem man z.B. bei einem Auswahlfeld von DropDown auf Radiobuttons umschaltet, dann sind diese Änderungen auch sofort in den benutzerdefinierten Formularen zu sehen. Wenn man aber den Spaltennamen ändert, wird im benutzerdefinierten Formular immer noch der alte Name angezeigt. Außerdem wird dieser Name immer nur in einer Sprache angezeigt und paßt sich nicht an, wenn ein Benutzer eine andere Sprache auswählt.

Um dieses Problem zu lösen, kann man in der Codeansicht von SharePoint Designer den fest eingefügten Text durch ein in SharePoint immer vorhandenes Control ersetzen:

<SharePoint:FieldLabel ControlMode="Display" runat="server" FieldName="Title" />

Für das FieldName-Attribut gibt man wie immer den internen Namen der Spalte an. Das ControlMode-Attribut muß angegeben werden, aber es macht keinen Unterschied, ob man Display, Edit oder New einträgt.

Das war’s auch schon. Es ist mir (mal wieder) ein Rätsel, warum SharePoint Designer das nicht gleich so macht.