C# 事件处理程序中WebForms控件上的属性集在事件处理程序返回后恢复

C# 事件处理程序中WebForms控件上的属性集在事件处理程序返回后恢复,c#,asp.net,events,C#,Asp.net,Events,我正在更新自定义事件处理程序中WebForms控件的属性,但当控件从事件处理程序返回时,该属性将恢复到原来的状态 以下是代码背后的相关部分: public partial class EditorLayoutv4 : System.Web.UI.Page { protected void Page_Load(object oSender, EventArgs oEventArgs) { if (!IsPostBack) { moSelect

我正在更新自定义事件处理程序中WebForms控件的属性,但当控件从事件处理程序返回时,该属性将恢复到原来的状态

以下是代码背后的相关部分:

public partial class EditorLayoutv4 : System.Web.UI.Page
{
    protected void Page_Load(object oSender, EventArgs oEventArgs)
    {
        if (!IsPostBack) {
            moSelectedContentBlock.NeedsCommitChanged += ContentBlock_NeedsCommitChanged;
        }
        else {
            // restore fields from Page.Session[]
        }
    }

    protected void Page_Prerender(object sender, EventArgs e) {
        // save fields to Page.Session[]
    }

    private void RefreshContentBlockInfoButtons()
    {
        btnSaveContentBlockChanges.Enabled = moSelectedContentBlock.NeedsCommit; // breakpoint location A
        btnDiscardContentBlockChanges.Enabled = moSelectedContentBlock.NeedsCommit;
    }

    protected void ContentBlock_NeedsCommitChanged(object oSender, EventArgs oEventArgs)
    {
        myContentBlockRow oContentBlock = (myContentBlockRow)oSender;

        if (oContentBlock.Enabled)
        {
            if (oContentBlock == moSelectedContentBlock)
            {
                RefreshContentBlockInfoButtons();
            }
        }
    }

    protected void txtContentBlockName_TextChanged(object oSender, EventArgs oEventArgs)
    {
        moSelectedContentBlock.Name = txtContentBlockName.Text;  // breakpoint location B
    }
}

public sealed class ContentBlock {
    public string Name { 
        get { return GetNameFromDB(); }
        set {
            if (value != GetNameFromDB()) {
                PutNameInDB(value);
                OnNeedsCommitChanged();
        }
    }

    private void OnNeedsCommitChanged()
    {
        RowStateChangeHandler hHandler = this.NeedsCommitChanged;

        if (hHandler != null)
        {
            hHandler(this, EventArgs.Empty);
        }
    }

    public event EventHandler NeedsCommitChanged;
}
执行过程如下:当用户更改控件的值(在本例中为
txtContentBlockName
)时,它会触发相应的事件(在本例中为
TextChanged
),并将控件传递给代码后面的相应处理程序(在本例中为
txtContentBlockName\u TextChanged()
)。在
ContentBlock
对象中,当我设置一个属性(在本例中是
Name
)时,setter会验证它实际上是一个更改,然后触发一个
NeedsCommitChanged
事件,该事件是在类中定义的,该页面对象使用
ContentBlock\u NeedsCommitChanged
作为处理程序订阅的。处理程序(除其他外)根据数据是否需要提交到数据库来更新保存和放弃按钮的状态。到目前为止,一切正常

这里的问题是:按钮的启用状态更改在
ContentBlock\u NeedsCommitChanged()
返回和控件传回
txtContentBlockName\u TextChanged()
之间的某个时间点恢复为false。我如上所示设置断点,然后在断点位置B单步执行,在离开TextChanged处理程序的控制之前在位置A中断。我在按钮控件上放了一块手表,看到Enabled属性设置为true。我保持单步执行——控制传递回
ContentBlock\u NeedsCommitChanged()
,并且Enabled属性仍然为true。另一个步骤将我带到
ContentBlock.OnNeedsCommitChanged()
,然后是
ContentBlock.Name
setter,正如我所期望的那样。当然,按钮在这两帧中超出了范围,所以我无法观看。在下一个步骤中,我返回到
txtContentBlockName\u TextChanged()
,按钮回到作用域中,但
按钮。已启用的
已恢复为false。我没有任何其他涉及按钮属性的代码。如果重要的话,以下是在.aspx中声明按钮的方式:

<asp:Button ID="btnSaveContentBlockChanges" runat="server" Text="Save Changes" ToolTip="Save changes you've made to this content block" OnClick="btnSaveContentBlockChanges_Click" />
<asp:Button ID="btnDiscardContentBlockChanges" runat="server" Text="Discard Changes" ToolTip="Discard changes you've made to this content block" OnClick="btnDiscardContentBlockChanges_Click" />


感谢您提供的任何见解……谢谢。

发现了问题。我正在使用
页面
会话
属性来存储对用户第一次打开页面时填充的字段的引用。当我处理回发事件时,我从
会话
还原这些字段。我遗漏的是
页面
对象本身与用于填充字段的对象不同,因此这些字段中引用
页面
对象中的任何内容都会引用旧的
页面
。为了解决这个问题,我只需将subscribe代码移出
if(!PostBack)
块,这样它就会出现在每个
页面上