6

Ich habe den Artikel TRULLY Understanding ViewState (großer Artikel btw) folgen und füllen meine Dropdown-Liste funktioniert super. Ich habe sogar ein OnSelectedIndexChange-Event eingerichtet, das fast genauso gut abfeuert.DropDownList OnSelectedIndexChange zu 0. Index w/out ViewState

Das Problem, das ich gefunden habe, ist das SelectedIndexChanged Ereignis wird nicht ausgelöst, wenn Sie den 0. Index auswählen. Es macht aber alle anderen Zeiten.

Hier einige Code:

<asp:DropDownList runat="server" ID="DropDownList1" EnableViewState="false" 
AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged" /> 


protected override void OnInit(EventArgs e) 
{ 
    this.DropDownList1.DataTextField = "Text"; 
    this.DropDownList1.DataValueField = "Value"; 
    this.DropDownList1.DataSource = fillQueueDropDown(); 
    this.DropDownList1.DataBind(); 

    base.OnInit(e); 
} 

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    OnSelectedQueueChanged(e); 
} 

public void OnSelectedQueueChanged(EventArgs e) 
    { 
     // Do stuff. 
    } 

public event EventHandler queueNamesChangedEvent; 
public void OnSelectedQueueChanged(EventArgs e) 
    { 
     if (queueNamesChangedEvent != null) 
      queueNamesChangedEvent(this, e); 
    } 

Ich nehme ich an in der Page_Load-Methode eine Art Scheck tun können:

if(ViewState["selectedIndexChangedFlag"] != 1) 
     // raise OnSelectedChange event 

Oder gibt es etwas, was ich kann Setup in der OnInit() -Methode, wo ich diese Daten immer wieder verbinde, die ich tun kann?

Sehen Sie, mein benutzerdefinierter EventHander löst ein Ereignis aus, das von einer übergeordneten Seite abgefangen wird, in der sich dieses Steuerelement befindet, damit das übergeordnete Element mit dem neu ausgewählten Wert eine Aktion ausführen kann. Dies funktioniert derzeit für alle Fälle, in denen der ausgewählte Index> 0 ist.

Ich erstelle in diesem Steuerelement eine Eigenschaft, die den zuletzt ausgewählten Index enthält. In diesem Fall kann meine übergeordnete Seite bei jedem Page_Load auf diesen Eigenschaftswert zugreifen. .. Keine Ahnung.

Offen für Vorschläge. Oder wie Sie dieses SelectedIndexChanged-Ereignis erzwingen, dass es für die 0. Indexauswahl ausgelöst wird.

Antwort

5

Mein Ziel bei der Deaktivierung von ViewState in dieser Dropdown-Liste besteht darin, die Größe von ViewState für die Seite zu minimieren.

Das Problem, das ich mit nur die If (! Page.IsPostBack) {... DataBind() ...} hatte, ist, dass, wenn Sie ein Element zum ersten Mal auswählen, und die Seite neu geladen wird, mein Tropfen Down-Liste wird leer.

Was ich getan habe, war das Erstellen einer anderen Eigenschaft für dieses Steuerelement, LastIndex. Wenn das OnSelectedIndexChanged-Ereignis ausgelöst wird, aktualisiere ich den LastIndex-Wert. In Page_Load vergleiche ich die aktuellen und letzten Indexwerte, wenn sie unterschiedlich sind, und feuere dann ein geändertes Indexereignis.

public int SelectedValue{ 
     get { return this.DropDownList1.SelectedItem.Value; } 
    } 

    public int LastIndex{ 
     get { return this.ViewState["lastIndex"] == null ? -1 : (int)this.ViewState["lastIndex"]; } 
     set { this.ViewState["lastIndex"] = value; } 
    } 

    protected override void OnInit(EventArgs e){ 
     base.OnInit(e); 
     this.DropDownList1.DataTextField = "Text"; 
     this.DropDownList1.DataValueField = "Value"; 
     this.DropDownList1.DataSource = fillQueueDropDown(); 
     this.DropDownList1.DataBind(); 
    } 

    protected void Page_Load(object sender, EventArgs e){ 
     if (this.LastIndex != this.SelectedValue) 
      this.OnSelectedQueueChanged(new EventArgs()); 
    } 

    private ListItemCollection fillQueueDropDown(){...} 

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e){ 
     OnSelectedQueueChanged(e); 
     this.LastIndex = this.SelectedValue; 
    } 

    public event EventHandler queueNamesChangedEvent; 
    public void OnSelectedQueueChanged(EventArgs e){ 
     if (queueNamesChangedEvent != null) 
      queueNamesChangedEvent(this, e); 
    } 

Sie haben jedoch Recht. Die Daten werden in der OnInit-Phase erneut geladen und neu gebunden. Dann wird der ViewState wiederhergestellt (und wenn der 0. Index wiederhergestellt wird), wenn wir schließlich zur Events-Phase gelangen, erkennt das Steuerelement die Änderung nicht.

Nicht sicher, das ist die eleganteste Route, aber es funktioniert so gut.

Dann fand ich dies in der MSDN-Dokumentation für IPostBackDataHandler:

public virtual bool LoadPostData(string postDataKey, 
    NameValueCollection postCollection) { 

    String presentValue = Text; 
    String postedValue = postCollection[postDataKey]; 

    if (presentValue == null || !presentValue.Equals(postedValue)) { 
     Text = postedValue; 
     return true; 
    } 

    return false; 
    } 

Da der gegenwärtige Wert der gleiche wie der geändert zu Wert ist, wird das Ereignis nicht ausgelöst wird.

+1

+1 Sehr schön - dies ist eine hervorragende Möglichkeit, dies ohne ViewState zu tun! Tut mir leid, ich habe nicht bemerkt, dass du ViewState nicht willst - ich werde die Frage beim nächsten Mal genauer lesen. –

+1

Vielen Dank für Ihre erste Lösung, es hat wirklich dazu beigetragen, etwas Licht in die Reihenfolge der Dinge zu bringen. Ich denke, ich kenne den asp.net Seitenlebenszyklus nicht so gut, wie ich dachte. –

8

Das Problem besteht darin, dass Sie die Daten jedes Mal laden und dadurch den ausgewählten Index zurücksetzen. Stellen Sie sich Ihren Drop-Down:

zero [selected] 
one 
two 

Dann im Client Sie den ausgewählten Index ändern:

zero 
one [selected] 
two 

Dieser füllt den versteckten Eingang __EVENTARGUMENT mit Ihrem neuen Index (1) und den versteckten Eingang __EVENTTARGET mit der id von Ihrem Dropdown. Nun ist der serverseitigen Code tritt in und lädt Ihre Daten:

zero [selected] 
one 
two 

„Null“ ist der gewählte Wert, denn das ist die Standardeinstellung, wenn die Daten geladen werden. Dann sucht ASP.NET nach __EVENTTARGET und __EVENTARGUMENT in der Request und findet Ihr Dropdown id und findet den neuen Index (1). Jetzt ist Ihre Drop-Down sieht wie folgt aus:

zero 
one [selected] 
two 

Da der Index geändert hat, das Drop-Down wirft seine SelectedIndexChanged Ereignis, das angibt, dass der Index geändert hat. Offensichtlich ist dies der Teil, der funktioniert, jetzt lasst uns sehen, warum das Auswählen des ersten Elements in der Liste das Ereignis nicht anhebt.

Jetzt sagen wir, dass wir noch das Dropdown in dem Zustand haben, in dem es gerade war (wobei "eins" ausgewählt ist und der ausgewählte Index 1 ist). Was passiert, wenn wir den ersten Eintrag in der Liste auf dem Client auswählen?

__EVENTTARGET und __EVENTARGUMENT mit dem id der Drop-Down-und den neuen Index (0) bevölkert. Dann lädt der Server die Daten in das Drop-down-und die Drop-Down sieht nun wie folgt wieder:

zero [selected] 
one 
two 

Beachten Sie, dass seit nachgeladen Sie die Daten vor die Ereignisse der Index feuerte bereits auf 0 gesetzt ist, denn das ist die Standardeinstellung . Wenn jetzt Ihr Ereignis ausgelöst wird und der ausgewählte Index des Drop-downs auf 0 gesetzt ist, wird dies im Drop-down nicht als Änderung angesehen, da der ausgewählte Index (soweit bekannt) sich nicht geändert hat.

Hier ist, wie das Problem zu beheben:

protected override void OnLoad(EventArgs e) 
{ 
    base.OnLoad(e); 

    if (!Page.IsPostBack) 
    { 
     this.DropDownList1.DataTextField = "Text"; 
     this.DropDownList1.DataValueField = "Value"; 
     this.DropDownList1.DataSource = fillQueueDropDown(); 
     this.DropDownList1.DataBind(); 
    }  
} 

Was dies ist nicht nur die Daten in der Dropdown-Liste laden, wenn die Seite nicht ein Postbacks ist. Dies bedeutet, dass ViewState die Daten für Sie und den ausgewählten Index verwaltet, so dass Sie beim Zurücksetzen des Dropdowns den neuen Index mit dem Index vergleichen, den Sie im Client gesehen haben.

+0

Eine sehr gute Erklärung! –

Verwandte Themen