AspElements.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. //
  2. // System.Web.Compilation.AspElements
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. //
  7. // (C) 2002 Ximian, Inc (http://www.ximian.com)
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.Reflection;
  12. using System.Text;
  13. using System.Web.UI;
  14. using System.Web.UI.HtmlControls;
  15. using System.Web.UI.WebControls;
  16. namespace System.Web.Compilation
  17. {
  18. enum ElementType
  19. {
  20. TAG,
  21. PLAINTEXT
  22. }
  23. abstract class Element
  24. {
  25. private ElementType elementType;
  26. public Element (ElementType type)
  27. {
  28. elementType = type;
  29. }
  30. public ElementType GetElementType
  31. {
  32. get { return elementType; }
  33. }
  34. } // class Element
  35. class PlainText : Element
  36. {
  37. private StringBuilder text;
  38. public PlainText () : base (ElementType.PLAINTEXT)
  39. {
  40. text = new StringBuilder ();
  41. }
  42. public PlainText (StringBuilder text) : base (ElementType.PLAINTEXT)
  43. {
  44. this.text = text;
  45. }
  46. public PlainText (string text) : this ()
  47. {
  48. this.text.Append (text);
  49. }
  50. public void Append (string more)
  51. {
  52. text.Append (more);
  53. }
  54. public string Text
  55. {
  56. get { return text.ToString (); }
  57. }
  58. public override string ToString ()
  59. {
  60. return "PlainText: " + Text;
  61. }
  62. }
  63. enum TagType
  64. {
  65. DIRECTIVE,
  66. HTML,
  67. HTMLCONTROL,
  68. SERVERCONTROL,
  69. INLINEVAR,
  70. INLINECODE,
  71. CLOSING,
  72. SERVEROBJECT,
  73. PROPERTYTAG,
  74. CODERENDER,
  75. DATABINDING,
  76. SERVERCOMMENT,
  77. NOTYET
  78. }
  79. /*
  80. * Attributes and values are stored in a couple of ArrayList in Add ().
  81. * When MakeHash () is called, they are converted to a Hashtable. If there are any
  82. * attributes duplicated it throws an ArgumentException.
  83. *
  84. * The [] operator works with the Hashtable if the values are in it, otherwise
  85. * it uses the ArrayList's.
  86. *
  87. * Why? You can have a tag in HTML like <a att="value" att="xxx">, but not in tags
  88. * marked runat=server and Hashtable requires the key to be unique.
  89. *
  90. */
  91. class TagAttributes
  92. {
  93. private Hashtable atts_hash;
  94. private ArrayList keys;
  95. private ArrayList values;
  96. private bool got_hashed;
  97. public TagAttributes ()
  98. {
  99. got_hashed = false;
  100. keys = new ArrayList ();
  101. values = new ArrayList ();
  102. }
  103. private void MakeHash ()
  104. {
  105. atts_hash = new Hashtable (new CaseInsensitiveHashCodeProvider (),
  106. new CaseInsensitiveComparer ());
  107. for (int i = 0; i < keys.Count; i++)
  108. atts_hash.Add (keys [i], values [i]);
  109. got_hashed = true;
  110. keys = null;
  111. values = null;
  112. }
  113. public bool IsRunAtServer ()
  114. {
  115. return got_hashed;
  116. }
  117. public void Add (object key, object value)
  118. {
  119. if (key != null && value != null &&
  120. 0 == String.Compare ((string) key, "runat", true) &&
  121. 0 == String.Compare ((string) value, "server", true))
  122. MakeHash ();
  123. if (got_hashed)
  124. atts_hash.Add (key, value);
  125. else {
  126. keys.Add (key);
  127. values.Add (value);
  128. }
  129. }
  130. public ICollection Keys
  131. {
  132. get { return (got_hashed ? atts_hash.Keys : keys); }
  133. }
  134. private int CaseInsensitiveSearch (string key)
  135. {
  136. // Hope not to have many attributes when the tag is not a server tag...
  137. for (int i = 0; i < keys.Count; i++){
  138. if (0 == String.Compare ((string) keys [i], key, true))
  139. return i;
  140. }
  141. return -1;
  142. }
  143. public object this [object key]
  144. {
  145. get {
  146. if (got_hashed)
  147. return atts_hash [key];
  148. int idx = CaseInsensitiveSearch ((string) key);
  149. if (idx == -1)
  150. return null;
  151. return values [idx];
  152. }
  153. set {
  154. if (got_hashed)
  155. atts_hash [key] = value;
  156. else {
  157. int idx = CaseInsensitiveSearch ((string) key);
  158. keys [idx] = value;
  159. }
  160. }
  161. }
  162. public int Count
  163. {
  164. get { return (got_hashed ? atts_hash.Count : keys.Count);}
  165. }
  166. public bool IsDataBound (string att)
  167. {
  168. if (att == null || !got_hashed)
  169. return false;
  170. return (att.StartsWith ("<%#") && att.EndsWith ("%>"));
  171. }
  172. public override string ToString ()
  173. {
  174. string ret = "";
  175. string value;
  176. foreach (string key in Keys){
  177. value = (string) this [key];
  178. value = value == null ? "" : value;
  179. ret += key + "=" + value + " ";
  180. }
  181. return ret;
  182. }
  183. }
  184. class Tag : Element
  185. {
  186. protected string tag;
  187. protected TagType tagType;
  188. protected TagAttributes attributes;
  189. protected bool self_closing;
  190. protected bool hasDefaultID;
  191. private static int ctrlNumber = 1;
  192. internal Tag (ElementType etype) : base (etype) { }
  193. internal Tag (Tag other) :
  194. this (other.tag, other.attributes, other.self_closing)
  195. {
  196. this.tagType = other.tagType;
  197. }
  198. public Tag (string tag, TagAttributes attributes, bool self_closing) :
  199. base (ElementType.TAG)
  200. {
  201. if (tag == null)
  202. throw new ArgumentNullException ();
  203. this.tag = tag;
  204. this.attributes = attributes;
  205. this.tagType = TagType.NOTYET;
  206. this.self_closing = self_closing;
  207. this.hasDefaultID = false;
  208. }
  209. public string TagID
  210. {
  211. get { return tag; }
  212. }
  213. public TagType TagType
  214. {
  215. get { return tagType; }
  216. }
  217. public bool SelfClosing
  218. {
  219. get { return self_closing; }
  220. }
  221. public TagAttributes Attributes
  222. {
  223. get { return attributes; }
  224. }
  225. public string PlainHtml
  226. {
  227. get {
  228. StringBuilder plain = new StringBuilder ();
  229. plain.Append ('<');
  230. if (tagType == TagType.CLOSING)
  231. plain.Append ('/');
  232. plain.Append (tag);
  233. if (attributes != null){
  234. plain.Append (' ');
  235. foreach (string key in attributes.Keys){
  236. plain.Append (key);
  237. if (attributes [key] != null){
  238. plain.Append ("=\"");
  239. plain.Append ((string) attributes [key]);
  240. plain.Append ("\" ");
  241. }
  242. }
  243. }
  244. if (self_closing)
  245. plain.Append ('/');
  246. plain.Append ('>');
  247. return plain.ToString ();
  248. }
  249. }
  250. public override string ToString ()
  251. {
  252. return TagID + " " + Attributes + " " + self_closing;
  253. }
  254. public bool HasDefaultID
  255. {
  256. get { return hasDefaultID; }
  257. }
  258. protected virtual void SetNewID ()
  259. {
  260. if (attributes == null)
  261. attributes = new TagAttributes ();
  262. attributes.Add ("ID", GetDefaultID ());
  263. hasDefaultID = true;
  264. }
  265. public static string GetDefaultID ()
  266. {
  267. return "_control" + ctrlNumber++;
  268. }
  269. }
  270. class CloseTag : Tag
  271. {
  272. public CloseTag (string tag) : base (tag, null, false)
  273. {
  274. tagType = TagType.CLOSING;
  275. }
  276. }
  277. class Directive : Tag
  278. {
  279. private static Hashtable directivesHash;
  280. private static string [] page_atts = { "AspCompat", "AutoEventWireup ", "Buffer",
  281. "ClassName", "ClientTarget", "CodePage",
  282. "CompilerOptions", "ContentType", "Culture", "Debug",
  283. "Description", "EnableSessionState", "EnableViewState",
  284. "EnableViewStateMac", "ErrorPage", "Explicit",
  285. "Inherits", "Language", "LCID", "ResponseEncoding",
  286. "Src", "SmartNavigation", "Strict", "Trace",
  287. "TraceMode", "Transaction", "UICulture",
  288. "WarningLevel" };
  289. private static string [] control_atts = { "AutoEventWireup", "ClassName", "CompilerOptions",
  290. "Debug", "Description", "EnableViewState",
  291. "Explicit", "Inherits", "Language", "Strict", "Src",
  292. "WarningLevel" };
  293. private static string [] import_atts = { "namespace" };
  294. private static string [] implements_atts = { "interface" };
  295. private static string [] assembly_atts = { "name", "src" };
  296. private static string [] register_atts = { "tagprefix", "tagname", "Namespace",
  297. "Src", "Assembly" };
  298. private static string [] outputcache_atts = { "Duration", "Location", "VaryByControl",
  299. "VaryByCustom", "VaryByHeader", "VaryByParam" };
  300. private static string [] reference_atts = { "page", "control" };
  301. private static string [] webservice_atts = { "class", "codebehind", "debug", "language" };
  302. static Directive ()
  303. {
  304. InitHash ();
  305. }
  306. private static void InitHash ()
  307. {
  308. CaseInsensitiveHashCodeProvider provider = new CaseInsensitiveHashCodeProvider ();
  309. CaseInsensitiveComparer comparer = new CaseInsensitiveComparer ();
  310. directivesHash = new Hashtable (provider, comparer);
  311. // Use Hashtable 'cause is O(1) in Contains (ArrayList is O(n))
  312. Hashtable valid_attributes = new Hashtable (provider, comparer);
  313. foreach (string att in page_atts) valid_attributes.Add (att, null);
  314. directivesHash.Add ("PAGE", valid_attributes);
  315. valid_attributes = new Hashtable (provider, comparer);
  316. foreach (string att in control_atts) valid_attributes.Add (att, null);
  317. directivesHash.Add ("CONTROL", valid_attributes);
  318. valid_attributes = new Hashtable (provider, comparer);
  319. foreach (string att in import_atts) valid_attributes.Add (att, null);
  320. directivesHash.Add ("IMPORT", valid_attributes);
  321. valid_attributes = new Hashtable (provider, comparer);
  322. foreach (string att in implements_atts) valid_attributes.Add (att, null);
  323. directivesHash.Add ("IMPLEMENTS", valid_attributes);
  324. valid_attributes = new Hashtable (provider, comparer);
  325. foreach (string att in register_atts) valid_attributes.Add (att, null);
  326. directivesHash.Add ("REGISTER", valid_attributes);
  327. valid_attributes = new Hashtable (provider, comparer);
  328. foreach (string att in assembly_atts) valid_attributes.Add (att, null);
  329. directivesHash.Add ("ASSEMBLY", valid_attributes);
  330. valid_attributes = new Hashtable (provider, comparer);
  331. foreach (string att in outputcache_atts) valid_attributes.Add (att, null);
  332. directivesHash.Add ("OUTPUTCACHE", valid_attributes);
  333. valid_attributes = new Hashtable (provider, comparer);
  334. foreach (string att in reference_atts) valid_attributes.Add (att, null);
  335. directivesHash.Add ("REFERENCE", valid_attributes);
  336. valid_attributes = new Hashtable (provider, comparer);
  337. foreach (string att in webservice_atts) valid_attributes.Add (att, null);
  338. directivesHash.Add ("WEBSERVICE", valid_attributes);
  339. }
  340. public Directive (string tag, TagAttributes attributes) :
  341. base (tag, attributes, true)
  342. {
  343. CheckAttributes ();
  344. tagType = TagType.DIRECTIVE;
  345. }
  346. private void CheckAttributes ()
  347. {
  348. Hashtable atts;
  349. if (!(directivesHash [tag] is Hashtable))
  350. throw new ApplicationException ("Unknown directive: " + tag);
  351. atts = (Hashtable) directivesHash [tag];
  352. foreach (string att in attributes.Keys){
  353. if (!atts.Contains (att))
  354. throw new ApplicationException ("Attribute " + att +
  355. " not valid for tag " + tag);
  356. }
  357. }
  358. public static bool IsDirectiveID (string id)
  359. {
  360. return directivesHash.Contains (id);
  361. }
  362. public override string ToString ()
  363. {
  364. return "Directive: " + tag;
  365. }
  366. }
  367. class ServerObjectTag : Tag
  368. {
  369. public ServerObjectTag (Tag tag) :
  370. base (tag.TagID, tag.Attributes, tag.SelfClosing)
  371. {
  372. tagType = TagType.SERVEROBJECT;
  373. if (!attributes.IsRunAtServer ())
  374. throw new ApplicationException ("<object> without runat=server");
  375. if (attributes.Count != 3 || !SelfClosing || ObjectID == null || ObjectClass == null)
  376. throw new ApplicationException ("Incorrect syntax: <object id=\"name\" " +
  377. "class=\"full.class.name\" runat=\"server\" />");
  378. }
  379. public string ObjectID
  380. {
  381. get { return (string) attributes ["id"]; }
  382. }
  383. public string ObjectClass
  384. {
  385. get { return (string) attributes ["class"]; }
  386. }
  387. }
  388. class HtmlControlTag : Tag
  389. {
  390. private Type control_type;
  391. private bool is_container;
  392. private static Hashtable controls;
  393. private static Hashtable inputTypes;
  394. private static void InitHash ()
  395. {
  396. controls = new Hashtable (new CaseInsensitiveHashCodeProvider (),
  397. new CaseInsensitiveComparer ());
  398. controls.Add ("A", typeof (HtmlAnchor));
  399. controls.Add ("BUTTON", typeof (HtmlButton));
  400. controls.Add ("FORM", typeof (HtmlForm));
  401. controls.Add ("IMG", typeof (HtmlImage));
  402. controls.Add ("INPUT", "INPUT");
  403. controls.Add ("SELECT", typeof (HtmlSelect));
  404. controls.Add ("TABLE", typeof (HtmlTable));
  405. controls.Add ("TD", typeof (HtmlTableCell));
  406. controls.Add ("TH", typeof (HtmlTableCell));
  407. controls.Add ("TR", typeof (HtmlTableRow));
  408. controls.Add ("TEXTAREA", typeof (HtmlTextArea));
  409. inputTypes = new Hashtable (new CaseInsensitiveHashCodeProvider (),
  410. new CaseInsensitiveComparer ());
  411. inputTypes.Add ("BUTTON", typeof (HtmlInputButton));
  412. inputTypes.Add ("SUBMIT", typeof (HtmlInputButton));
  413. inputTypes.Add ("RESET", typeof (HtmlInputButton));
  414. inputTypes.Add ("CHECKBOX", typeof (HtmlInputCheckBox));
  415. inputTypes.Add ("FILE", typeof (HtmlInputFile));
  416. inputTypes.Add ("HIDDEN", typeof (HtmlInputHidden));
  417. inputTypes.Add ("IMAGE", typeof (HtmlInputImage));
  418. inputTypes.Add ("RADIO", typeof (HtmlInputRadioButton));
  419. inputTypes.Add ("TEXT", typeof (HtmlInputText));
  420. inputTypes.Add ("PASSWORD", typeof (HtmlInputText));
  421. }
  422. static HtmlControlTag ()
  423. {
  424. InitHash ();
  425. }
  426. public HtmlControlTag (string tag, TagAttributes attributes, bool self_closing) :
  427. base (tag, attributes, self_closing)
  428. {
  429. SetData ();
  430. if (attributes == null || attributes ["ID"] == null)
  431. SetNewID ();
  432. }
  433. public HtmlControlTag (Tag source_tag) :
  434. this (source_tag.TagID, source_tag.Attributes, source_tag.SelfClosing)
  435. {
  436. }
  437. private void SetData ()
  438. {
  439. tagType = TagType.HTMLCONTROL;
  440. if (!(controls [tag] is string)){
  441. control_type = (Type) controls [tag];
  442. if (control_type == null)
  443. control_type = typeof (HtmlGenericControl);
  444. is_container = (0 != String.Compare (tag, "img", true));
  445. } else {
  446. string type_value = (string) attributes ["TYPE"];
  447. if (type_value== null)
  448. throw new ArgumentException ("INPUT tag without TYPE attribute!!!");
  449. control_type = (Type) inputTypes [type_value];
  450. //TODO: what does MS with this one?
  451. if (control_type == null)
  452. throw new ArgumentException ("Unknown input type -> " + type_value);
  453. is_container = false;
  454. self_closing = true; // All <input ...> are self-closing
  455. }
  456. }
  457. public Type ControlType
  458. {
  459. get { return control_type; }
  460. }
  461. public string ControlID
  462. {
  463. get { return (string) attributes ["ID"]; }
  464. }
  465. public bool IsContainer
  466. {
  467. get { return is_container; }
  468. }
  469. public override string ToString ()
  470. {
  471. string ret = "HtmlControlTag: " + tag + " Name: " + ControlID + "Type:" +
  472. control_type.ToString () + "\n\tAttributes:\n";
  473. foreach (string key in attributes.Keys){
  474. ret += "\t" + key + "=" + attributes [key];
  475. }
  476. return ret;
  477. }
  478. }
  479. enum ChildrenKind
  480. {
  481. NONE,
  482. /*
  483. * Children must be ASP.NET server controls. Literal text is passed as LiteralControl.
  484. * Child controls and text are added using AddParsedSubObject ().
  485. */
  486. CONTROLS,
  487. /*
  488. * Children must correspond to properties of the parent control. No literal text allowed.
  489. */
  490. PROPERTIES,
  491. /*
  492. * Special case used inside <columns>...</columns>
  493. * Only allow DataGridColumn and derived classes.
  494. */
  495. DBCOLUMNS,
  496. /*
  497. * Special case for list controls (ListBox, DropDownList...)
  498. */
  499. LISTITEM,
  500. /* For HtmlSelect children. They are <option> tags that must
  501. * be treated as ListItem
  502. */
  503. OPTION
  504. }
  505. // TODO: support for ControlBuilderAttribute that may be used in custom controls
  506. class AspComponent : Tag
  507. {
  508. private Type type;
  509. private string alias;
  510. private string control_type;
  511. private bool is_close_tag;
  512. private bool allow_children;
  513. private ChildrenKind children_kind;
  514. private string defaultPropertyName;
  515. private ChildrenKind GuessChildrenKind (Type type)
  516. {
  517. object [] custom_atts = type.GetCustomAttributes (true);
  518. foreach (object custom_att in custom_atts){
  519. if (custom_att is ParseChildrenAttribute){
  520. /* FIXME
  521. * When adding full support for custom controls, we gotta
  522. * bear in mind the pca.DefaultProperty value
  523. */
  524. ParseChildrenAttribute pca = custom_att as ParseChildrenAttribute;
  525. defaultPropertyName = pca.DefaultProperty;
  526. /* this property will be true for all controls derived from
  527. * WebControls. */
  528. if (pca.ChildrenAsProperties == false)
  529. return ChildrenKind.CONTROLS;
  530. else if (defaultPropertyName == "")
  531. return ChildrenKind.PROPERTIES;
  532. else
  533. return ChildrenKind.LISTITEM;
  534. }
  535. }
  536. return ChildrenKind.NONE;
  537. }
  538. private static bool GuessAllowChildren (Type type)
  539. {
  540. PropertyInfo controls = type.GetProperty ("Controls");
  541. if (controls == null)
  542. return false;
  543. MethodInfo getm = controls.GetGetMethod ();
  544. object control_instance = Activator.CreateInstance (type);
  545. object control_collection = getm.Invoke (control_instance, null);
  546. return (!(control_collection is System.Web.UI.EmptyControlCollection));
  547. }
  548. public AspComponent (Tag input_tag, Type type) :
  549. base (input_tag)
  550. {
  551. tagType = TagType.SERVERCONTROL;
  552. this.is_close_tag = input_tag is CloseTag;
  553. this.type = type;
  554. this.defaultPropertyName = "";
  555. this.allow_children = GuessAllowChildren (type);
  556. if (input_tag.SelfClosing)
  557. this.children_kind = ChildrenKind.NONE;
  558. else if (type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
  559. type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)))
  560. this.children_kind = ChildrenKind.PROPERTIES;
  561. else if (type == typeof (System.Web.UI.WebControls.ListItem))
  562. this.children_kind = ChildrenKind.CONTROLS;
  563. else
  564. this.children_kind = GuessChildrenKind (type);
  565. int pos = input_tag.TagID.IndexOf (':');
  566. alias = tag.Substring (0, pos);
  567. control_type = tag.Substring (pos + 1);
  568. if (attributes == null || attributes ["ID"] == null)
  569. SetNewID ();
  570. }
  571. public Type ComponentType
  572. {
  573. get { return type; }
  574. }
  575. public string ControlID
  576. {
  577. get { return (string) attributes ["ID"]; }
  578. }
  579. public bool IsCloseTag
  580. {
  581. get { return is_close_tag; }
  582. }
  583. public bool AllowChildren
  584. {
  585. get { return allow_children; }
  586. }
  587. public ChildrenKind ChildrenKind
  588. {
  589. get { return children_kind; }
  590. }
  591. public string DefaultPropertyName
  592. {
  593. get { return defaultPropertyName; }
  594. }
  595. public override string ToString ()
  596. {
  597. return type.ToString () + " Alias: " + alias + " ID: " + (string) attributes ["id"];
  598. }
  599. }
  600. class PropertyTag : Tag
  601. {
  602. private Type type;
  603. private string name;
  604. public PropertyTag (Tag tag, Type type, string name)
  605. : base (tag)
  606. {
  607. tagType = TagType.PROPERTYTAG;
  608. SetNewID ();
  609. this.name = name;
  610. this.type = type;
  611. }
  612. public Type PropertyType
  613. {
  614. get { return type; }
  615. }
  616. public string PropertyID
  617. {
  618. get { return (string) attributes ["ID"]; }
  619. }
  620. public string PropertyName
  621. {
  622. get { return name; }
  623. }
  624. }
  625. class CodeRenderTag : Tag
  626. {
  627. private string code;
  628. private bool isVarName;
  629. public CodeRenderTag (bool isVarName, string code) : base ("", null, false)
  630. {
  631. tagType = TagType.CODERENDER;
  632. this.isVarName = isVarName;
  633. this.code = code.Trim ();
  634. }
  635. public string Code
  636. {
  637. get { return code; }
  638. }
  639. public bool IsVarName
  640. {
  641. get { return isVarName; }
  642. }
  643. public string AsText
  644. {
  645. get { return "<%" + (IsVarName ? "=" : "") + Code + "%>"; }
  646. }
  647. }
  648. class DataBindingTag : Tag
  649. {
  650. private string data;
  651. public DataBindingTag (string data) : base ("", null, false)
  652. {
  653. tagType = TagType.DATABINDING;
  654. this.data = data.Trim ();
  655. }
  656. public string Data
  657. {
  658. get { return data; }
  659. }
  660. public string AsText
  661. {
  662. get { return "<%#" + Data + "%>"; }
  663. }
  664. }
  665. class ServerComment : Tag
  666. {
  667. public ServerComment (string tag)
  668. : base (ElementType.TAG)
  669. {
  670. if (tag == null)
  671. throw new ArgumentNullException ();
  672. this.tag = tag;
  673. this.attributes = null;
  674. this.tagType = TagType.SERVERCOMMENT;
  675. this.self_closing = true;
  676. this.hasDefaultID = false;
  677. }
  678. public override string ToString ()
  679. {
  680. return TagID;
  681. }
  682. protected override void SetNewID ()
  683. {
  684. throw new NotSupportedException ();
  685. }
  686. }
  687. }