Laden...

Dynamisch generiertes GridView (code behind) nach Postback beibehalten

Erstellt von Freeman4gu vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.535 Views
Freeman4gu Themenstarter:in
71 Beiträge seit 2007
vor 13 Jahren
Dynamisch generiertes GridView (code behind) nach Postback beibehalten

Hallo zusammen,

kurz zur aktuellen Lage. Ich generiere mehrere GridViews dynamisch aus einer Liste und schreibe diese als Childcontrols in ein Panel.

Das Problem ist, nach einem Postback sind diese logischerweise weg 😦
Ich führe aber Aktionen auf Grundlage dieser GridViews aus bzw. einfach OnSelectedIndexChanged-Methoden. Da die GridViews aber nicht mehr da sind, gehts natürlich nicht.

Gibts ne Möglichkeit diese beispielsweise über den ViewState beizubehalten?

UPDATE: Habs mal mit ner Session versucht und mit pnl.EnableViewState hat aber beides nicht funktioniert, wobei ich ersteres eh nicht so toll finde ^^

Android & WP7 development | Bikube - Projektmanagement und Wiki
http://zero-level-studios.com
http://bikube.de

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo,

an welcher Stelle erstellst Du denn die GridViews?
Wenn Du den ViewState für dynamische Steuerelemente benutzen willst, musst Du sie im Page_PreInit erzeugen, da bereits zwischen Page_PreInit und Page_Load der ViewState wiederhergestellt wird.

Schau Dir dazu auch unbedingt die Übersicht über den Lebenszyklus von ASP.NET-Seiten, da steht auch noch viel mehr Wissenswertes über die Funktionsweise von ASP.NET

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

Freeman4gu Themenstarter:in
71 Beiträge seit 2007
vor 13 Jahren

Hmm, ich habs mal versucht, allerdings sind im PreInit noch keine Steuerelemente vorhanden. Also ich kann zwar meine Grids erzeugen, kann sie aber nicht als Childcontrol an das Panel hängen.

Android & WP7 development | Bikube - Projektmanagement und Wiki
http://zero-level-studios.com
http://bikube.de

P
67 Beiträge seit 2007
vor 13 Jahren

Hi Freeman4gu,

die Init Ereignisse sind dafür nicht gerade gut geeigenet, da du die GridViews ja nach einem Postback benötigst und Inits werden ja nur beim ersten mal durchlaufen. Wenn du die Gridviews nach einem Postback noch haben möchtest, musst du sie entweder beim Client im Viewstate speichern oder dir in der Session hinterlegen. Im Viewstate würde ich nicht gerade empfehlen, da die Daten wahrscheinlich nicht gerade wenig sind und die ja jedesmal mit übertragen werden. Ich hatte mal ne riesige Liste im Viewstate und die hat beim Laden bzws. wieder abschicken Ewigkeiten gebraucht.

Bei der Session musst du die einfach beim Erstellen mit dort rein hängen und beim nächsten Aufruf wieder rausholen und auf der Seite hinzufügen. Wenn du Ereignisse verwendest darauf achten das die Controls ID haben sonst generiert der Server wieder andere und die Ereignisse werden nicht ausgelöst.

Schau dir mal auf der aktuellen Seite (Lebenszyklus von Seiten), die dir MarsStein empfohlen hat nach, da gibt es ganz unten eine schöne Grafik, wo du genau sieht in welcher Reihenfolge was kommt. Da kannst du genau sehen, wann gewisse Daten beim Postback wieder hergestellt werden bzw. wann du die Controls wieder hergestellt haben musst bevor die Ereignisse eintreten.

PS: in einem Thema drüber versuche ich auch gerade zu erfragen wie man so etwas einfacher lösen kann.

Gruß Phoenix

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo,

Hmm, ich habs mal versucht, allerdings sind im PreInit noch keine Steuerelemente vorhanden.

Warum nicht? Zumindest die in der aspx vorhandenen Steurelemente sollten da bereits erstellt worden sein. Oder ist das Panel auch dynamisch? Dann müsstest Du es vorhererstellen.

die Init Ereignisse sind dafür nicht gerade gut geeigenet, da du die GridViews ja nach einem Postback benötigst und Inits werden ja nur beim ersten mal durchlaufen.

Sorry aber das ist Unsinn. Natürlich werden die Init-Ereignisse auch bei einem PostBack durchlaufen. Und die dynamischen Steuerelemente müssen erstellt werden, bevor ihr Zustand wiederhergestellt wird, das dürfte klar sein. Also bleiben nur die Init-Ereignise dafür übrig, wie aus der von mir verlinkten Seite auch hervorgeht.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

Freeman4gu Themenstarter:in
71 Beiträge seit 2007
vor 13 Jahren

Hallo nochmal,

also ich habe festgestellt, solange ich die Grids immer wieder gleich anbinde, funktionieren auch die Methodenaufrufe. Wenn da nicht direkt ein anderes Problem wäre... und zwar wird die Seite direkt 2 mal geladen.

Ich kenne das eigentlich nur wenn irgendwo ein html-Fehler z.b. beim Bilderladen entsteht.

Das Problem ist, ich rufe über die dynamischen Grids jeweils eine Löschen Methode auf, die einen Datensatz entfernt. Beim 2ten Laden jedoch existiert der Datensatz ja bereits nicht mehr und meine Methode läuft in eine Exception.

Klever wie ich bin, dachte ich mir, ok speicherst den Zustand, also das schon ein Aufruf war in der Session. Funktioniert auch, allerdings bekomme ich dann eine Zustandsexception des Grid, da ja der eine Datensatz bereits gelöscht ist.

Warum ist das denn nur so behindert bei Grids, habe das Ganze mal mit nem Label und ner Textbox versucht. Das einzige wo es ordentlich geklappt hat, war mit der Textbox, diese kann einfach nachgeladen werden und speichert dann auch den Zustand. Das Grid scheint im ViewState den Inhalt zu verlieren, ebenso das Label.

UPDATE: Beitrag übersehen, also das Panel ist nicht dynamisch. Ist aber leider auch nicht im PreInit vorhanden, bekomme dort immer eine NullReferenceException des Panels ^^

Android & WP7 development | Bikube - Projektmanagement und Wiki
http://zero-level-studios.com
http://bikube.de

P
67 Beiträge seit 2007
vor 13 Jahren

Hi MarsStein,

die Init Ereignisse sind dafür nicht gerade gut geeigenet, da du die GridViews ja nach einem Postback benötigst und Inits werden ja nur beim ersten mal durchlaufen.
Sorry aber das ist Unsinn. Natürlich werden die Init-Ereignisse auch bei einem PostBack durchlaufen...

Nein werden sie nicht. Teste es mal mit einem Button und einem Label und lass dir bei Load und Init mal was ins Label schreiben. Dann wirst du sehen das Init nur ein mal drin stehen wird und Load beim jedem Postback reinschreibt.

PS: Bitte das nächste mal nicht gleich mit "Unsinn" kommentieren.

Gruß Phoenix

Freeman4gu Themenstarter:in
71 Beiträge seit 2007
vor 13 Jahren

Ok, so scheinbar siehts ganz gut aus. Habe den doppel-Postback fehler gefunden. Es handelt sich dabei um den GridView-Button ^^

Hatte schonmal ähnliche Probleme, sobald ich in diesem Code


CommandField delete = new CommandField();
//delete.SelectImageUrl = "images/delete-page-red.gif";
delete.SelectText = "Löschen";
delete.ShowSelectButton = true;
delete.ButtonType = ButtonType.Link;
delete.HeaderText = "Aktion";
delete.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
delete.ItemStyle.Width = Unit.Percentage(10);
delete.ItemStyle.HorizontalAlign = HorizontalAlign.Center;

den ButtonType auf Image stelle und die SelectImageUrl wieder
mit in den Code nehme, erfolgt ein doppelter Postback ^^

UPDATE: So ich habs jetzt einfach folgendermaßen geklärt, ist zwar bissl dirty aber was solls ^^


delete.SelectText = "<img src=\"images/delete-page-red.gif\" alt=\"Löschen\" />";

Ich danke euch für eure Hilfe!!!

Also das Nachladen des Grids mache ich jetzt einfach über die gleiche Methode wie das erstellen, das mit dem ViewState und der Session hatte aufgrund des DoppelPostbacks ebenfalls nicht funktioniert. Zudem ist es glaub ich mit der Session nicht möglich, da ein komplettes Grid nicht serialisierbar ist und der Viewstate des Grids wurde ebenfalls nicht gespeichert. Daher habe ich mich jetzt für diese Lösung entschieden. Die jetzt auch zum Glück funktioniert 😉

Das einzige was ich persönlich noch unschön finde ist die Tatsache, das bei einem Delete 2 mal eine Datenbankanfrage geschickt wird um die Daten vorher und nachher zu holen. Dort seh ich allerdings auch im mom keine Möglichkeit das zu ändern.

Android & WP7 development | Bikube - Projektmanagement und Wiki
http://zero-level-studios.com
http://bikube.de

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo,

Nein werden sie nicht. Teste es mal mit einem Button und einem Label und lass dir bei Load und Init mal was ins Label schreiben. Das ist die falsche Art zu testen, dadas Label dem ViewState unterliegt. Setz mal einen break im Page_PreInit, und Du wirst sehen daß er anhält 😉

Folgendes einfache Beispiel veranschaulicht das:

CodeBehind:

public partial class _Default : System.Web.UI.Page 
{
  Label lbl;
  protected void Page_PreInit(object sender, EventArgs e)
  {
    lbl = new Label();
    lbl.ID = "lbl";
    testPanel.Controls.Add(lbl);

    // Hier dürfen die Werte noch nicht gesetzt werden, sonst geht alles verloren.
    // Das darf erst im Page_Load gemacht werden.

    //if (!IsPostBack)
    //{
    //  lbl.Text = "foo";  // wäre zu früh!
    //}
  }
  protected void Page_Load(object sender, EventArgs e)
  {
    // Hier müssen die Werte gestzt werden, damit ViewState funktioniert.
    if (!IsPostBack)
    {
      lbl.Text = "foo";
    }
  }
  protected void b1_click(object sender, EventArgs e) {
    lbl.Text = "bar: " + lbl.Text;
  }
}

ASPX:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head runat="server">
    <title></title>
</head>
<body>
<div>
    <form id="form1" runat="server">
    <asp:Panel ID="testPanel" runat="server"></asp:Panel>
    <asp:Button ID="b1" OnClick="b1_click" Text="Test" runat="server"/>
    </form>
</div>
</body>
</html>

Wenn Du den Button mehrfach klickst, siehst Du wie's funktioniert.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

P
67 Beiträge seit 2007
vor 13 Jahren

Hi MarsStein,

ja sorry hast recht. Der Viewstate überschreibt ja den Eintrag der im PreInit gemacht wird jedesmal deswegen steht es nur ein mal drin. Und ich hatte immer geglaubt (weil ich es so getestet hatte) das Init immer nur ein mal durchlaufen wird.

Gruß Phoenix