OnCreateControl and DesignMode property

Posted by: makis1970 on 8 September 2017, 12:38 pm EST

  • Posted 8 September 2017, 12:38 pm EST

    Hello,


    I have implemented a derived spread control inheriting from FpSpread class. By overriding the OnCreateControl method and checking the DesignMode property, I initialize my custom control, adding a second sheet and setting some properties of the sheets such as column and row count, headers and so on. I ended up to this solution after reading a relative post in the forums and indeed, up to now, this worked as a charm. But after installing version 3 of the product that is not the case anymore. Without making any changes to the code implementation of my derived spread control, DesignMode property is now always false. At version 2.5, DesignMode was true when the control drops on a form and when I (re)build the project which suited my needs and this is the normal behavior for any control as I know. I am wondering if this is an issue on the new version of the product and/or whether I should use some other way of initializing my custom spread control to the state I need overriding some other method instead of OnCreateControl.


    Thanks in advance.

  • Replied 8 September 2017, 12:38 pm EST

    BobM, thanks for your help.


    Is there an estimate on when there will be a new product version released with the bug fixed?


    Thanks in advance.

  • Replied 8 September 2017, 12:38 pm EST

    I was able to reproduce this and have reported it as bug# 20724.
  • Replied 8 September 2017, 12:38 pm EST

    The developers response...

    "You should be able to force the creation of the control at any point that he needs, such as immediately after the Site gets set.  I would suggest he try adding some code in his OnCreateControl override to check the Site property and skip his initialization when it is null, then add code to override the Site property and force the control to be recreated when the Site is set with a non-null value by calling RecreateHandle."

  • Replied 8 September 2017, 12:38 pm EST

    Hi BobM,


    I can now confirm that although in ver2.5 the method OnCreateControl was called (or was forced to be called) when the host form of the spread control was shown, that is not the case in ver3 of the product; OnCreateControl is called (or forced to be called) at the constructor of the spread class and that is the source of the problem since DesignMode is always False within the constructor or from any code that the constructor calls.


    So, I don't see any point in overriding the Site property; if I keep my initialization code in OnCreateControl and it keeps beeing called by the constructor, DesignMode will be again and always False. Besides, DesignMode works correctly afterwards; I have shown it in the Property Browser of the spread control and it returns True.


    The change in the creation of the control has another side effect: I can't place my initialization code inside OnCreateControl event if I skipped checking the DesignMode property because the spread designer would crash (I need to add another sheet and that can't be done in constructor code, see thread http://www.clubfarpoint.com/Forums/forums/thread/38802.aspx).


    Is there another event or method I could use to do my initializing that you are aware of? For my part, I will check the solution that was posted on thread http://www.clubfarpoint.com/Forums/forums/thread/47106.aspx (I would prefer if EndInit was overridable by the way).


    Thanks in advance.

  • Replied 8 September 2017, 12:38 pm EST

    This came back as not a bug.  Here's what the develper had to say...

    "I do not think this is actually a bug.  Controls can force the creation of their window and children by calling CreateControl at any time.  I do not know exactly what has changed to make the new version force the creation of the window handle to happen at an earlier point than the old verison, but this change is not a breaking change.

    You should override the Site property if you need to determine when the control is in design mode."

  • Replied 8 September 2017, 12:38 pm EST

    I do not have an estimated date at this time. 
  • Replied 8 September 2017, 12:38 pm EST

    I have passed this on to the developer and will let you know if I hear back.
  • Replied 8 September 2017, 12:38 pm EST

    I will try and make sure that the developer that handles this offers as many suggestions as he can.
  • Replied 8 September 2017, 12:38 pm EST

    Hi BobM,


    first of all, I would like to thank you and the developing team for your help. I realize that implementing a custom ControlDesigner for my derived spread control is the best possible solution, but doing so is not so convenient, mainly due to the fact that the designer classes are not public.


    Since I can do what I want, either by implementing ISupportInitialize and declaring a EndInit method, or simply invoking my initialization code in my OnCreateControl override by using BeginInvoke, I'll stick to these solutions.


    If I ever encounter an issue that needs a custom designer defined, I will post back; besides, in that case, I will probably need your help.


    Best regards.

  • Replied 8 September 2017, 12:38 pm EST

    The developer had the following recommendations...

    I think it would be safer to implement ISupportInitialize and put your initialization code in the EndInit method, after calling the base class EndInit.  Then you know that your code will be called at the end of InitializeComponent.  You can do things to the sheets that are already there, or add new sheets, or replace the sheets with new ones, or whatever you need.  Part of the way IComponent objects (and this includes controls) get serialized to code at design time is, if the object also implements ISupportInitialize, then code gets generated to call its EndInit method at the end of InitializeComponent.

     

    Keep in mind that what you do will affect how the subclass works at design time.  The code serialization is not able to determine whether changes made to the control are made by a user at design time or by your code, so it will serialize everything to the InitializeComponent code when code gets generated for your subclass.  If your subclass is not intended for use at design time, then I would suggest not calling your code in design mode to prevent this redundant code getting generated.

     

    If you are intending for your subclass to be used at design time, then maybe you should move your code into a ControlDesigner class for your subclass.  That is the way to handle design time initialization and behavior of a control.  You could, for example, put code that initializes a new instance of the control once when it is first added to a form at design time, but not when it is created from code serialized to the form.  That is not generally recommended though, since it is not so easy to do.  The designer classes for FpSpread and SheetView are not public, so delegating to them would require some reflection calls to get the type names from the Designer attributes and create instances of them, which is not very convenient.

  • Replied 8 September 2017, 12:38 pm EST

    Hi BobM,


    I tried what your developer team suggested and was able to force control recreation after Site was assigned a non null value. There is a slight problem though; when OnCreateControl gets called (after the RecreateHandle call in the Site property override), the Sheets property of the spread is empty, thus I am not able to initialize the default sheet. Furthermore, if I manually try to add a sheet, I get a Visual Studio error message ("Duplicate component name...") after that, obviously when the spread control tries to add its default sheet.


    Carefully considering all the above facts, led me to a thought that I would like to share with you and the developer team. It seems that all my problems will be over if I somehow manage to call my initialization code after OnCreateControl method ends. So, I wrapped my initialization code in a delegate and used BeginInvoke to call it from the OnCreateControl override and, after some initial testing, it seems to work fine. And what's more, because DesignMode property is now working correctly, I don't even need to implement all the recreating handle thing.


    As I'm not sure if the above solution has any special implications, if your developer team thinks that problems might occur with this approach, please inform me.


    Thanks in advance.

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels