1 //------------------------------------------------------------------------------
2 // <copyright file="MobileTemplatedControlDesigner.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 namespace System.Web.UI.Design.MobileControls
8 {
9     using System;
10     using System.Collections;
11     using System.ComponentModel;
12     using System.ComponentModel.Design;
13     using System.Diagnostics;
14     using System.Drawing;
15     using System.Drawing.Design;
16     using System.Globalization;
17     using System.Reflection;
18     using System.Text;
19     using System.Web.UI;
20     using System.Web.UI.Design;
21     using System.Web.UI.Design.MobileControls.Adapters;
22     using System.Web.UI.Design.MobileControls.Converters;
23     using System.Web.UI.Design.MobileControls.Util;
24     using System.Web.UI.MobileControls;
25     using System.Web.UI.MobileControls.Adapters;
26 
27     using WebCtrlStyle = System.Web.UI.WebControls.Style;
28     using DialogResult = System.Windows.Forms.DialogResult;
29 
30     [
31         System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand,
32         Flags=System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)
33     ]
34     [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.")]
35     internal abstract class MobileTemplatedControlDesigner : TemplatedControlDesigner, IMobileDesigner, IDeviceSpecificDesigner
36     {
37         #if TRACE
38             internal static BooleanSwitch TemplateableControlDesignerSwitch =
39                 new BooleanSwitch("MobileTemplatedControlDesigner", "Enable TemplateableControl designer general purpose traces.");
40         #endif
41 
42         private System.Windows.Forms.Control    _header;
43         private MobileControl                   _mobileControl;
44         private System.Web.UI.Control           _control;
45         private DesignerVerbCollection          _designerVerbs = null;
46         private DeviceSpecificChoice            _currentChoice = null;
47         private bool                            _containmentStatusDirty = true;
48         private ContainmentStatus               _containmentStatus;
49         private IDesignerHost                   _host;
50         private IWebFormsDocumentService        _iWebFormsDocumentService;
51         private IMobileWebFormServices          _iMobileWebFormServices;
52         private const String                    _htmlString = "html";
53         private TemplateEditingVerb[]           _templateVerbs;
54         private bool                            _templateVerbsDirty = true;
55         private const int                       _templateWidth = 275;
56 
57         private static readonly String _noChoiceText =
58             SR.GetString(SR.DeviceFilter_NoChoice);
59 
60         private static readonly String _defaultChoiceText =
61             SR.GetString(SR.DeviceFilter_DefaultChoice);
62 
63         private static readonly String _nonHtmlSchemaErrorMessage =
64             SR.GetString(SR.MobileControl_NonHtmlSchemaErrorMessage);
65 
66         private static readonly String _illFormedWarning =
67             SR.GetString(SR.TemplateFrame_IllFormedWarning);
68 
69         private const String _illFormedHtml =
70             "<DIV style=\"font-family:tahoma;font-size:8pt; COLOR: infotext; BACKGROUND-COLOR: infobackground\">{0}</DIV>";
71 
72         internal const String DefaultTemplateDeviceFilter = "__TemplateDeviceFilter__";
73         private const String _templateDeviceFilterPropertyName = "TemplateDeviceFilter";
74         private const String _appliedDeviceFiltersPropertyName = "AppliedDeviceFilters";
75         private const String _propertyOverridesPropertyName = "PropertyOverrides";
76         private const String _expressionsPropertyName = "Expressions";
77         private const String _defaultDeviceSpecificIdentifier = "unique";
78 
79         // used by DesignerAdapterUtil.GetMaxWidthToFit
80         // and needs to be exposed in object model because
81         // custom controls may need to access the value just like
82         // DesignerAdapterUtil.GetMaxWidthToFit does.
83         public virtual int TemplateWidth
84         {
85             get
86             {
87                 return _templateWidth;
88             }
89         }
90 
91         public override bool AllowResize
92         {
93             get
94             {
95                 // Non mobilecontrols (ie. DeviceSpecific) does not render templates, no need to resize.
96                 // When templates are not defined, we render a read-only fixed
97                 // size block. Once templates are defined or are being edited
98                 // the control should allow resizing.
99                 return InTemplateMode || (_mobileControl != null && _mobileControl.IsTemplated);
100             }
101         }
102 
103         private bool AllowTemplateEditing
104         {
105             get
106             {
107                 return (CurrentChoice != null && IsHTMLSchema(CurrentChoice) && !ErrorMode);
108             }
109         }
110 
111         [
112             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
113             Editor(typeof(AppliedDeviceFiltersTypeEditor), typeof(UITypeEditor)),
114             MergableProperty(false),
115             MobileCategory("Category_DeviceSpecific"),
116             MobileSysDescription(SR.MobileControl_AppliedDeviceFiltersDescription),
117             ParenthesizePropertyName(true),
118         ]
119         protected String AppliedDeviceFilters
120         {
121             get
122             {
123                 return String.Empty;
124             }
125         }
126 
127         protected ContainmentStatus ContainmentStatus
128         {
129             get
130             {
131                 if (!_containmentStatusDirty)
132                 {
133                     return _containmentStatus;
134                 }
135 
136                 _containmentStatus =
137                     DesignerAdapterUtil.GetContainmentStatus(_control);
138 
139                 _containmentStatusDirty = false;
140                 return _containmentStatus;
141             }
142         }
143 
144         public DeviceSpecificChoice CurrentChoice
145         {
146             get
147             {
148                 return _currentChoice;
149             }
150 
151             set
152             {
153                 if (_currentChoice != value)
154                 {
155                     SetTemplateVerbsDirty();
156 
157                     _currentChoice = value;
158                     OnCurrentChoiceChange();
159                 }
160             }
161         }
162 
163         public virtual DeviceSpecific CurrentDeviceSpecific
164         {
165             get
166             {
167                 if (null == _mobileControl)
168                 {
169                     return null;
170                 }
171 
172                 return _mobileControl.DeviceSpecific;
173             }
174         }
175 
176         internal Object DesignTimeElementInternal
177         {
178             get
179             {
180                 return typeof(HtmlControlDesigner).InvokeMember("DesignTimeElement",
181                     BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic,
182                     null, this, null, CultureInfo.InvariantCulture);
183             }
184         }
185 
186         public override bool DesignTimeHtmlRequiresLoadComplete
187         {
188             get
189             {
190                 return true;
191             }
192         }
193 
194         //
195 
196 
197         // Return true only when GetErrorMessage returns non-null string and
198         // it is not info mode (warning only).
199         protected virtual bool ErrorMode
200         {
201             get
202             {
203                 bool infoMode;
204                 return (GetErrorMessage(out infoMode) != null && !infoMode);
205             }
206         }
207 
208         protected IDesignerHost Host
209         {
210             get
211             {
212                 if (_host != null)
213                 {
214                     return _host;
215                 }
216                 _host = (IDesignerHost)GetService(typeof(IDesignerHost));
217                 Debug.Assert(_host != null);
218                 return _host;
219             }
220         }
221 
222         protected IMobileWebFormServices IMobileWebFormServices
223         {
224             get
225             {
226                 if (_iMobileWebFormServices == null)
227                 {
228                     _iMobileWebFormServices =
229                         (IMobileWebFormServices)GetService(typeof(IMobileWebFormServices));
230                 }
231 
232                 return _iMobileWebFormServices;
233             }
234         }
235 
236         private IWebFormsDocumentService IWebFormsDocumentService
237         {
238             get
239             {
240                 if (_iWebFormsDocumentService == null)
241                 {
242                     _iWebFormsDocumentService =
243                         (IWebFormsDocumentService)GetService(typeof(IWebFormsDocumentService));
244 
245                     Debug.Assert(_iWebFormsDocumentService != null);
246                 }
247 
248                 return _iWebFormsDocumentService;
249             }
250         }
251 
252         /// <summary>
253         ///     Indicates whether the initial page load is completed
254         /// </summary>
255         protected bool LoadComplete
256         {
257             get
258             {
259                 return !IWebFormsDocumentService.IsLoading;
260             }
261         }
262 
263         [
264             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
265             Editor(typeof(PropertyOverridesTypeEditor), typeof(UITypeEditor)),
266             MergableProperty(false),
267             MobileCategory("Category_DeviceSpecific"),
268             MobileSysDescription(SR.MobileControl_DeviceSpecificPropsDescription),
269             ParenthesizePropertyName(true),
270         ]
271         protected String PropertyOverrides
272         {
273             get
274             {
275                 return String.Empty;
276             }
277         }
278 
279         [
280             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
281             MobileSysDescription(SR.TemplateableDesigner_TemplateChoiceDescription),
282             TypeConverter(typeof(ChoiceConverter)),
283         ]
284         public String TemplateDeviceFilter
285         {
286             get
287             {
288                 if (null == CurrentChoice)
289                 {
290                     return _noChoiceText;
291                 }
292                 if (CurrentChoice.Filter.Length == 0)
293                 {
294                     return _defaultChoiceText;
295                 }
296                 else
297                 {
298                     return DesignerUtility.ChoiceToUniqueIdentifier(CurrentChoice);
299                 }
300             }
301             set
302             {
303                 if (String.IsNullOrEmpty(value) ||
304                     value.Equals(SR.GetString(SR.DeviceFilter_NoChoice)))
305                 {
306                     CurrentChoice = null;
307                     return;
308                 }
309 
310                 if (null == CurrentDeviceSpecific)
311                 {
312                     return;
313                 }
314 
315                 Debug.Assert(CurrentDeviceSpecific.Choices != null);
316 
317                 foreach (DeviceSpecificChoice choice in CurrentDeviceSpecific.Choices)
318                 {
319                     if (DesignerUtility.ChoiceToUniqueIdentifier(choice).Equals(value) ||
320                         (choice.Filter.Length == 0 &&
321                          value.Equals(SR.GetString(SR.DeviceFilter_DefaultChoice))))
322                     {
323                         CurrentChoice = choice;
324                         return;
325                     }
326                 }
327 
328                 CurrentChoice = null;
329             }
330         }
331 
332         private bool ValidContainment
333         {
334             get
335             {
336                 return (ContainmentStatus == ContainmentStatus.InForm ||
337                         ContainmentStatus == ContainmentStatus.InPanel ||
338                         ContainmentStatus == ContainmentStatus.InTemplateFrame);
339             }
340         }
341 
342         public override DesignerVerbCollection Verbs
343         {
344             get
345             {
346                 if (_designerVerbs == null)
347                 {
348                     _designerVerbs = new DesignerVerbCollection();
349 
350                     _designerVerbs.Add(new DesignerVerb(
351                         SR.GetString(SR.TemplateableDesigner_SetTemplatesFilterVerb),
352                         new EventHandler(this.OnSetTemplatesFilterVerb)));
353                 }
354 
355                 _designerVerbs[0].Enabled = !this.InTemplateMode;
356                 return _designerVerbs;
357             }
358         }
359 
360         protected WebCtrlStyle WebCtrlStyle
361         {
362             get
363             {
364                 WebCtrlStyle style = new WebCtrlStyle();
365 
366                 if (_mobileControl != null)
367                 {
368                     _mobileControl.Style.ApplyTo(style);
369                 }
370                 else
371                 {
372                     Debug.Assert(_control is DeviceSpecific);
373                     if (_control.Parent is Panel)
374                     {
375                         ((Panel)_control.Parent).Style.ApplyTo(style);
376                     }
377                 }
378 
379                 return style;
380             }
381         }
382 
383         [
384             Conditional("DEBUG")
385         ]
CheckTemplateName(String templateName)386         private void CheckTemplateName(String templateName)
387         {
388             Debug.Assert (
389                 templateName == Constants.HeaderTemplateTag ||
390                 templateName == Constants.FooterTemplateTag ||
391                 templateName == Constants.ItemTemplateTag ||
392                 templateName == Constants.AlternatingItemTemplateTag ||
393                 templateName == Constants.SeparatorTemplateTag ||
394                 templateName == Constants.ItemDetailsTemplateTag ||
395                 templateName == Constants.ContentTemplateTag);
396         }
397 
CreateTemplateEditingFrame(TemplateEditingVerb verb)398         protected override ITemplateEditingFrame CreateTemplateEditingFrame(TemplateEditingVerb verb)
399         {
400             ITemplateEditingService teService =
401                 (ITemplateEditingService)GetService(typeof(ITemplateEditingService));
402             Debug.Assert(teService != null,
403                 "How did we get this far without an ITemplateEditingService");
404 
405             String[] templateNames = GetTemplateFrameNames(verb.Index);
406             ITemplateEditingFrame editingFrame = teService.CreateFrame(
407                 this,
408                 TemplateDeviceFilter,
409                 templateNames,
410                 WebCtrlStyle,
411                 null /* we don't have template styles */);
412 
413             editingFrame.InitialWidth = _templateWidth;
414             return editingFrame;
415         }
416 
Dispose(bool disposing)417         protected override void Dispose(bool disposing)
418         {
419             if (disposing)
420             {
421                 DisposeTemplateVerbs();
422 
423                 if (IMobileWebFormServices != null)
424                 {
425                     // If the page is in loading mode, it means the remove is trigged by webformdesigner.
426                     if (IWebFormsDocumentService.IsLoading)
427                     {
428                         IMobileWebFormServices.SetCache(_control.ID, (Object) DefaultTemplateDeviceFilter, (Object) this.TemplateDeviceFilter);
429                     }
430                     else
431                     {
432                         // setting to null will remove the entry.
433                         IMobileWebFormServices.SetCache(_control.ID, (Object) DefaultTemplateDeviceFilter, null);
434                     }
435                 }
436             }
437 
438             base.Dispose(disposing);
439         }
440 
OnComponentChanged(Object sender, ComponentChangedEventArgs ce)441         public override void OnComponentChanged(Object sender, ComponentChangedEventArgs ce)
442         {
443             base.OnComponentChanged(sender, ce);
444 
445             MemberDescriptor member = ce.Member;
446             if (member != null &&
447                 member.GetType().FullName.Equals(Constants.ReflectPropertyDescriptorTypeFullName))
448             {
449                 PropertyDescriptor propDesc = (PropertyDescriptor)member;
450 
451                 switch (propDesc.Name)
452                 {
453                     case "ID":
454                     {
455                         // Update the dictionary of device filters stored in the page designer
456                         // setting to null will remove the entry.
457                         IMobileWebFormServices.SetCache(ce.OldValue.ToString(), (Object) DefaultTemplateDeviceFilter, null);
458                         break;
459                     }
460 
461                     case "BackColor":
462                     case "ForeColor":
463                     case "Font":
464                     case "StyleReference":
465                     {
466                         SetTemplateVerbsDirty();
467                         break;
468                     }
469                 }
470             }
471         }
472 
DisposeTemplateVerbs()473         private void DisposeTemplateVerbs()
474         {
475             if (_templateVerbs != null)
476             {
477                 for (int i = 0; i < _templateVerbs.Length; i++)
478                 {
479                     _templateVerbs[i].Dispose();
480                 }
481 
482                 _templateVerbs = null;
483                 _templateVerbsDirty = true;
484             }
485         }
486 
GetCachedTemplateEditingVerbs()487         protected override TemplateEditingVerb[] GetCachedTemplateEditingVerbs()
488         {
489             if (ErrorMode)
490             {
491                 return null;
492             }
493 
494             // dispose template verbs during template editing would cause exiting from editing mode
495             // without saving.
496             if (_templateVerbsDirty == true && !InTemplateMode)
497             {
498                 DisposeTemplateVerbs();
499 
500                 _templateVerbs = GetTemplateVerbs();
501                 _templateVerbsDirty = false;
502             }
503 
504             foreach(TemplateEditingVerb verb in _templateVerbs)
505             {
506                 verb.Enabled = AllowTemplateEditing;
507             }
508 
509             return _templateVerbs;
510         }
511 
512         // Gets the HTML to be used for the design time representation of the control runtime.
GetDesignTimeHtml()513         public sealed override String GetDesignTimeHtml()
514         {
515             if (!LoadComplete)
516             {
517                 return null;
518             }
519 
520             bool infoMode;
521             String errorMessage = GetErrorMessage(out infoMode);
522             SetStyleAttributes();
523 
524             if (null != errorMessage)
525             {
526                 return GetDesignTimeErrorHtml(errorMessage, infoMode);
527             }
528 
529             String designTimeHTML = null;
530 
531             // This is to avoiding cascading error rendering.
532             try
533             {
534                 designTimeHTML = GetDesignTimeNormalHtml();
535             }
536             catch (Exception ex)
537             {
538                 Debug.Fail(ex.ToString());
539                 designTimeHTML = GetDesignTimeErrorHtml(ex.Message, false);
540             }
541 
542             return designTimeHTML;
543         }
544 
GetDesignTimeErrorHtml(String errorMessage, bool infoMode)545         protected virtual String GetDesignTimeErrorHtml(String errorMessage, bool infoMode)
546         {
547             return DesignerAdapterUtil.GetDesignTimeErrorHtml(
548                 errorMessage, infoMode, _control, Behavior, ContainmentStatus);
549         }
550 
GetDesignTimeNormalHtml()551         protected virtual String GetDesignTimeNormalHtml()
552         {
553             return GetEmptyDesignTimeHtml();
554         }
555 
556         // We sealed this method because it will never be called
557         // by our designers under current structure.
GetErrorDesignTimeHtml(Exception e)558         protected override sealed String GetErrorDesignTimeHtml(Exception e)
559         {
560             return base.GetErrorDesignTimeHtml(e);
561         }
562 
GetErrorMessage(out bool infoMode)563         protected virtual String GetErrorMessage(out bool infoMode)
564         {
565             infoMode = false;
566 
567             if (!DesignerAdapterUtil.InMobileUserControl(_control))
568             {
569                 if (DesignerAdapterUtil.InUserControl(_control))
570                 {
571                     infoMode = true;
572                     return MobileControlDesigner._userControlWarningMessage;
573                 }
574 
575                 if (!DesignerAdapterUtil.InMobilePage(_control))
576                 {
577                     return MobileControlDesigner._mobilePageErrorMessage;
578                 }
579 
580                 if (!ValidContainment)
581                 {
582                     return MobileControlDesigner._formPanelContainmentErrorMessage;
583                 }
584             }
585 
586             if (CurrentChoice != null && !IsHTMLSchema(CurrentChoice))
587             {
588                 infoMode = true;
589                 return _nonHtmlSchemaErrorMessage;
590             }
591 
592             // Containment is valid, return null;
593             return null;
594         }
595 
596         /// <summary>
597         ///    <para>
598         ///       Gets the HTML to be persisted for the content present within the associated server control runtime.
599         ///    </para>
600         /// </summary>
601         /// <returns>
602         ///    <para>
603         ///       Persistable Inner HTML.
604         ///    </para>
605         /// </returns>
GetPersistInnerHtml()606         public override String GetPersistInnerHtml()
607         {
608             String persist = null;
609 
610             if (InTemplateMode)
611             {
612                 SaveActiveTemplateEditingFrame();
613             }
614 
615             if (IsDirty)
616             {
617                 persist = MobileControlPersister.PersistInnerProperties(Component, Host);
618             }
619 
620             if (InTemplateMode)
621             {
622                 IsDirty = true;
623             }
624 
625             return persist;
626         }
627 
GetTemplateContent( ITemplateEditingFrame editingFrame, String templateName, out bool allowEditing)628         public override String GetTemplateContent(
629             ITemplateEditingFrame editingFrame,
630             String templateName,
631             out bool allowEditing)
632         {
633             Debug.Assert(AllowTemplateEditing);
634 #if DEBUG
635             CheckTemplateName(templateName);
636 #endif
637             allowEditing = true;
638 
639             ITemplate template = null;
640             String templateContent = String.Empty;
641 
642             // Here we trust the TemplateVerbs to give valid template names
643             template = (ITemplate)CurrentChoice.Templates[templateName];
644 
645             if (template != null)
646             {
647                 templateContent = GetTextFromTemplate(template);
648                 if (!IsCompleteHtml(templateContent))
649                 {
650                     allowEditing = false;
651                     templateContent = String.Format(CultureInfo.CurrentCulture, _illFormedHtml, _illFormedWarning);
652                 }
653             }
654 
655             return templateContent;
656         }
657 
GetTemplateFrameNames(int index)658         protected abstract String[] GetTemplateFrameNames(int index);
659 
GetTemplateVerbs()660         protected abstract TemplateEditingVerb[] GetTemplateVerbs();
661 
662         /// <summary>
663         ///    <para>
664         ///       Initializes the designer.
665         ///    </para>
666         /// </summary>
667         /// <param name='component'>
668         ///    The control element being designed.
669         /// </param>
670         /// <remarks>
671         ///    <para>
672         ///       This is called by the designer host to establish the component being
673         ///       designed.
674         ///    </para>
675         /// </remarks>
676         /// <seealso cref='System.ComponentModel.Design.IDesigner'/>
Initialize(IComponent component)677         public override void Initialize(IComponent component)
678         {
679             Debug.Assert(component is System.Web.UI.MobileControls.MobileControl ||
680                          component is System.Web.UI.MobileControls.DeviceSpecific,
681                          "MobileTemplatedControlDesigner.Initialize - Invalid (Mobile) Control");
682 
683             base.Initialize(component);
684 
685             if (component is System.Web.UI.MobileControls.MobileControl)
686             {
687                 _mobileControl = (System.Web.UI.MobileControls.MobileControl) component;
688             }
689             // else the component is a DeviceSpecific control
690             _control = (System.Web.UI.Control) component;
691 
692             if (IMobileWebFormServices != null)
693             {
694                 this.TemplateDeviceFilter = (String) IMobileWebFormServices.GetCache(_control.ID, (Object)DefaultTemplateDeviceFilter);
695             }
696         }
697 
IsCompleteHtml(String templateContent)698         private bool IsCompleteHtml(String templateContent)
699         {
700             if (!String.IsNullOrEmpty(templateContent))
701             {
702                 return SimpleParser.IsWellFormed(templateContent);
703             }
704 
705             // if template is empty, it's always editable.
706             return true;
707         }
708 
IsHTMLSchema(DeviceSpecificChoice choice)709         protected bool IsHTMLSchema(DeviceSpecificChoice choice)
710         {
711             Debug.Assert(choice != null);
712 
713             return choice.Xmlns != null &&
714                 choice.Xmlns.ToLower(CultureInfo.InvariantCulture).IndexOf(_htmlString, StringComparison.Ordinal) != -1;
715         }
716 
717         // Notification that is called when current choice is changed, it is currently
718         // used to notify StyleSheet that template device filter is changed.
OnCurrentChoiceChange()719         protected virtual void OnCurrentChoiceChange()
720         {
721         }
722 
723         /// <summary>
724         ///    <para>
725         ///       Notification that is called when internal changes have been made.
726         ///    </para>
727         /// </summary>
OnInternalChange()728         protected virtual void OnInternalChange()
729         {
730             ISite site = _control.Site;
731             if (site != null)
732             {
733                 IComponentChangeService changeService =
734                     (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
735                 if (changeService != null)
736                 {
737                     try
738                     {
739                         changeService.OnComponentChanging(_control, null);
740                     }
741                     catch (CheckoutException ex)
742                     {
743                         if (ex == CheckoutException.Canceled)
744                         {
745                             return;
746                         }
747                         throw;
748                     }
749                     changeService.OnComponentChanged(_control, null, null, null);
750                 }
751             }
752         }
753 
754         /// <summary>
755         ///    <para>
756         ///       Notification that is called when the associated control is parented.
757         ///    </para>
758         /// </summary>
OnSetParent()759         public override void OnSetParent()
760         {
761             base.OnSetParent();
762 
763             // Template verbs may need to be refreshed
764             SetTemplateVerbsDirty();
765 
766             // this needs to be set before OnLoadComplete;
767             _containmentStatusDirty = true;
768 
769             if (LoadComplete)
770             {
771                 UpdateRendering();
772             }
773         }
774 
OnSetTemplatesFilterVerb(Object sender, EventArgs e)775         private void OnSetTemplatesFilterVerb(Object sender, EventArgs e)
776         {
777             ShowTemplatingOptionsDialog();
778         }
779 
OnTemplateModeChanged()780         protected override void OnTemplateModeChanged()
781         {
782             base.OnTemplateModeChanged();
783 
784             if (InTemplateMode)
785             {
786                 // Set xmlns in view linked document to show HTML intrinsic
787                 // controls in property grid with same schema used by
788                 // Intellisense for current choice tag in HTML view.
789 
790                 // This code won't work in Venus now since there are no viewlinks and
791                 // they don't support this kind of schema.
792                 /*
793                 NativeMethods.IHTMLElement htmlElement = (NativeMethods.IHTMLElement) ((IHtmlControlDesignerBehavior) Behavior).DesignTimeElementView;
794                 Debug.Assert(htmlElement != null,
795                     "Invalid HTML element in MobileTemplateControlDesigner.OnTemplateModeChanged");
796                 NativeMethods.IHTMLDocument2 htmlDocument2 = (NativeMethods.IHTMLDocument2) htmlElement.GetDocument();
797                 Debug.Assert(htmlDocument2 != null,
798                     "Invalid HTML Document2 in MobileTemplateControlDesigner.OnTemplateModeChanged");
799                 NativeMethods.IHTMLElement htmlBody = (NativeMethods.IHTMLElement) htmlDocument2.GetBody();
800                 Debug.Assert(htmlBody != null,
801                     "Invalid HTML Body in MobileTemplateControlDesigner.OnTemplateModeChanged");
802                 htmlBody.SetAttribute("xmlns", (Object) CurrentChoice.Xmlns, 0);
803                 */
804             }
805         }
806 
PreFilterProperties(IDictionary properties)807         protected override void PreFilterProperties(IDictionary properties)
808         {
809             base.PreFilterProperties(properties);
810 
811             // DesignTime Property only, we will use this to select choices.
812             properties[_templateDeviceFilterPropertyName] =
813                 TypeDescriptor.CreateProperty(this.GetType(),
814                 _templateDeviceFilterPropertyName,
815                 typeof(String),
816                 new DefaultValueAttribute(SR.GetString(SR.DeviceFilter_NoChoice)),
817                 MobileCategoryAttribute.Design,
818                 InTemplateMode ? BrowsableAttribute.No : BrowsableAttribute.Yes
819                 );
820 
821             // design time only entry used to display dialog box used to create choices.
822             properties[_appliedDeviceFiltersPropertyName] =
823                 TypeDescriptor.CreateProperty(this.GetType(),
824                 _appliedDeviceFiltersPropertyName,
825                 typeof(String),
826                 InTemplateMode? BrowsableAttribute.No : BrowsableAttribute.Yes
827                 );
828 
829             // design time only entry used to display dialog box to create choices.
830             properties[_propertyOverridesPropertyName] =
831                 TypeDescriptor.CreateProperty(this.GetType(),
832                 _propertyOverridesPropertyName,
833                 typeof(String),
834                 InTemplateMode? BrowsableAttribute.No : BrowsableAttribute.Yes
835                 );
836 
837             PropertyDescriptor property = (PropertyDescriptor) properties[_expressionsPropertyName];
838             if (property != null) {
839                 properties[_expressionsPropertyName] = TypeDescriptor.CreateProperty(this.GetType(), property, BrowsableAttribute.No);
840             }
841         }
842 
SetStyleAttributes()843         protected virtual void SetStyleAttributes()
844         {
845             Debug.Assert(Behavior != null);
846             DesignerAdapterUtil.SetStandardStyleAttributes(Behavior, ContainmentStatus);
847         }
848 
SetTemplateContent( ITemplateEditingFrame editingFrame, String templateName, String templateContent)849         public override void SetTemplateContent(
850             ITemplateEditingFrame editingFrame,
851             String templateName,
852             String templateContent)
853         {
854             Debug.Assert(AllowTemplateEditing);
855 
856             // Debug build only checking
857             CheckTemplateName(templateName);
858 
859             ITemplate template = null;
860 
861             if ((templateContent != null) && (templateContent.Length != 0))
862             {
863                 template = GetTemplateFromText(templateContent);
864             }
865             else
866             {
867                 CurrentChoice.Templates.Remove(templateName);
868                 return;
869             }
870 
871             // Here we trust the TemplateVerbs to give valid template names
872             CurrentChoice.Templates[templateName] = template;
873         }
874 
SetTemplateVerbsDirty()875         protected internal void SetTemplateVerbsDirty()
876         {
877             _templateVerbsDirty = true;
878         }
879 
ShowTemplatingOptionsDialog()880         protected virtual void ShowTemplatingOptionsDialog()
881         {
882             IComponentChangeService changeService =
883                 (IComponentChangeService)GetService(typeof(IComponentChangeService));
884             if (changeService != null)
885             {
886                 try
887                 {
888                     changeService.OnComponentChanging(_control, null);
889                 }
890                 catch (CheckoutException ex)
891                 {
892                     if (ex == CheckoutException.Canceled)
893                     {
894                         return;
895                     }
896                     throw;
897                 }
898             }
899 
900             try
901             {
902                 TemplatingOptionsDialog dialog = new TemplatingOptionsDialog(
903                     this,
904                     _control.Site,
905                     MobileControlDesigner.MergingContextTemplates);
906                 dialog.ShowDialog();
907             }
908             finally
909             {
910                 if (changeService != null)
911                 {
912                     changeService.OnComponentChanged(_control, null, null, null);
913 
914                     if (IMobileWebFormServices != null)
915                     {
916                         IMobileWebFormServices.ClearUndoStack();
917                     }
918                 }
919             }
920         }
921 
UpdateRendering()922         public void UpdateRendering()
923         {
924             if (!(null == _mobileControl || _mobileControl is StyleSheet))
925             {
926                 _mobileControl.RefreshStyle();
927             }
928 
929             // template editing frame need to be recreated because the style
930             // (WebCtrlStyle) to use may have to change
931             SetTemplateVerbsDirty();
932 
933             if (!InTemplateMode)
934             {
935                 UpdateDesignTimeHtml();
936             }
937         }
938 
939         ////////////////////////////////////////////////////////////////////////
940         //  Begin IDeviceSpecificDesigner Implementation
941         ////////////////////////////////////////////////////////////////////////
942 
IDeviceSpecificDesigner.SetDeviceSpecificEditor(IRefreshableDeviceSpecificEditor editor)943         void IDeviceSpecificDesigner.SetDeviceSpecificEditor
944             (IRefreshableDeviceSpecificEditor editor)
945         {
946         }
947 
948         String IDeviceSpecificDesigner.CurrentDeviceSpecificID
949         {
950             get
951             {
952                 return _defaultDeviceSpecificIdentifier;
953             }
954         }
955 
956         System.Windows.Forms.Control IDeviceSpecificDesigner.Header
957         {
958             get
959             {
960                 return _header;
961             }
962         }
963 
964         System.Web.UI.Control IDeviceSpecificDesigner.UnderlyingControl
965         {
966             get
967             {
968                 return _control;
969             }
970         }
971 
972         Object IDeviceSpecificDesigner.UnderlyingObject
973         {
974             get
975             {
976                 return _control;
977             }
978         }
979 
IDeviceSpecificDesigner.InitHeader(int mergingContext)980         void IDeviceSpecificDesigner.InitHeader(int mergingContext)
981         {
982             HeaderPanel panel = new HeaderPanel();
983             HeaderLabel lblDescription = new HeaderLabel();
984 
985             lblDescription.TabIndex = 0;
986             lblDescription.Height = 24;
987             lblDescription.Width = 204;
988             panel.Height = 28;
989             panel.Width = 204;
990             panel.Controls.Add(lblDescription);
991 
992             switch (mergingContext)
993             {
994                 case MobileControlDesigner.MergingContextTemplates:
995                 {
996                     lblDescription.Text = SR.GetString(SR.TemplateableDesigner_SettingTemplatingChoiceDescription);
997                     break;
998                 }
999 
1000                 default:
1001                 {
1002                     lblDescription.Text = SR.GetString(SR.TemplateableDesigner_SettingGenericChoiceDescription);
1003                     break;
1004                 }
1005             }
1006 
1007             _header = panel;
1008         }
1009 
IDeviceSpecificDesigner.RefreshHeader(int mergingContext)1010         void IDeviceSpecificDesigner.RefreshHeader(int mergingContext)
1011         {
1012         }
1013 
IDeviceSpecificDesigner.GetDeviceSpecific(String deviceSpecificParentID, out DeviceSpecific ds)1014         bool IDeviceSpecificDesigner.GetDeviceSpecific(String deviceSpecificParentID, out DeviceSpecific ds)
1015         {
1016             Debug.Assert(_defaultDeviceSpecificIdentifier == deviceSpecificParentID);
1017             ds = CurrentDeviceSpecific;
1018             return true;
1019         }
1020 
IDeviceSpecificDesigner.SetDeviceSpecific(String deviceSpecificParentID, DeviceSpecific ds)1021         void IDeviceSpecificDesigner.SetDeviceSpecific(String deviceSpecificParentID, DeviceSpecific ds)
1022         {
1023             Debug.Assert(_defaultDeviceSpecificIdentifier == deviceSpecificParentID);
1024 
1025             if (_mobileControl != null)
1026             {
1027                 if (null != ds)
1028                 {
1029                     ds.SetOwner(_mobileControl);
1030                 }
1031                 _mobileControl.DeviceSpecific = ds;
1032             }
1033             else if (_control != null && ds == null)
1034             {
1035                 Debug.Assert(_control is DeviceSpecific);
1036 
1037                 // Clear the choices if it is a DeviceSpecific control.
1038                 ((DeviceSpecific)_control).Choices.Clear();
1039             }
1040 
1041             if (null != CurrentChoice)
1042             {
1043                 if (null == ds)
1044                 {
1045                     CurrentChoice = null;
1046                 }
1047                 else
1048                 {
1049                     // This makes sure that the CurrentChoice value is set to null if
1050                     // it was deleted during the deviceSpecific object editing
1051                     if (CurrentChoice.Filter.Length == 0)
1052                     {
1053                         TemplateDeviceFilter = SR.GetString(SR.DeviceFilter_DefaultChoice);
1054                     }
1055                     else
1056                     {
1057                         TemplateDeviceFilter = DesignerUtility.ChoiceToUniqueIdentifier(CurrentChoice);
1058                     }
1059                 }
1060             }
1061         }
1062 
IDeviceSpecificDesigner.UseCurrentDeviceSpecificID()1063         void IDeviceSpecificDesigner.UseCurrentDeviceSpecificID()
1064         {
1065         }
1066 
1067         ////////////////////////////////////////////////////////////////////////
1068         //  End IDeviceSpecificDesigner Implementation
1069         ////////////////////////////////////////////////////////////////////////
1070 
1071         // Hack : Internal class used to provide TemplateContainerAttribute for Templates.
1072         [
1073             System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand,
1074             Flags=System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)
1075         ]
1076         [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.")]
1077     internal class TemplateContainer
1078         {
1079             [
1080                 TemplateContainer(typeof(MobileListItem))
1081             ]
1082             internal ITemplate HeaderTemplate
1083             {
1084                 get {return null;}
1085             }
1086 
1087             [
1088                 TemplateContainer(typeof(MobileListItem))
1089             ]
1090             internal ITemplate FooterTemplate
1091             {
1092                 get {return null;}
1093             }
1094 
1095             [
1096                 TemplateContainer(typeof(MobileListItem))
1097             ]
1098             internal ITemplate ItemTemplate
1099             {
1100                 get {return null;}
1101             }
1102 
1103             [
1104                 TemplateContainer(typeof(MobileListItem))
1105             ]
1106             internal ITemplate AlternatingItemTemplate
1107             {
1108                 get {return null;}
1109             }
1110 
1111             [
1112                 TemplateContainer(typeof(MobileListItem))
1113             ]
1114             internal ITemplate SeparatorTemplate
1115             {
1116                 get {return null;}
1117             }
1118 
1119             [
1120                 TemplateContainer(typeof(MobileListItem))
1121             ]
1122             internal ITemplate ContentTemplate
1123             {
1124                 get {return null;}
1125             }
1126 
1127             [
1128                 TemplateContainer(typeof(MobileListItem))
1129             ]
1130             internal ITemplate LabelTemplate
1131             {
1132                 get {return null;}
1133             }
1134 
1135             [
1136                 TemplateContainer(typeof(MobileListItem))
1137             ]
1138             internal ITemplate ItemDetailsTemplate
1139             {
1140                 get {return null;}
1141             }
1142         }
1143     }
1144 }
1145