1 //------------------------------------------------------------------------------
2 // <copyright file="Form.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 using System.Web.Mobile;
8 using System.Web.UI;
9 using System.Collections;
10 using System.ComponentModel;
11 using System.ComponentModel.Design;
12 using System.Globalization;
13 using System.Security.Permissions;
14 
15 namespace System.Web.UI.MobileControls
16 {
17     /// <include file='doc\Form.uex' path='docs/doc[@for="Form"]/*' />
18     [
19         ControlBuilderAttribute(typeof(FormControlBuilder)),
20         DefaultEvent("Activate"),
21         Designer(typeof(System.Web.UI.Design.MobileControls.FormDesigner)),
22         DesignerAdapter(typeof(System.Web.UI.MobileControls.Adapters.HtmlFormAdapter)),
23         PersistChildren(true),
24         ToolboxData("<{0}:Form runat=\"server\"></{0}:Form>"),
25         ToolboxItem("System.Web.UI.Design.WebControlToolboxItem, " + AssemblyRef.SystemDesign)
26     ]
27     [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
28     [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
29     [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
30     public class Form : Panel, ITemplateable, IPostBackEventHandler
31     {
32 
33         private static readonly Object EventActivate         = new Object();
34         private static readonly Object EventDeactivate       = new Object();
35         private static readonly Object EventPaginated        = new Object();
36 
37         private PagerStyle _pagerStyle;
38         private int _cachedCurrentPage = -1;
39         private Panel _headerContainer = null;
40         private Panel _footerContainer = null;
41         private Panel _scriptContainer = null;
42 
43         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Form"]/*' />
Form()44         public Form()
45         {
46             _pagerStyle = new PagerStyle();
47             _pagerStyle.SetControl(this);
48         }
49 
50         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Title"]/*' />
51         /// <summary>
52         /// <para>
53         /// Gets or sets the title used to identify the form.
54         /// </para>
55         /// </summary>
56         /// <value>
57         /// <para>
58         /// The title may be rendered as part of the form, on devices
59         /// that support a title separate from page content (e.g., on
60         /// the title bar of a browser using the title tag in HTML).
61         /// </para>
62         /// </value>
63         [
64             Bindable(true),
65             DefaultValue(""),
66             MobileCategory(SR.Category_Appearance),
67             MobileSysDescription(SR.Form_Title)
68         ]
69         public String Title
70         {
71             get
72             {
73                 String s = (String) ViewState["Title"];
74                 return((s != null) ? s : String.Empty);
75             }
76             set
77             {
78                 ViewState["Title"] = value;
79             }
80         }
81 
82         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Method"]/*' />
83         [
84             Bindable(true),
85             DefaultValue(FormMethod.Post),
86             MobileCategory(SR.Category_Behavior),
87             MobileSysDescription(SR.Form_Method)
88         ]
89         public FormMethod Method
90         {
91             get
92             {
93                 Object o = ViewState["Method"];
94                 return ((o != null) ? (FormMethod)o : FormMethod.Post);
95             }
96             set
97             {
98                 ViewState["Method"] = value;
99             }
100         }
101 
102         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Action"]/*' />
103         [
104             Bindable(true),
105             DefaultValue(""),
106             Editor(typeof(System.Web.UI.Design.UrlEditor),
107                 typeof(System.Drawing.Design.UITypeEditor)),
108             MobileCategory(SR.Category_Behavior),
109             MobileSysDescription(SR.Form_Action)
110         ]
111         public String Action
112         {
113             get
114             {
115                 String s = (String) ViewState["Action"];
116                 return((s != null) ? s : String.Empty);
117             }
118             set
119             {
120                 ViewState["Action"] = value;
121             }
122         }
123 
124         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.PagerStyle"]/*' />
125         [
126             DefaultValue(null),
127             DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
128             MobileCategory(SR.Category_Style),
129             MobileSysDescription(SR.Form_PagerStyle),
130             NotifyParentProperty(true)
131         ]
132         public PagerStyle PagerStyle
133         {
134             get
135             {
136                 return _pagerStyle;
137             }
138         }
139 
140         /// <internalonly/>
RaisePostBackEvent(String eventArgument)141         protected void RaisePostBackEvent(String eventArgument)
142         {
143             // If the event argument is all numeric, then it's a pager event.
144 
145             bool notANumber = false;
146             int length = eventArgument.Length;
147             for (int i = 0; i < length; i++)
148             {
149                 char c = eventArgument[i];
150                 if (c < '0' || c > '9')
151                 {
152                     notANumber = true;
153                     break;
154                 }
155             }
156 
157             if (!notANumber && length > 0)
158             {
159                 try
160                 {
161                     int page = Int32.Parse(eventArgument, CultureInfo.InvariantCulture);
162                     if (page > 0)
163                     {
164                         int oldPage = _currentPage;
165                         if(_cachedCurrentPage == -1)
166                         {
167                             _currentPage = page;
168                             _cachedCurrentPage = page;
169                         }
170 
171                         // currentpage may != page if page is invalid
172                         OnPageChange(oldPage, _currentPage);
173                     }
174                     return;
175                 }
176                 catch
177                 {
178                     // Argument may be invalid number, so let adapter handle it.
179                 }
180             }
181 
182             Adapter.HandlePostBackEvent(eventArgument);
183         }
184 
185         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Activate"]/*' />
186         [
187             MobileCategory(SR.Category_Action),
188             MobileSysDescription(SR.Form_OnActivate)
189         ]
190         public event EventHandler Activate
191         {
192             add
193             {
194                 Events.AddHandler(EventActivate, value);
195             }
196             remove
197             {
198                 Events.RemoveHandler(EventActivate, value);
199             }
200         }
201 
202         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Deactivate"]/*' />
203         [
204             MobileCategory(SR.Category_Action),
205             MobileSysDescription(SR.Form_OnDeactivate)
206         ]
207         public event EventHandler Deactivate
208         {
209             add
210             {
211                 Events.AddHandler(EventDeactivate, value);
212             }
213             remove
214             {
215                 Events.RemoveHandler(EventDeactivate, value);
216             }
217         }
218 
219         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Paginated"]/*' />
220         [
221             MobileCategory(SR.Category_Action),
222             MobileSysDescription(SR.Form_OnPaginated)
223         ]
224         public event EventHandler Paginated
225         {
226             add
227             {
228                 Events.AddHandler(EventPaginated, value);
229             }
230             remove
231             {
232                 Events.RemoveHandler(EventPaginated, value);
233             }
234         }
235 
236         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Header"]/*' />
237         [
238             Bindable(false),
239             Browsable(false),
240             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
241         ]
242         public Panel Header
243         {
244             get
245             {
246                 return _headerContainer;
247             }
248         }
249 
250         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Footer"]/*' />
251         [
252             Bindable(false),
253             Browsable(false),
254             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
255         ]
256         public Panel Footer
257         {
258             get
259             {
260                 return _footerContainer;
261             }
262         }
263 
264         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Script"]/*' />
265         [
266             Bindable(false),
267             Browsable(false),
268             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
269         ]
270         public Panel Script
271         {
272             get
273             {
274                 return _scriptContainer;
275             }
276         }
277 
278         internal bool Activated = false;
279 
FireActivate(EventArgs e)280         internal void FireActivate(EventArgs e)
281         {
282             if (!Activated)
283             {
284                 Activated = true;
285                 OnActivate(e);
286             }
287         }
288 
FireDeactivate(EventArgs e)289         internal void FireDeactivate(EventArgs e)
290         {
291             if (Activated)
292             {
293                 Activated = false;
294                 OnDeactivate(e);
295             }
296         }
297 
298         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.OnActivate"]/*' />
OnActivate(EventArgs e)299         protected virtual void OnActivate(EventArgs e)
300         {
301             EventHandler onActivate = (EventHandler)Events[EventActivate];
302             if (onActivate != null)
303             {
304                 onActivate(this, e);
305             }
306         }
307 
308         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.OnDeactivate"]/*' />
OnDeactivate(EventArgs e)309         protected virtual void OnDeactivate(EventArgs e)
310         {
311             EventHandler onDeactivate = (EventHandler)Events[EventDeactivate];
312             if (onDeactivate != null)
313             {
314                 onDeactivate(this, e);
315             }
316         }
317 
318         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.HasActivateHandler"]/*' />
HasActivateHandler()319         public virtual bool HasActivateHandler()
320         {
321             return Events[EventActivate] != null;
322         }
323 
324         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.HasDeactivateHandler"]/*' />
HasDeactivateHandler()325         public virtual bool HasDeactivateHandler()
326         {
327             return Events[EventDeactivate] != null;
328         }
329 
330         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.OnPaginated"]/*' />
OnPaginated(EventArgs e)331         protected virtual void OnPaginated(EventArgs e)
332         {
333             EventHandler onPaginated = (EventHandler)Events[EventPaginated];
334             if (onPaginated != null)
335             {
336                 onPaginated(this, e);
337             }
338         }
339 
340         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.OnInit"]/*' />
OnInit(EventArgs e)341         protected override void OnInit(EventArgs e)
342         {
343             if (MobilePage != null && !MobilePage.DesignMode)
344             {
345                 // Be sure we're not included in any other Forms.
346                 for (Control control = this.Parent; control != null; control = control.Parent)
347                 {
348                     Form parentForm = control as Form;
349                     if (parentForm != null)
350                     {
351                         throw new Exception(SR.GetString(SR.Form_NestedForms,
352                             this.ID,
353                             parentForm.ID));
354                     }
355                 }
356             }
357 
358             base.OnInit(e);
359         }
360 
361         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.GetLinkedForms"]/*' />
GetLinkedForms(int optimumPageWeight)362         public IList GetLinkedForms(int optimumPageWeight)
363         {
364             // Always add itself to the list as the first one
365             UniqueSet set = new UniqueSet();
366             set.Add(this);
367 
368             // If the form has a deactivate handler, then we
369             // can't send the form with linked forms, because server interaction
370             // is necessary to move between forms.
371 
372             if (HasDeactivateHandler())
373             {
374                 return set;
375             }
376 
377             // Will stop once no new forms are added in a pass, or has
378             // reached the optimum page weight.
379 
380             int totalWeight = 0;
381             int i;
382 
383             // negative means the caller doesn't care about the weight
384             bool checkWeight = optimumPageWeight >= 0;
385 
386             for (i = 0; i < set.Count; i++)
387             {
388                 Form form = (Form)set[i];
389 
390                 if (checkWeight)
391                 {
392                     totalWeight += form.GetVisibleWeight();
393                     if (totalWeight > optimumPageWeight)
394                     {
395                         break;
396                     }
397                 }
398                 form.AddLinkedForms(set);
399             }
400 
401             // More forms may have been linked than the total weight allows.
402             // Remove these.
403 
404             if (i != 0 &&  // i == 0 means only one form is in the list
405                 i < set.Count)
406             {
407                 for (int j = set.Count - 1; j >= i; j--)
408                 {
409                     set.RemoveAt(j);
410                 }
411             }
412 
413             return set;
414         }
415 
416         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.CreateDefaultTemplatedUI"]/*' />
CreateDefaultTemplatedUI(bool doDataBind)417         public override void CreateDefaultTemplatedUI(bool doDataBind)
418         {
419             ITemplate headerTemplate = GetTemplate(Constants.HeaderTemplateTag);
420             ITemplate footerTemplate = GetTemplate(Constants.FooterTemplateTag);
421             ITemplate scriptTemplate = GetTemplate(Constants.ScriptTemplateTag);
422 
423             if (scriptTemplate != null)
424             {
425                 _scriptContainer = new TemplateContainer();
426                 // The scriptTemplate is not added to the controls tree, so no need to do
427                 // CheckedInstantiateTemplate to check for infinite recursion.
428                 scriptTemplate.InstantiateIn(_scriptContainer);
429                 _scriptContainer.EnablePagination = false;
430             }
431 
432             if (headerTemplate != null)
433             {
434                 _headerContainer = new TemplateContainer();
435                 CheckedInstantiateTemplate (headerTemplate, _headerContainer, this);
436                 _headerContainer.EnablePagination = false;
437                 Controls.AddAt(0, _headerContainer);
438             }
439 
440             if (footerTemplate != null)
441             {
442                 _footerContainer = new TemplateContainer();
443                 CheckedInstantiateTemplate (footerTemplate, _footerContainer, this);
444                 _footerContainer.EnablePagination = false;
445                 Controls.Add(_footerContainer);
446             }
447 
448             // Do not call base.CreateDefaultTemplatedUI(), since we don't want
449             // Forms to have ContentTemplates as Panels do.
450         }
451 
452         private int _pageCount = -1;
453         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.PageCount"]/*' />
454         [
455             Bindable(false),
456             Browsable(false),
457             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
458         ]
459         public int PageCount
460         {
461             get
462             {
463                 // If not yet paginated, it's okay to return -1.
464 
465                 return _pageCount;
466             }
467         }
468 
469         private int _currentPage = 1;
470         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.CurrentPage"]/*' />
471         [
472             Bindable(false),
473             Browsable(false),
474             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
475         ]
476         public int CurrentPage
477         {
478             get
479             {
480                 return _currentPage;
481             }
482             set
483             {
484                 if (_currentPage != value)
485                 {
486                     OnPageChange (_currentPage, value);
487                 }
488                 _currentPage = value;
489                 _cachedCurrentPage = _currentPage;
490             }
491         }
492 
493         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.BreakAfter"]/*' />
494         [
495             Bindable(false),
496             Browsable(false),
497             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
498             EditorBrowsable(EditorBrowsableState.Never)
499         ]
500         public override bool BreakAfter
501         {
502             get
503             {
504                 if (MobilePage.DesignMode)
505                 {
506                     return true;
507                 }
508                 throw new Exception(
509                     SR.GetString(SR.Form_PropertyNotAccessible, "BreakAfter"));
510             }
511 
512             set
513             {
514                 throw new Exception(
515                     SR.GetString(SR.Form_PropertyNotSettable, "BreakAfter"));
516             }
517         }
518 
519         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.OnPreRender"]/*' />
OnPreRender(EventArgs e)520         protected override void OnPreRender(EventArgs e)
521         {
522             // AUI 3630
523             base.OnPreRender(e);
524 
525             _pageCount = PaginateForm();
526 
527             // Clamp to 1 < _currentPage <= PageCount
528 
529             int page = Math.Max(Math.Min(_currentPage, _pageCount), 1);
530             if(_currentPage != page)
531             {
532                 _currentPage = page;
533             }
534 
535             if ((Paginate) || (ControlToPaginate != null))
536             {
537                 OnPaginated(new EventArgs());
538             }
539         }
540 
541         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Render"]/*' />
Render(HtmlTextWriter writer)542         protected override void Render(HtmlTextWriter writer)
543         {
544             MobilePage.EnterFormRender(this);
545             OnRender(writer);
546             MobilePage.ExitFormRender();
547         }
548 
PaginateForm()549         private int PaginateForm()
550         {
551             int pageWeight = MobilePage.Adapter.OptimumPageWeight;
552             if (Header != null)
553             {
554                 pageWeight -= Header.VisibleWeight;
555             }
556             if (Footer != null)
557             {
558                 pageWeight -= Footer.VisibleWeight;
559             }
560             if (pageWeight <= 0)
561             {
562                 //
563 
564 
565                 pageWeight = MobilePage.Adapter.OptimumPageWeight / 2;
566             }
567 
568             if (IsFormPaginationAllowed())
569             {
570                 if ((Paginate) || (ControlToPaginate == this))
571                 {
572                     ControlPager pager = new ControlPager(this, pageWeight);
573                     base.PaginateRecursive(pager);
574                     return pager.PageCount;
575                 }
576                 else if(ControlToPaginate != null)
577                 {
578                     ControlPager pager = new ControlPager(this, pageWeight);
579                     SetControlPage(1);
580                     Control control = ControlToPaginate;
581                     MobileControl ctp = control as MobileControl;
582                     if(ctp != null)
583                     {
584                         ctp.PaginateRecursive(pager);
585                     }
586                     else
587                     {
588                         int firstAssignedPage = -1;
589                         DoPaginateChildren(pager, control, ref firstAssignedPage);
590                     }
591                     while(control != this)
592                     {
593                         MobileControl mc = control as MobileControl;
594                         if(mc != null)
595                         {
596                             if(mc is Form)
597                             {
598                                 throw(new Exception(SR.GetString(SR.Form_InvalidControlToPaginateForm)));
599                             }
600                             if (mc.FirstPage > ctp.FirstPage)
601                             {
602                                 mc.FirstPage = ctp.FirstPage;
603                             }
604                             if(mc.LastPage < ctp.LastPage)
605                             {
606                                 mc.LastPage = ctp.LastPage;
607                             }
608                         }
609                         control = control.Parent;
610                     }
611                     this.LastPage = Math.Max(pager.PageCount, 1);
612                     if(Header != null)
613                     {
614                         SetEnablePaginationRecursive(Header, false);
615                     }
616                     if(Footer != null)
617                     {
618                         SetEnablePaginationRecursive(Footer, false);
619                     }
620                     return this.LastPage;
621                 }
622             }
623 
624             return 1;
625         }
626 
IsFormPaginationAllowed()627         private bool IsFormPaginationAllowed()
628         {
629             // AUI 4721
630 
631             if (Action.Length == 0)
632             {
633                 return true;
634             }
635 
636             MobileCapabilities device = (MobileCapabilities)Page.Request.Browser;
637             String type = device.PreferredRenderingType;
638             bool javascriptSupported = device.JavaScript;
639 
640             return javascriptSupported ||
641                     (type != MobileCapabilities.PreferredRenderingTypeHtml32 &&
642                      type != MobileCapabilities.PreferredRenderingTypeChtml10);
643         }
644 
645         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.PaginateRecursive"]/*' />
PaginateRecursive(ControlPager pager)646         public override void PaginateRecursive(ControlPager pager)
647         {
648             _pageCount = PaginateForm();
649         }
650 
651         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.PaginateChildren"]/*' />
652         protected override bool PaginateChildren
653         {
654             get
655             {
656                 return true;
657             }
658         }
659 
660         private Control _controlToPaginate = null;
661 
662         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.ControlToPaginate"]/*' />
663         [
664             Bindable(false),
665             Browsable(false),
666             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
667         ]
668         public Control ControlToPaginate
669         {
670             get
671             {
672                 if(_controlToPaginate != null)
673                 {
674                     return _controlToPaginate;
675                 }
676                 if(ViewState["ControlToPaginate"] != null)
677                 {
678                     _controlToPaginate = Page.FindControl((ViewState["ControlToPaginate"]).ToString());
679                 }
680                 return _controlToPaginate;
681             }
682             set
683             {
684                 if(value != null)
685                 {
686                     ViewState["ControlToPaginate"] = value.UniqueID;
687                 }
688                 else
689                 {
690                     ViewState.Remove("ControlToPaginate");
691                 }
692                 _controlToPaginate = value;
693             }
694         }
695 
696         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.LoadPrivateViewState"]/*' />
LoadPrivateViewState(Object state)697         protected override void LoadPrivateViewState(Object state)
698         {
699             _currentPage = state != null ? (int)state : 1;
700         }
701 
702         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.SavePrivateViewState"]/*' />
SavePrivateViewState()703         protected override Object SavePrivateViewState()
704         {
705             int currentPage = _currentPage;
706             if (currentPage > 1 && this == MobilePage.ActiveForm)
707             {
708                 return currentPage;
709             }
710             else
711             {
712                 return null;
713             }
714         }
715 
716         /// <include file='doc\Form.uex' path='docs/doc[@for="Form.OnDataBinding"]/*' />
OnDataBinding(EventArgs e)717         protected override void OnDataBinding(EventArgs e)
718         {
719             if(Script != null)
720             {
721                 Script.DataBind();
722             }
723             base.OnDataBinding(e);
724         }
725 
726         private IPostBackEventHandler _defaultEventHandler = null;
RegisterEventHandler(IPostBackEventHandler control)727         internal void RegisterEventHandler(IPostBackEventHandler control)
728         {
729             if (_defaultEventHandler == null)
730             {
731                 _defaultEventHandler = control;
732             }
733         }
734 
735         internal IPostBackEventHandler DefaultEventHandler
736         {
737             get
738             {
739                 return _defaultEventHandler;
740             }
741         }
742 
InvalidateParentStyles()743         internal override void InvalidateParentStyles()
744         {
745             PagerStyle.InvalidateParentStyle();
746             base.InvalidateParentStyles();
747         }
748 
749         #region IPostBackEventHandler implementation
IPostBackEventHandler.RaisePostBackEvent(String eventArgument)750         void IPostBackEventHandler.RaisePostBackEvent(String eventArgument) {
751             RaisePostBackEvent(eventArgument);
752         }
753         #endregion
754     }
755 
756     /// <include file='doc\Form.uex' path='docs/doc[@for="FormControlBuilder"]/*' />
757     [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
758     [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
759     [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
760     public class FormControlBuilder : LiteralTextContainerControlBuilder
761     {
762         /// <include file='doc\Form.uex' path='docs/doc[@for="FormControlBuilder.AppendSubBuilder"]/*' />
AppendSubBuilder(ControlBuilder subBuilder)763         public override void AppendSubBuilder(ControlBuilder subBuilder)
764         {
765             Type controlType = subBuilder.ControlType;
766             if(!(
767                  (subBuilder.GetType().FullName == "System.Web.UI.CodeBlockBuilder") ||
768                  (typeof(MobileControl).IsAssignableFrom(controlType)) ||
769                  (typeof(UserControl).IsAssignableFrom(controlType)) ||
770                  (typeof(DeviceSpecific).IsAssignableFrom(controlType))
771                  ))
772             {
773                 throw(new Exception(SR.GetString(SR.Form_InvalidSubControlType, subBuilder.TagName)));
774             }
775             base.AppendSubBuilder(subBuilder);
776         }
777     }
778 }
779