1

asp.net (3.5) アプリケーションを開発していますが、ポストバックの動作に困惑しています。

次のシナリオを考えてみましょう: 基本的にフォームである Web ユーザー コントロールがあります。ただし、各フォーム フィールドはそれ自体が Web ユーザー コントロールです。

保存ボタンのクリック イベントでは、フォーム内のすべてのコントロールを繰り返し処理し、値を保存するデータベース フィールドを参照するフィールド値とフィールド名を取得します。

クリック イベントによってポストバックがトリガーされ、ポストバック中にコントロールにアクセスすると、データベース フィールドのプロパティ値が null になっています。誰かがここに光を当てることができますか?

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

[Serializable]
public partial class UserProfileForm : CustomIntranetWebappUserControl
{
    protected override void OnInit(EventArgs e)
    {
        //AutoEventWireup is set to false
        Load += Page_Load;
        CancelLinkButton.Click += CancelButtonClickEvent;
        SaveLinkButton.Click += SaveButtonClickEvent;
        base.OnInit(e);
    }

    private void SaveButtonClickEvent(object sender, EventArgs e)
    {
        VisitFormFields();
    }

    private void VisitFormFields()
    {
        var userProfileVisitor = new UserProfileVisitor();

        foreach (var control in Controls)
        {
            if (control is FormFieldUserControl)
            {
                var formField = (FormFieldUserControl) control;
                formField.Visit(userProfileVisitor);
            }
        }
        userProfileVisitor.Save();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindText();
        }
    }

    private void BindText()
    {
        LastNameFormLine.LabelText = string.Format("{0}:", HomePage.Localize("Last Name"));
        LastNameFormLine.InputValue = UserProfile.LastName;
        LastNameFormLine.IsMandatoryField = true;
        LastNameFormLine.IsMultilineField = false;
        LastNameFormLine.ProfileField = "UserProfile.LastName";
        //... the rest of this method is exactly like the 4 lines above.
    }
}

[Serializable]
public abstract class FormFieldUserControl : CustomIntranetWebappUserControl
{
    public string ProfileField { get; set; }
    public abstract void Visit(UserProfileVisitor userProfileVisitor);
}


[Serializable]
public partial class FormLineTextBox : FormFieldUserControl
{
//...  irrelevant code removed... 

    public override void Visit(UserProfileVisitor userProfileVisitor)
    {
        if (userProfileVisitor == null)
        {
            Log.Error("UserProfileVisitor not defined for the field: " + ProfileField);
            return;
        }
        userProfileVisitor.Visit(this);
    }
}

[Serializable]
public class UserProfileVisitor
{

    public void Visit(FormLineTextBox formLine)
    {
        // The value of formLine.ProfileField is null!!!
        Log.Debug(string.Format("Saving form field type {1} with profile field [{0}] and value {2}", formLine.ProfileField, formLine.GetType().Name, formLine.InputValue));
    }

    // ... removing irrelevant code... 

    public void Save()
    {
        Log.Debug("Triggering the save operation...");
    }
}
4

4 に答える 4

7

ASP.NET はステートレスです。作成されたプロパティは、ページがブラウザにレンダリングされた後に破棄されます。そのため、ポストバックごとにオブジェクトを再作成するか、それらをビュー、セッション、またはアプリケーションの状態に保存する必要があります。

プロパティを実行するときは、ビューステートを保存するように指示する必要があります。自動的には保存されません。ビュー ステート プロパティのサンプルを次に示します。

public string SomePropertyAsString
{
    get
    {
        if (this.ViewState["SomePropertyAsString"] == null)
            return string.Empty;

        return (string)this.ViewState["SomePropertyAsString"];
    }
    set { this.ViewState["SomePropertyAsString"] = value; }
}

public MyCustomType ObjectProperty
{
    get
    {
        if (this.ViewState["ObjectProperty"] == null)
            return null;

        return (MyCustomType)this.ViewState["ObjectProperty"];
    }
    set { this.ViewState["ObjectProperty"] = value; }
}
于 2009-09-04T12:35:45.780 に答える
0

あなたの問題は、「ProfileField」がポストバックで利用できないことですよね?

解決策は、その値を (自動実装されたプロパティではなく) ViewState に格納することです。それがなければ、ポストバックで利用できません。

于 2009-09-04T12:42:50.693 に答える
0

最初の推測では、BindText() は Page_Load ではなく Page_Init にあるはずなので、コントロールの状態は保存されます。

于 2009-09-04T12:35:30.270 に答える
0

@David Basarab、これは真実ではなく、.Net 1.1、.Net2以降の場合にのみ当てはまりました.Initですべての魔法のことを行うと、これはすべてフレームワークによって処理されます。

于 2009-09-04T12:38:54.250 に答える