.NET Forum / Windows Forms / Design Time / April 2007
How to skip execution during Design Time?
|
|
Thread rating:  |
Dave Leach - 23 Mar 2007 19:02 GMT I am writing a Windows Forms application using .NET 1.1, VS 2003 and C#.
There is a section of code in one of my form's constructors that needs to be skipped over if the constructor is being called at design time.
Is there a way to conditionally execute this code only at runtime and not at design time?
Thanks, Dave
 Signature Dave Leach Agilent Technologies, Inc.
Sergey M - 24 Mar 2007 04:11 GMT > There is a section of code in one of my form's constructors that > needs to be > skipped over if the constructor is being called at design time. You can check form's Site.DesignMode property, which is set to true at design time. The caveat there is that constructor is too early to check for that as component is not yet sited at that point. You could try overriding OnLoad() to see if that helps.
 Signature Sergey Mishkovskiy http://www.usysware.com/dpack/ - DPack - free VS add-ons http://www.usysware.com/blog/
Linda Liu [MSFT] - 26 Mar 2007 05:46 GMT Hi Dave,
Firstly, when we open a form in the designer, the code in the form's constructor won't be called.
You have mentioned that you have a section of code in one of your form's constructors that needs to be skipped over if the constructor is being called at design time. It seems that the section of code must be in a base form's constructor, and what you open in the form designer is an inherited form.
It's no use to make use of the form's DesignMode property in the constructor to determine whether it is at design time or run time, because the Site property of the form has not been assigned when the form is being constructed. The DesignMode property of the form always returns false when we get its value in the constructor.
When the form's Load event handler is called, the form has already finished the construction and the DesignMode property has a valid value. So the solution is to move the section of code that you need to prevent from being executed at design time to the form's Load event handler, and add a condition of "! this.DesignMode" on the section of code.
Alternatively, you could implement the ISupportInitialize interface for the base form and move the section of code to either of the ISupportInitialize members -- BeginInit or EndInit method (of course, you still need to add "! this.DesignMode" condition on the section of code).
When the base form implements the ISupportInitialize interface and we open the inherited form in the designer, the code to call the ISupportInitialize.BeginInit and ISupportInitilize.EndInit methods are serialized in the InitializeComponent method of the inherited form. When the ISupportInitialize.BeginInit or ISupportInitialize.EndInit method is executed, the base form has already finished the construction, thus the DesignMode property returns a valid value at this time.
Hope this helps. If you have anything unclear, please feel free to let me know.
Sincerely, Linda Liu Microsoft Online Community Support
================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Dave Leach - 28 Mar 2007 01:59 GMT Linda,
I have experimented with the ISupportInitialize interface, but without success. I have copied some very simplified code below to demonstrate how I have tried to use this interface. Note that I am applying the interface to a derived control instead of the derived form as the original message stated. This seemed like the more correct location for my application.
When I try to display the "DerivedForm" with the Forms Designer, the code that causes the assert is still being reached, even though that code is called from the EndInit() method and includes a test for DesignMode.
Please look at the code below and let me know if I am missing something.
Thanks, Dave
===============Code Starts Here================= public class MyPanelBase : System.Windows.Forms.UserControl, ISupportInitialize { public MyPanelBase() { InitializeComponent(); }
protected virtual void FinishConstruction() { DoSomethingThatAssertsAtDesignTime(); }
// Virtual method overridden by derived class. protected virtual void DoSomethingThatAssertsAtDesignTime() {}
public void BeginInit() {}
public void EndInit() { if ( !this.DesignMode ) { DoSomethingThatAssertsAtDesignTime(); } } }
public class DerivedPanel : MyPanelBase { public DerivedPanel() : base() { InitializeComponent(); }
protected override void DoSomethingThatAssertsAtDesignTime() { DoSomethingAtRuntime(); // Causes VS2003 Assert at DesignTime. }
private void InitializeComponent() { ((System.ComponentModel.ISupportInitialize)(this)).BeginInit(); this.SuspendLayout();
// Controls go here...
((System.ComponentModel.ISupportInitialize)(this)).EndInit(); this.ResumeLayout(false); } }
public class DerivedForm : ChildFormBase { private DerivedPanel myDerivedPanel;
public DerivedForm() : base() { InitializeComponent(); }
private void InitializeComponent() { this.myDerivedPanel = new DerivedPanel(); ((System.ComponentModel.ISupportInitialize)(this.myDerivedPanel)).BeginInit(); this.SuspendLayout(); // // myDerivedPanel // this.myDerivedPanel.Location = new System.Drawing.Point(0, 50); this.myDerivedPanel.Name = "myDerivedPanel"; this.myDerivedPanel.Size = new System.Drawing.Size(410, 140); this.myDerivedPanel.TabIndex = 0; // // DerivedForm // this.AutoScaleBaseSize = new System.Drawing.Size(7, 17); this.ClientSize = new System.Drawing.Size(432, 643); this.Controls.Add(this.myDerivedPanel); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "DerivedForm"; this.Text = "My Form"; ((System.ComponentModel.ISupportInitialize)(this.myDerivedPanel)).EndInit(); this.ResumeLayout(false); } } ===============Code Ends Here==================
 Signature Dave Leach Agilent Technologies, Inc.
> Hi Dave, > [quoted text clipped - 58 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. Linda Liu [MSFT] - 28 Mar 2007 04:46 GMT Hi Dave,
Thank you for your feedback and sample code.
I performed a test based on your sample code and did reproduce the problem on my side. To make things clear, I modify the code in the EndInit method within the MyPanelBase class as follows:
public class MyPanelBase : System.Windows.Forms.UserControl, ISupportInitialize { ..... public void EndInit() { // if ( !this.DesignMode ) // { // DoSomethingThatAssertsAtDesignTime(); // } MessageBox.Show("in EndInit: MyPanelBase.DesignMode=" + this.DesignMode.ToString()); } }
Buid the project and re-open the form that contains the DerivedPanel control. The result is that the message box pops up twice--for the first time, it shows "in EndInit: MyPanelBase.DesignMode=false" and for the second time, "in EndInit: MyPanelBase.DesignMode=true".
The reason why the EndInit method is called twice is that the statement "((System.ComponentModel.ISupportInitialize)(this)).EndInit();" is serialized in the InitializeComponent method within the DerivedPanel class as well as in the InitializeComponent method within the form that contains the DerivedPanel control.
When we open the form that contains the DerivedPanel, an instance of the DerivedPanel class is created, so the constructor of the DerivedPanel is called, which in turn calls the InitializeComponent method. Note that the instance of the DerivedPanel has not finished the construction, so the value of its DesignMode property is FALSE at this time.
When the InitializeComponent method of the form is called, the instance of the DerivedPanel has already finished the construction, so the DesignMode property of the DerivedPanel returns true.
As for your practice, I suggest that you move the section of code to the MyPanelBase's Load event handler. This event handler will be called only once and after the instance of the DerivedPanel has finished the construction.
Hope I make some clarification.
If you have anything unclear, please feel free to let me know.
Sincerely, Linda Liu Microsoft Online Community Support
Dave Leach - 28 Mar 2007 17:06 GMT Linda,
The suggestion to move a section of code to the Load event handler is not an acceptable solution. That section of code is related to our system initialization.
The initialization (at runtime) needs to execute at construction time for reasons related to the required system performance. We do not want the initialization to be deferred to the form's load time.
Is there another solution available other than ISupportInitialize (which appears to not be a solution)? Are there any other interfaces or attributes that could solve this problem?
Regards, Dave
 Signature Dave Leach Agilent Technologies, Inc.
> Hi Dave, > [quoted text clipped - 52 lines] > Linda Liu > Microsoft Online Community Support Linda Liu [MSFT] - 30 Mar 2007 09:56 GMT Hi Dave,
Thank you for your reply.
What I'd like to say is that it's a recommended way to place the section of code to the EndInit method to prevent it from being executed at design time.
This workaround works great in the case that you have a UserControl which has a section of code that needs to be executed at construction time as well as at run time.
However, this workaround doesn't work well for a more complex scenario, e.g. you derive a new control from the UserControl that implements the ISupportInitialize interface and then drag&drop the derived control onto a form in the designer.
As I have pointed out in my last reply, the key point of the problem is that the call to the EndInit method is serialized to the InitializeComponent method of the derived control, which I think may not necessary because the call to the EndInit method will be serialized to the InitializeComponent method of the form when we drag&drop the derived control onto it.
I'm sorry that I don't think there is a interface/attribute other than the ISupportInitialize interface that could solve this problem.
I suggest that you comment out the call to the EndInit method in the InitializeComponent method within the derived UserControl, and build the project , and then drag&drop the derived control onto a form in the designer.
Note that if you re-configure the derived UserControl in the designer, the code in the InitializeComponent will be refreshed by the designer automatically and the call the EndInit method will be serialized again. You should comment this code out and then build the project again.
Although it is not very elegant, it does work for your complex scenario.
If you have any concern, please feel free to let me know.
Sincerely, Linda Liu Microsoft Online Community Support
Dave Leach - 10 Apr 2007 18:38 GMT Linda,
Sorry I have not replied before now. I was on vacation last week. Before I left I came up with a solution that works, but I felt was a hack and commented it as such. Now I guess I'll remove the "hack" comment.
The solution was to add a static boolean that will only be set to true within our initialization code at run time. During design time this boolean is false and will prevent the code that generates the exception from being executed.
As for commenting out the call to the EndInit method: I will not take this approach as that requires future developers to somehow know to repeat that process any time they make changes to the derived UserControl using the forms designer.
You should consider this issue closed. I will clean-up and add appropriate comments to the static boolean solution I have implemented.
Regards, Dave
 Signature Dave Leach Agilent Technologies, Inc.
> Hi Dave, > [quoted text clipped - 40 lines] > Linda Liu > Microsoft Online Community Support Frank Hileman - 30 Mar 2007 13:25 GMT Hi Dave,
We have some experience in this area. The only safe assumption is to assume it is design-time during construction, until told otherwise. In run-time code call a method on a top-level object that is propagated to lower level objects (via collection iteration), informing all sub-objects it is not design-time, but run-time. You could create an interface containing this method.
That technique works even if your component is deep in a hierarchy. For example, placing a UserControl in another UserControl, and then placing it on a Form. In that case the lowest-level UserControl will never be marked DesignMode == true while editing the Form, even after construction.
A second approach is to use a static property or field available globally, signifying run-time mode. By default, it signals design-time mode, and is only set to run-time mode truly at run-time. In this case, as long as you initialize the field/property before any objects are constructed, you can refer to that mode even during construction, and it is accurate.
Regards, Frank Hileman
check out VG.net: http://www.vgdotnet.com Animated vector graphics system Integrated Visual Studio graphics editor
> Linda, > [quoted text clipped - 11 lines] > attributes > that could solve this problem? Dave Leach - 10 Apr 2007 18:48 GMT Frank,
Thanks for taking the time to post a reply. I implemented a similar solution to the one you have suggested, however at the time I considered it a hack. I was hoping that Microsoft had a solution for controlling execution during design time. Now I will be making my hack a permanent solution.
I am fortunate that our system design provides an ordered initialization sequence that I can take advantage of and guarantee that a static flag can be set before any of my forms or controls are constructed.
Thanks again, Dave
 Signature Dave Leach Agilent Technologies, Inc.
> Hi Dave, > [quoted text clipped - 38 lines] > > attributes > > that could solve this problem?
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|