1 //------------------------------------------------------------------------------
2 // <copyright file="EditorZoneBase.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 namespace System.Web.UI.WebControls.WebParts {
10 using System.Collections;
11 using System.ComponentModel;
13 using System.Globalization;
15 using System.Web.UI.WebControls;
16 using System.Web.Util;
18 public abstract class EditorZoneBase : ToolZone {
20 private EditorPartCollection _editorParts;
22 private const int baseIndex = 0;
23 private const int applyVerbIndex = 1;
24 private const int cancelVerbIndex = 2;
25 private const int okVerbIndex = 3;
26 private const int viewStateArrayLength = 4;
28 private WebPartVerb _applyVerb;
29 private WebPartVerb _cancelVerb;
30 private WebPartVerb _okVerb;
32 private bool _applyError;
34 private EditorPartChrome _editorPartChrome;
36 private const string applyEventArgument = "apply";
37 private const string cancelEventArgument = "cancel";
38 private const string okEventArgument = "ok";
40 protected EditorZoneBase() : base(WebPartManager.EditDisplayMode) {
45 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
46 NotifyParentProperty(true),
47 PersistenceMode(PersistenceMode.InnerProperty),
49 WebSysDescription(SR.EditorZoneBase_ApplyVerb),
51 public virtual WebPartVerb ApplyVerb {
53 if (_applyVerb == null) {
54 _applyVerb = new WebPartEditorApplyVerb();
55 _applyVerb.EventArgument = applyEventArgument;
56 if (IsTrackingViewState) {
57 ((IStateManager)_applyVerb).TrackViewState();
66 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
67 NotifyParentProperty(true),
68 PersistenceMode(PersistenceMode.InnerProperty),
70 WebSysDescription(SR.EditorZoneBase_CancelVerb),
72 public virtual WebPartVerb CancelVerb {
74 if (_cancelVerb == null) {
75 _cancelVerb = new WebPartEditorCancelVerb();
76 _cancelVerb.EventArgument = cancelEventArgument;
77 if (IsTrackingViewState) {
78 ((IStateManager)_cancelVerb).TrackViewState();
86 protected override bool Display {
88 return (base.Display && WebPartToEdit != null);
94 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
96 public EditorPartChrome EditorPartChrome {
98 if (_editorPartChrome == null) {
99 _editorPartChrome = CreateEditorPartChrome();
101 return _editorPartChrome;
107 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
109 public EditorPartCollection EditorParts {
111 if (_editorParts == null) {
112 WebPart webPartToEdit = WebPartToEdit;
113 EditorPartCollection webPartEditorParts = null;
114 if (webPartToEdit != null && webPartToEdit is IWebEditable) {
115 webPartEditorParts = ((IWebEditable)webPartToEdit).CreateEditorParts();
118 EditorPartCollection editorParts = new EditorPartCollection(webPartEditorParts, CreateEditorParts());
120 // Verify that each EditorPart has a nonempty ID. Don't throw an exception in the designer,
121 // since we want only the offending control to render as an error block, not the whole CatalogZone.
123 foreach (EditorPart editorPart in editorParts) {
124 if (String.IsNullOrEmpty(editorPart.ID)) {
125 throw new InvalidOperationException(SR.GetString(SR.EditorZoneBase_NoEditorPartID));
130 _editorParts = editorParts;
132 // Call EnsureChildControls to parent the EditorParts and set the WebPartToEdit,
133 // WebPartManager, and Zone
134 EnsureChildControls();
142 WebSysDefaultValue(SR.EditorZoneBase_DefaultEmptyZoneText)
144 public override string EmptyZoneText {
145 // Must look at viewstate directly instead of the property in the base class,
146 // so we can distinguish between an unset property and a property set to String.Empty.
148 string s = (string)ViewState["EmptyZoneText"];
149 return((s == null) ? SR.GetString(SR.EditorZoneBase_DefaultEmptyZoneText) : s);
152 ViewState["EmptyZoneText"] = value;
158 WebCategory("Behavior"),
159 WebSysDefaultValue(SR.EditorZoneBase_DefaultErrorText),
160 WebSysDescription(SR.EditorZoneBase_ErrorText),
162 public virtual string ErrorText {
164 string s = (string)ViewState["ErrorText"];
165 return((s == null) ? SR.GetString(SR.EditorZoneBase_DefaultErrorText) : s);
168 ViewState["ErrorText"] = value;
173 WebSysDefaultValue(SR.EditorZoneBase_DefaultHeaderText)
175 public override string HeaderText {
177 string s = (string)ViewState["HeaderText"];
178 return((s == null) ? SR.GetString(SR.EditorZoneBase_DefaultHeaderText) : s);
181 ViewState["HeaderText"] = value;
186 WebSysDefaultValue(SR.EditorZoneBase_DefaultInstructionText),
188 public override string InstructionText {
190 string s = (string)ViewState["InstructionText"];
191 return((s == null) ? SR.GetString(SR.EditorZoneBase_DefaultInstructionText) : s);
194 ViewState["InstructionText"] = value;
200 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
201 NotifyParentProperty(true),
202 PersistenceMode(PersistenceMode.InnerProperty),
203 WebCategory("Verbs"),
204 WebSysDescription(SR.EditorZoneBase_OKVerb),
206 public virtual WebPartVerb OKVerb {
208 if (_okVerb == null) {
209 _okVerb = new WebPartEditorOKVerb();
210 _okVerb.EventArgument = okEventArgument;
211 if (IsTrackingViewState) {
212 ((IStateManager)_okVerb).TrackViewState();
219 protected WebPart WebPartToEdit {
221 if (WebPartManager != null && WebPartManager.DisplayMode == WebPartManager.EditDisplayMode) {
222 return WebPartManager.SelectedWebPart;
230 private void ApplyAndSyncChanges() {
231 WebPart webPartToEdit = WebPartToEdit;
232 Debug.Assert(webPartToEdit != null);
233 if (webPartToEdit != null) {
234 EditorPartCollection editorParts = EditorParts;
235 foreach (EditorPart editorPart in editorParts) {
236 if (editorPart.Display && editorPart.Visible && editorPart.ChromeState == PartChromeState.Normal) {
237 if (!editorPart.ApplyChanges()) {
243 foreach (EditorPart editorPart in editorParts) {
244 editorPart.SyncChanges();
251 /// Returns the Page to normal view. Does not call ApplyChanges to any EditorParts.
253 protected override void Close() {
254 if (WebPartManager != null) {
255 WebPartManager.EndWebPartEditing();
260 protected internal override void CreateChildControls() {
261 ControlCollection controls = Controls;
264 WebPart webPartToEdit = WebPartToEdit;
265 foreach (EditorPart editorPart in EditorParts) {
266 // webPartToEdit will be null if WebPartManager is null
267 if (webPartToEdit != null) {
268 editorPart.SetWebPartToEdit(webPartToEdit);
269 editorPart.SetWebPartManager(WebPartManager);
271 editorPart.SetZone(this);
272 controls.Add(editorPart);
276 protected virtual EditorPartChrome CreateEditorPartChrome() {
277 return new EditorPartChrome(this);
280 protected abstract EditorPartCollection CreateEditorParts();
282 // Called by a derived class if the list of EditorParts changes, and they want CreateEditorParts()
283 // to be called again.
284 protected void InvalidateEditorParts() {
286 ChildControlsCreated = false;
289 protected override void LoadViewState(object savedState) {
290 if (savedState == null) {
291 base.LoadViewState(null);
294 object[] myState = (object[]) savedState;
295 if (myState.Length != viewStateArrayLength) {
296 throw new ArgumentException(SR.GetString(SR.ViewState_InvalidViewState));
299 base.LoadViewState(myState[baseIndex]);
300 if (myState[applyVerbIndex] != null) {
301 ((IStateManager) ApplyVerb).LoadViewState(myState[applyVerbIndex]);
303 if (myState[cancelVerbIndex] != null) {
304 ((IStateManager) CancelVerb).LoadViewState(myState[cancelVerbIndex]);
306 if (myState[okVerbIndex] != null) {
307 ((IStateManager) OKVerb).LoadViewState(myState[okVerbIndex]);
312 protected override void OnDisplayModeChanged(object sender, WebPartDisplayModeEventArgs e) {
313 InvalidateEditorParts();
314 base.OnDisplayModeChanged(sender, e);
317 protected internal override void OnPreRender(EventArgs e) {
320 EditorPartChrome.PerformPreRender();
323 protected override void OnSelectedWebPartChanged(object sender, WebPartEventArgs e) {
324 if (WebPartManager != null && WebPartManager.DisplayMode == WebPartManager.EditDisplayMode) {
325 InvalidateEditorParts();
327 // SelectedWebPartChanged is raised when a WebPart is entering or exiting Edit mode.
328 // We only want to call SyncChanges when a WebPart is entering Edit mode
329 // (e.WebPart will be non-null).
330 if (e.WebPart != null) {
331 foreach (EditorPart editorPart in EditorParts) {
332 editorPart.SyncChanges();
337 base.OnSelectedWebPartChanged(sender, e);
340 protected override void RaisePostBackEvent(string eventArgument) {
341 if (String.Equals(eventArgument, applyEventArgument, StringComparison.OrdinalIgnoreCase)) {
342 if (ApplyVerb.Visible && ApplyVerb.Enabled && WebPartToEdit != null) {
343 ApplyAndSyncChanges();
346 else if (String.Equals(eventArgument, cancelEventArgument, StringComparison.OrdinalIgnoreCase)) {
347 if (CancelVerb.Visible && CancelVerb.Enabled && WebPartToEdit != null) {
351 else if (String.Equals(eventArgument, okEventArgument, StringComparison.OrdinalIgnoreCase)) {
352 if (OKVerb.Visible && OKVerb.Enabled && WebPartToEdit != null) {
353 ApplyAndSyncChanges();
355 // Only close the EditorZone if there were no errors applying the EditorParts
361 base.RaisePostBackEvent(eventArgument);
365 protected internal override void Render(HtmlTextWriter writer) {
367 Page.VerifyRenderingInServerForm(this);
373 protected override void RenderBody(HtmlTextWriter writer) {
374 RenderBodyTableBeginTag(writer);
376 RenderDesignerRegionBeginTag(writer, Orientation.Vertical);
380 bool firstCell = true;
382 RenderInstructionText(writer, ref firstCell);
385 RenderErrorText(writer, ref firstCell);
388 EditorPartChrome chrome = EditorPartChrome;
389 foreach (EditorPart editorPart in EditorParts) {
390 if ((!editorPart.Display) || (!editorPart.Visible)) {
394 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
397 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingTop, "0");
402 writer.RenderBeginTag(HtmlTextWriterTag.Td);
404 chrome.RenderEditorPart(writer, editorPart);
406 writer.RenderEndTag(); // Td
407 writer.RenderEndTag(); // Tr
410 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
412 // Mozilla renders padding on an empty TD without this attribute
413 writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "0");
415 // Add an extra row with height of 100%, to Microsoft up any extra space
416 // if the height of the zone is larger than its contents
417 // Mac IE needs height=100% set on <td> instead of <tr>
418 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "100%");
420 writer.RenderBeginTag(HtmlTextWriterTag.Td);
421 writer.RenderEndTag(); // Td
422 writer.RenderEndTag(); // Tr
425 RenderEmptyZoneText(writer);
429 RenderDesignerRegionEndTag(writer);
431 RenderBodyTableEndTag(writer);
434 private void RenderEmptyZoneText(HtmlTextWriter writer) {
435 string emptyZoneText = EmptyZoneText;
436 if (!String.IsNullOrEmpty(emptyZoneText)) {
437 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
439 writer.AddAttribute(HtmlTextWriterAttribute.Valign, "top");
441 Style emptyZoneTextStyle = EmptyZoneTextStyle;
442 if (!emptyZoneTextStyle.IsEmpty) {
443 emptyZoneTextStyle.AddAttributesToRender(writer, this);
445 writer.RenderBeginTag(HtmlTextWriterTag.Td);
447 writer.Write(emptyZoneText);
449 writer.RenderEndTag(); // Td
450 writer.RenderEndTag(); // Tr
454 private void RenderErrorText(HtmlTextWriter writer, ref bool firstCell) {
455 string errorText = ErrorText;
456 if (!String.IsNullOrEmpty(errorText)) {
457 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
458 writer.RenderBeginTag(HtmlTextWriterTag.Td);
461 Label label = new Label();
462 label.Text = errorText;
464 label.ApplyStyle(ErrorStyle);
465 label.RenderControl(writer);
467 writer.RenderEndTag(); // Td
468 writer.RenderEndTag(); // Tr
472 private void RenderInstructionText(HtmlTextWriter writer, ref bool firstCell) {
473 string instructionText = InstructionText;
474 if (!String.IsNullOrEmpty(instructionText)) {
475 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
476 writer.RenderBeginTag(HtmlTextWriterTag.Td);
479 Label label = new Label();
480 label.Text = instructionText;
482 label.ApplyStyle(InstructionTextStyle);
483 label.RenderControl(writer);
485 writer.RenderEndTag(); // Td
486 writer.RenderEndTag(); // Tr
490 protected override void RenderVerbs(HtmlTextWriter writer) {
491 RenderVerbsInternal(writer, new WebPartVerb[] {OKVerb, CancelVerb, ApplyVerb});
494 protected override object SaveViewState() {
495 object[] myState = new object[viewStateArrayLength];
497 myState[baseIndex] = base.SaveViewState();
498 myState[applyVerbIndex] = (_applyVerb != null) ? ((IStateManager)_applyVerb).SaveViewState() : null;
499 myState[cancelVerbIndex] = (_cancelVerb != null) ? ((IStateManager)_cancelVerb).SaveViewState() : null;
500 myState[okVerbIndex] = (_okVerb != null) ? ((IStateManager)_okVerb).SaveViewState() : null;
502 for (int i=0; i < viewStateArrayLength; i++) {
503 if (myState[i] != null) {
508 // More performant to return null than an array of null values
512 protected override void TrackViewState() {
513 base.TrackViewState();
515 if (_applyVerb != null) {
516 ((IStateManager) _applyVerb).TrackViewState();
518 if (_cancelVerb != null) {
519 ((IStateManager) _cancelVerb).TrackViewState();
521 if (_okVerb != null) {
522 ((IStateManager) _okVerb).TrackViewState();