6

私は記事TRULLY Understanding ViewState (すばらしい記事btw)に従いましたが、ドロップダウンリストの作成はうまく機能しています。OnSelectedIndexChange イベントもセットアップしましたが、これはほぼ同じように発生します。

私が見つけた問題は、0 番目のインデックスを選択したときに SelectedIndexChanged イベントが発生しないことです。ただし、それ以外の場合はすべて行います。

ここにいくつかのコードがあります:

<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);
    }

Page_Load メソッドで何らかのチェックを行うことができると思います。

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

または、私ができるたびにこのデータを再バインドしている OnInit() メソッドでセットアップできるものはありますか?

私のカスタム EventHander は、このコントロールが存在する親ページによってキャッチされるイベントを発生させ、親が新しく選択された値を使用して何らかのアクションを実行できるようにします。そして、これは現在、選択したインデックスが 0 を超えるすべてのケースで機能しています。

このコントロールに、最近選択されたインデックスを含むプロパティを作成します。この場合、親ページは Page_Load ごとにこのプロパティ値に対してアクションを実行できます... わかりません。

提案を受け付けます。または、この SelectedIndexChanged イベントをその 0 番目のインデックス選択に対して強制的に発生させる方法。

4

2 に答える 2

5

このドロップダウン リストで ViewState を無効にする私の目標は、ページの ViewState のサイズを最小限に抑えることです。

if(!Page.IsPostBack){...DataBind()...} のみを実行したときに発生した問題は、アイテムを初めて選択してページをリロードすると、ドロップダウン リストが空になることです。 .

私が最終的に行ったのは、このコントロールの LastIndex に別のプロパティを作成することでした。OnSelectedIndexChanged イベントが発生したら、LastIndex 値を更新します。Page_Load では、Current と Last のインデックス値を比較し、異なる場合は Index changed イベントを発生させます。

    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);
    }

あなたは正しいです。データは、OnInit フェーズで再ロードおよび再バインドされます。その後、ViewState が復元され (そして 0 番目のインデックスが復元されると)、最終的にイベント フェーズに到達すると、コントロールは変更を検出しません。

これが最もエレガントなルートかどうかはわかりませんが、今のところうまく機能しています。

次に、IPostBackDataHandler の msdn ドキュメントでこれを見つけました。

  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;
  }

現在の値は変更後の値と同じであるため、イベントは発生しません。

于 2009-01-24T00:33:10.033 に答える