Web Part requires clicking twice the Apply/OK button to apply the changes


Recently I was debugging a Web Part which had an issue with applying its changes. It required clicking the Apply/OK button twice in order to apply the changes. While this problem is quite commonly seen in different examples on the Internet, the solution is very simple.

To illustrate this issue I have created a simple Web Part which displays the text typed in the Web Part’s properties:

Sample Web Part that displays the text typed in the in the Web Part’s properties

Right after adding the value of the My Property property is empty:

Sample Web Part right after adding it to the page: the My Property property is empty and no text is displayed

Then after having provided some text in the value of My Property you click the Apply button… and nothing changes. The Web Part still doesn’t display the text:

After clicking the Apply button the Web Part still hasn’t applied the changes

After clicking the Apply button again, the Web Part finally displays the changes:

After clicking the Apply button for the second time the Web Part applied the changes

The Web Part was created using the following code:

public class MyWebPart : WebPart
{
    [Personalizable(PersonalizationScope.Shared), WebBrowsable(true), WebDisplayName("My Property")]
    public string MyProperty { get; set; }

    protected Literal literal;

    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        literal = new Literal();
        Controls.Add(literal);
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        EnsureChildControls();
        literal.Text = MyProperty;
    }
}

Although the above example is very simple and doesn’t really requires the Literal control, I’ve decided to use it instead of the RenderContents method, to give you a good example of how to solve the issue while working with controls.

The reason of the issue that I mentioned, is the lifecycle of controls in ASP.NET and in particular the order in which different events occur. In this particular scenario the event responsible for synchronizing the properties from Web Part’s Editor Pane with the Web Part itself occurs after the Load event. So if the Web Part uses the OnLoad event handler to read the value of one of its properties, it will still get the old value.

The fix to this challenge is very simple. What you can do is to move the implementation from the Load event to the PreRender event:

public class MyWebPart : WebPart
{
    [Personalizable(PersonalizationScope.Shared), WebBrowsable(true), WebDisplayName("My Property")]
    public string MyProperty { get; set; }

    protected Literal literal;

    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        literal = new Literal();
        Controls.Add(literal);
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        EnsureChildControls();
        literal.Text = MyProperty;
    }
}

Using exactly the same code you can make your Web Part behave as it is supposed to! Every change done to the value of the My Property property, will be applied with a single click.

Although you cannot see the results here, I strongly encourage you to test the code above: both the original one using the OnLoad event handler and the one using the OnPreRender event handler.

Technorati Tags: SharePoint

Others found also helpful: