سؤال

أقوم بتطوير تطبيق ASP.NET (3.5) وأنا في حيرة من سلوك Postbacks.

ضع في اعتبارك السيناريو التالي: لديّ عنصر تحكم مستخدم ويب يعد نموذجًا في الأساس. ومع ذلك ، فإن كل حقل نموذج هو تحكم مستخدم الويب في حد ذاته.

في حدث النقر فوق الزر "حفظ" الذي أكرره من خلال جميع عناصر التحكم في النموذج الخاص بي وأسترجع قيمة الحقل واسم الحقل الذي يشير إلى حقل قاعدة البيانات الذي أقوم بحفظ القيمة إليه.

يؤدي حدث Click Postback إلى Postback ، وخلال Postback أقوم بزيارة عناصر التحكم وهنا هو الشيء المضحك: أصبحت قيمة الممتلكات لحقل قاعدة البيانات لاغية! هل يمكن لأي شخص إلقاء الضوء هنا؟

هنا بعض التعليمات البرمجية الأساسية:

[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...");
    }
}
هل كانت مفيدة؟

المحلول

تذكر 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; }
}

نصائح أخرى

أول تخمين سيكون أن BindText () لا ينبغي أن يكون في page_load ، ولكن في page_init ، سيتم حفظ حالة التحكم.

david basarab ، هذا ليس صحيحًا AFAIK ، وكان هو الحال فقط في .NET 1.1 ، في .NET2 وما فوق يتم التعامل مع كل هذا بواسطة الإطار إذا قمت بكل الأشياء السحرية في البداية.

مشكلتك هي أن "ملف التعريف" غير متوفر على بعد الظهير ، أليس كذلك؟

يتمثل الحل في تخزين القيمة لذلك في ViewState (بدلاً من خاصية تنفيذ تلقائي). بدون ذلك ، لن يكون متاحًا على Postback.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top