事件处理程序返回后,在事件处理程序中的WebForms控件上设置的属性将恢复为

时间:2016-02-03 21:43:28

标签: c# asp.net events

我正在更新自定义事件处理程序中的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_TextChanged())。在ContentBlock对象中,当我设置属性(在本例中为Name)时,setter会验证它实际上是一个更改,然后触发在类中定义的NeedsCommitChanged事件,此Page对象以ContentBlock_NeedsCommitChanged作为处理程序订阅。处理程序(除其他外)根据数据是否需要提交到数据库来更新保存和丢弃按钮的状态。到目前为止,这么好......这一切都有效。

这就是问题所在:在ContentBlock_NeedsCommitChanged()返回和控制权传递回txtContentBlockName_TextChanged()之间的某个时刻,按钮的启用状态更改将恢复为false。我设置了如上所示的断点,然后我在断点位置B单步执行,然后在离开TextChanged处理程序的控制权之前在位置A处中断。我对按钮控件进行了监视,并将Enabled属性设置为true。我保持单步执行 - 控制传递回ContentBlock_NeedsCommitChanged()并且Enabled属性仍然是真的。另一个步骤将我带到ContentBlock.OnNeedsCommitChanged()然后转到ContentBlock.Name设置器,就像我期望的那样。当然,按钮超出了这两个框架的范围,所以我无法观看它。在下一步中,我返回txtContentBlockName_TextChanged(),按钮返回范围,但button.Enabled已恢复为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" />

欣赏任何见解......谢谢。

1 个答案:

答案 0 :(得分:0)

发现问题。我正在使用Page的{​​{1}}属性来存储对用户第一次调出页面时填充的字段的引用。当我处理PostBack事件时,我会从Session恢复这些字段。我错过的是Session对象本身与用于填充字段的对象不同,因此引用Page对象中某些内容的那些字段中的任何内容都引用旧的Page 。要解决此问题,我只需将订阅代码移出Page块,以便它在每个if (!PostBack)上发生。