locked
questions regarding my custom composite control RRS feed

  • Question

  • User192013029 posted

    i'm writing a composite control that contains 2 buttons, an xml control and a text box. depending on the value of a property, i render only the one of the latter 2 in the RenderContents method. actually it pretty much works the way it is now but there's some things i'm confused about or not sure i'm doing the right way. which brings up those questions..

    i've seen samples of controls in books, etc that use the ViewState collection to store the values of properties. but i've also seen control samples that use the standard private variable. how do you know when to use which?

    i've also seen examples where a call to EnsureChildControls is made within the accessors of the properties. but i've also seen examples where they don't. again, how do you know when or when not to call ECC?

    what's the proper procedure for initializing certain property values so that the first time you do a get, there's a value already set. and no, using the DefaultValue attribute doesn't work. this is the property i use to determine whether to render the xml control or the text box (using ViewState). i want it to default to the text box so since the defaultvalue doesn't seem to take, i initialize it in the overridden OnInit handler. this seems to work although i have no idea why. if i don't initialize it in OnInit, i get an exception in the get accessor saying 'object reference not set to instance of object' when i run the containing app. this refers to the ViewState var which when init'd in OnInit, gets rid of this error. that's fine but since OnInit is executed on every postback, how is it the views are still swapped correctly (ie: the old value is still retained) when i keep reseting it's value back to Text in
    OnInit? you would think it would always start out as Text and only allow a
    swap to Xml just once but not back again.

    appreciate any help..


    Monday, May 25, 2009 12:06 PM

Answers

  • User192013029 posted

    thanx for the help Allen but i think i found the proper way to do this. it removes what looked to me like a timing issue..

    first i commented out the setting of CurViewState in the OnInit handler then i modified the get accessor as follows..

            public virtual VIEWSTATE CurViewState
    {
    get
    {
    if (ViewState["CurViewState"] != null)
    {
    VIEWSTATE curViewState = (VIEWSTATE)ViewState["CurViewState"];
    return curViewState;
    }
    else
    {
    return VIEWSTATE.TEXT;
    }
    }
    set
    {
    ViewState["CurViewState"] = value;
    }
    }

    feel kind of silly that all it took was a simple is null check but it works. the problem i think stemmed from the timing of when RenderContents checks CurViewState to determine what control to render vs when CurViewState is first set in OnBubble. obviously when the page is first rendered, Render executes but OnBubble doesn't since it only kicks off via the button click. the is null allowed me to return a valid indicator up until the button is clicked. since i wanted TEXT to be the default, i knew i could set it to TEXT since it's only null at start up.

    of course this doesn't explain why the value of CurViewState didn't stick between the OnInit and OnBubble events but i never believed that was the right way to do it anyway.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, June 1, 2009 9:45 PM

All replies

  • User192013029 posted

    thanx..

    i found the page life cycle page the most helpful but i'm still in the dark about how the old value of CurViewState is retained when i reset it everytime in OnInit. just so you can see what i mean, i added some Debug stmt's. here's the output..

    In OnInit                                   <--- OnInit executes on startup
    In set CurViewState: TEXT         <--- CurViewState is init'd to TEXT
    In CreateChildControls
    In CreateContainerChildControls
    In CreateContainerChildControls
    In CreateContainerChildControls
    In LoadTextView
    In get FileSelected: True
    In get XmlFilePath
    In CreateContainerChildControls
    In LoadTreeView
    In get FileSelected: True
    In get XmlFilePath
    In CreateContainerChildControls
    In OnLoad
    In SwapView handler                 <--- SwapView button handler in OnBubbleEvent
    In get CurViewState: TEXT         <--- CurViewState checked for value
    In set CurViewState: TREE        <--- change CurViewState to TREE
    In RenderContents
     

    ok, fine. but look what happens the second time the button is pressed..

    In OnInit                                   <--- second time through 
    In set CurViewState: TEXT         <--- init'd to TEXT again
    In CreateChildControls
    In CreateContainerChildControls
    In CreateContainerChildControls
    In CreateContainerChildControls
    In LoadTextView
    In get FileSelected: True
    In get XmlFilePath
    In CreateContainerChildControls
    In LoadTreeView
    In get FileSelected: True
    In get XmlFilePath
    In CreateContainerChildControls
    In OnLoad
    In SwapView handler                <--- SwapView button handler in OnBubbleEvent
    In get CurViewState: TREE       <--- ?? how is this TREE when OnInit set it back to TEXT?
    In set CurViewState: TEXT              no changes were made to the property in between.
    In RenderContents


    hope that clarifies my question.. i know it's working but this makes no sense to me.

    Thursday, May 28, 2009 8:47 PM
  • User-2106054853 posted

    Could you provide a demo that can reproduce this issue? What's CurViewState?

    Thursday, May 28, 2009 10:55 PM
  • User192013029 posted

    do you mean like a web page? all's i have right now are the projects - i've run everything within Visual Studio.

    CurViewState is the property i use to keep track of how the xml should be displayed - TEXT for straight text in a textbox, TREE for formatted in the Xml control (using defaultss.xslt). it's this property that RenderContents looks at to determine which of the 2 controls will actually be rendered.

    Friday, May 29, 2009 12:41 AM
  • User-2106054853 posted

    Hi,

    Thanks for the clarification but it's hard to understand your scenario without code. Could you create a demo project that can demonstrate this issue?

    Friday, May 29, 2009 4:19 AM
  • User192013029 posted

    since i only saw the source code option as a way to post code as opposed to being able to attach a zip file, i included just the code for my class library/dll. guess you'll have to make it work from there. 

    remember i'm only doing anything in OnInit in an attempt to initialize the CurViewState property to TEXT. if there's a better way to do it, let me know. thanx.

    <--snip-->
    Friday, May 29, 2009 8:51 AM
  • User-2106054853 posted

    Hi,

    I cannot test your code because definition of some classes are not provided, such as XMLViewerContainer. But from your code I think it's probably set in:

    protected override bool OnBubbleEvent(object source, EventArgs args)

    {

    bool handled = false;

    CommandEventArgs ce = args as CommandEventArgs;

    if (ce != null && ce.CommandName == "SwapView")

    {

    Debug.WriteLine("In SwapView handler");

    CurViewState = (CurViewState == VIEWSTATE.TEXT) ? VIEWSTATE.TREE : VIEWSTATE.TEXT;

    //LoadXMLFile();

    handled = true;

    }

    else if (ce != null && ce.CommandName == "SaveXml")

    {

    OnSaveXml(
    new SaveXmlEventArgs(TextBoxText));handled = true;

    }

    return handled;

    }

    You can set breakpoints to debug. If you still cannot find it out you can upload a demo project to http://skydrive.live.com/ and paste the download link here for me to test.

    Sunday, May 31, 2009 11:34 PM
  • User192013029 posted

    well, it's not so much where it is being set but what the old value is when it is set the second time through OnBubble (see debug trace).

    thanx for the link. i'm currently trying to upload both the class library and container app projects..

    done..

    http://cid-cdf3a9c82254f846.skydrive.live.com/browse.aspx/.Public?uc=2

    Monday, June 1, 2009 11:13 AM
  • User192013029 posted

    thanx for the help Allen but i think i found the proper way to do this. it removes what looked to me like a timing issue..

    first i commented out the setting of CurViewState in the OnInit handler then i modified the get accessor as follows..

            public virtual VIEWSTATE CurViewState
    {
    get
    {
    if (ViewState["CurViewState"] != null)
    {
    VIEWSTATE curViewState = (VIEWSTATE)ViewState["CurViewState"];
    return curViewState;
    }
    else
    {
    return VIEWSTATE.TEXT;
    }
    }
    set
    {
    ViewState["CurViewState"] = value;
    }
    }

    feel kind of silly that all it took was a simple is null check but it works. the problem i think stemmed from the timing of when RenderContents checks CurViewState to determine what control to render vs when CurViewState is first set in OnBubble. obviously when the page is first rendered, Render executes but OnBubble doesn't since it only kicks off via the button click. the is null allowed me to return a valid indicator up until the button is clicked. since i wanted TEXT to be the default, i knew i could set it to TEXT since it's only null at start up.

    of course this doesn't explain why the value of CurViewState didn't stick between the OnInit and OnBubble events but i never believed that was the right way to do it anyway.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, June 1, 2009 9:45 PM