|
//------------------------------------------------------------------------------
// <copyright file="MobileControl.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using System.IO;
using System.Web;
using System.Web.Mobile;
using System.Web.UI;
using System.Web.UI.Design.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.Util;
using System.Security.Permissions;
namespace System.Web.UI.MobileControls
{
/*
* Mobile control base class.
* All core controls and extension controls extend from this class.
*
* Copyright (c) 2000 Microsoft Corporation
*/
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl"]/*' />
[
ControlBuilderAttribute(typeof(MobileControlBuilder)),
Designer(typeof(System.Web.UI.Design.MobileControls.MobileControlDesigner)),
ParseChildren(false),
PersistChildren(false),
ToolboxItem(false),
ToolboxItemFilter("System.Web.UI"),
ToolboxItemFilter("System.Web.UI.MobileControls", ToolboxItemFilterType.Require),
]
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
[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.")]
public abstract class MobileControl : Control, IAttributeAccessor
{
private IControlAdapter _adapter;
private DeviceSpecific _deviceSpecific;
internal const String InnerTextViewStateKey = "_!InnerText";
private static String[] _ignoredCustomAttributes;
static MobileControl()
{
// Note: These should be in alphabetical order!
_ignoredCustomAttributes = new String[2];
_ignoredCustomAttributes[0] = "designtimedragdrop";
_ignoredCustomAttributes[1] = "name";
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.Adapter"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
public new IControlAdapter Adapter
{
get
{
if (_adapter == null && MobilePage != null)
{
_adapter = MobilePage.GetControlAdapter(this);
}
return _adapter;
}
}
[
DefaultValue(false)
]
public override sealed bool EnableTheming {
get {
return false;
}
set {
throw new NotSupportedException(SR.GetString(SR.Theme_Not_Supported_On_MobileControls));
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.MobilePage"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
public MobilePage MobilePage
{
get
{
Page page = Page;
if (page != null)
{
MobilePage mobilePage = page as MobilePage;
if (mobilePage == null)
{
if (Site == null || !Site.DesignMode)
{
throw new Exception(
SR.GetString(SR.MobileControl_MustBeInMobilePage,
Page));
}
}
return mobilePage;
}
else
{
return null;
}
}
}
private Form _form = null;
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.Form"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
public Form Form
{
get
{
if (_form == null)
{
for (Control control = this; control != null; control = control.Parent)
{
Form form = control as Form;
if (form != null)
{
_form = form;
return _form;
}
}
if (_form == null && RequiresForm)
{
throw new Exception(SR.GetString(SR.MobileControl_MustBeInForm,
UniqueID,
GetType().Name));
}
}
return _form;
}
}
[
Browsable(false)
]
public override sealed string SkinID {
get {
return String.Empty;
}
set {
throw new NotSupportedException(SR.GetString(SR.Theme_Not_Supported_On_MobileControls));
}
}
[
EditorBrowsable(EditorBrowsableState.Never),
]
public override sealed void ApplyStyleSheetSkin(Page page) {
throw new NotSupportedException(SR.GetString(SR.Theme_Not_Supported_On_MobileControls));
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.ResolveFormReference"]/*' />
public Form ResolveFormReference(String formID)
{
Form form = ResolveFormReferenceNoThrow(formID);
if (form == null)
{
throw new ArgumentException(
SR.GetString(SR.MobilePage_FormNotFound, formID));
}
return form;
}
internal Form ResolveFormReferenceNoThrow(String formID)
{
for (Control ctl = this; ctl != null; ctl = ctl.Parent)
{
if (ctl is TemplateControl)
{
Form childForm = ctl.FindControl(formID) as Form;
if (childForm != null)
{
return childForm;
}
}
}
return null;
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.AddedControl"]/*' />
protected override void AddedControl(Control control, int index)
{
_cachedInnerText = null;
base.AddedControl(control, index);
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.RemovedControl"]/*' />
protected override void RemovedControl(Control control) {
MobileControl ctl = control as MobileControl;
if (ctl != null) {
ctl.InvalidateParentStyles();
}
// Remove the cached _deviceSpecific.
DeviceSpecific deviceSpecific = control as DeviceSpecific;
if (deviceSpecific != null) {
_deviceSpecific.SetOwner(null);
_deviceSpecific = null;
}
_cachedInnerText = null;
base.RemovedControl(control);
}
internal virtual void InvalidateParentStyles()
{
Style.InvalidateParentStyle();
}
/////////////////////////////////////////////////////////////////////////
// TEMPLATES SUPPORT
/////////////////////////////////////////////////////////////////////////
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.IsTemplated"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
public virtual bool IsTemplated
{
get
{
if (_deviceSpecific != null && _deviceSpecific.HasTemplates)
{
return true;
}
else
{
Style referredStyle = Style.ReferredStyle;
return referredStyle != null && referredStyle.IsTemplated;
}
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.GetTemplate"]/*' />
public virtual ITemplate GetTemplate(String templateName)
{
Debug.Assert(this is ITemplateable);
ITemplate t = null;
if (_deviceSpecific != null)
{
t = _deviceSpecific.GetTemplate(templateName);
}
if (t == null)
{
Style referredStyle = Style.ReferredStyle;
if (referredStyle != null)
{
t = referredStyle.GetTemplate(templateName);
}
}
return t;
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.EnsureTemplatedUI"]/*' />
public virtual void EnsureTemplatedUI()
{
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.CreateTemplatedUI"]/*' />
protected virtual void CreateTemplatedUI(bool doDataBind)
{
// It is possible for a rogue control to call this even though
// the control is not templated. Catch and throw an exception for
// this case.
if (!IsTemplated)
{
throw new Exception(
SR.GetString(SR.MobileControl_NoTemplatesDefined));
}
Adapter.CreateTemplatedUI(doDataBind);
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.CreateDefaultTemplatedUI"]/*' />
public virtual void CreateDefaultTemplatedUI(bool doDataBind)
{
// Create nothing by default.
}
// Return the nearest containing TemplateControl (UserControl or Page),
// or null if none.
internal TemplateControl FindContainingTemplateControl()
{
Control control = this;
while (!(control is TemplateControl) &&
control != null)
{
control = control.Parent;
}
// We assume that the only template controls are Page and
// UserControl.
Debug.Assert(control == null ||
control is Page ||
control is UserControl);
return (TemplateControl)control;
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.ResolveUrl"]/*' />
public new String ResolveUrl(String relativeUrl)
{
int length;
if (relativeUrl == null ||
(length = relativeUrl.Length) == 0 ||
!UrlPath.IsRelativeUrl(relativeUrl))
{
return relativeUrl;
}
// VSWhidbey 450801. Make the relativeUrl app-absolute first.
relativeUrl = UrlPath.MakeVirtualPathAppAbsolute(relativeUrl);
// Deal with app relative syntax (e.g. ~/foo)
String baseUrl = UrlPath.MakeVirtualPathAppAbsolute(TemplateSourceDirectory);
// Determine if there are any . or .. sequences.
bool containsDots = false;
for (int examine = 0; examine < length; examine++)
{
examine = relativeUrl.IndexOf('.', examine);
if (examine < 0)
{
break;
}
// Expression borrowed from UrlPath.cs
if ((examine == 0 || relativeUrl[examine - 1] == '/')
&& (examine + 1 == length || relativeUrl[examine + 1] == '/' ||
(relativeUrl[examine + 1] == '.' &&
(examine + 2 == length || relativeUrl[examine + 2] == '/'))))
{
containsDots = true;
break;
}
}
if (!containsDots)
{
if (baseUrl.Length == 0)
{
return relativeUrl;
}
TemplateControl parentTemplateControl = FindContainingTemplateControl();
if (parentTemplateControl == null || parentTemplateControl is MobilePage)
{
return relativeUrl;
}
}
if (baseUrl.IndexOf(' ') != -1)
{
baseUrl = baseUrl.Replace(" ", "%20");
}
String url = UrlPath.Combine(baseUrl, relativeUrl);
return Context.Response.ApplyAppPathModifier(url);
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.OnDataBinding"]/*' />
protected override void OnDataBinding(EventArgs e)
{
if (_containsDataboundLiteral)
{
_cachedInnerText = null;
}
base.OnDataBinding(e);
}
/////////////////////////////////////////////////////////////////////////
// BEGIN DESIGN TIME TEMPLATES SUPPORT
/////////////////////////////////////////////////////////////////////////
// We need to expose the DeviceSpecific in runtime code for two purposes. A. We need to
// access all components inside DeviceSpecific. B. We have to persist the modified HTML.
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.DeviceSpecific"]/*' />
[
Browsable(false),
Bindable(false),
//PersistenceMode(PersistenceMode.InnerDefaultProperty)
PersistenceMode(PersistenceMode.InnerProperty)
]
public DeviceSpecific DeviceSpecific
{
get
{
return _deviceSpecific;
}
set
{
_deviceSpecific = value;
if (value != null)
{
value.SetOwner(this);
}
}
}
/////////////////////////////////////////////////////////////////////////
// CONTROL OVERRIDES
/////////////////////////////////////////////////////////////////////////
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.AddParsedSubObject"]/*' />
protected override void AddParsedSubObject(Object obj)
{
if (obj is DeviceSpecific)
{
if (DeviceSpecific == null)
{
DeviceSpecific = (DeviceSpecific)obj;
}
else
{
throw new Exception(
SR.GetString(SR.MobileControl_NoMultipleDeviceSpecifics));
}
}
else
{
base.AddParsedSubObject(obj);
}
}
internal virtual void ApplyDeviceSpecifics()
{
if (_deviceSpecific != null)
{
_deviceSpecific.ApplyProperties();
}
}
/////////////////////////////////////////////////////////////////////////
// BEGIN ADAPTER PLUMBING
/////////////////////////////////////////////////////////////////////////
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.OnInit"]/*' />
protected override void OnInit(EventArgs e)
{
MobilePage page = MobilePage;
bool isRuntime = page != null && !page.DesignMode;
// We don't want to override the properties at design time.
if (isRuntime)
{
ApplyDeviceSpecifics();
}
if (Adapter != null)
{
Adapter.OnInit(e);
}
base.OnInit(e);
// If we are being created after the first pass
// then
if (isRuntime && page.PrivateViewStateLoaded)
{
Object privateViewState = ((MobilePage)Page).GetPrivateViewState(this);
if(privateViewState != null)
{
LoadPrivateViewStateInternal(privateViewState);
}
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.IsFormSubmitControl"]/*' />
protected virtual bool IsFormSubmitControl()
{
return false;
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.OnLoad"]/*' />
protected override void OnLoad(EventArgs e)
{
IPostBackEventHandler eventHandler = this as IPostBackEventHandler;
if (Form != null && eventHandler != null && IsFormSubmitControl())
{
Form.RegisterEventHandler(eventHandler);
}
// Handle custom attributes.
if (_customAttributes != null && !MobilePage.AllowCustomAttributes)
{
// AUI 2346
ICollection keys = CustomAttributes.Keys;
String illegalCustomAttributes = null;
if (keys != null)
{
foreach (String key in keys)
{
String keyLower = key.ToLower(CultureInfo.InvariantCulture);
if (Array.BinarySearch(_ignoredCustomAttributes, keyLower) < 0)
{
if (illegalCustomAttributes != null)
{
illegalCustomAttributes += "; ";
}
illegalCustomAttributes += key + "=" + CustomAttributes[key];
}
}
}
if (illegalCustomAttributes != null)
{
throw new Exception(
SR.GetString(SR.MobileControl_NoCustomAttributes,
illegalCustomAttributes));
}
}
Adapter.OnLoad(e);
base.OnLoad(e);
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.OnPreRender"]/*' />
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Adapter.OnPreRender(e);
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.Render"]/*' />
protected override void Render(HtmlTextWriter writer)
{
if (RequiresForm && Page != null)
{
Page.VerifyRenderingInServerForm(this);
}
if (IsVisibleOnPage(Form.CurrentPage))
{
OnRender(writer);
}
}
internal virtual bool RequiresForm
{
get
{
return true;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.OnRender"]/*' />
protected virtual void OnRender(HtmlTextWriter writer)
{
Adapter.Render(writer);
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.OnUnload"]/*' />
protected override void OnUnload(EventArgs e)
{
base.OnUnload(e);
if (Adapter != null) {
Adapter.OnUnload(e);
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.RenderChildren"]/*' />
public new void RenderChildren(HtmlTextWriter writer)
{
base.RenderChildren(writer);
}
/////////////////////////////////////////////////////////////////////////
// VIEW STATE SUPPORT
/////////////////////////////////////////////////////////////////////////
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.TrackViewState"]/*' />
protected override void TrackViewState()
{
base.TrackViewState();
((IStateManager)Style).TrackViewState();
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.LoadViewState"]/*' />
protected override void LoadViewState(Object savedState)
{
if (savedState != null)
{
Object[] state = (Object[])savedState;
if (state[0] != null)
{
base.LoadViewState(state[0]);
}
if (state[1] != null)
{
((IStateManager)Style).LoadViewState(state[1]);
}
// Reset the property if persisted before, done similarly in
// ASP.NET
String s = (String)ViewState[InnerTextViewStateKey];
if (s != null)
{
InnerText = s;
}
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.SaveViewState"]/*' />
protected override Object SaveViewState()
{
Object baseState = base.SaveViewState();
Object styleState = ((IStateManager)Style).SaveViewState();
if (baseState == null && styleState == null)
{
return null;
}
return new Object[2] { baseState, styleState };
}
internal void SavePrivateViewStateInternal()
{
Object privateState = SavePrivateViewState();
Object adapterState = Adapter.SaveAdapterState();
if (privateState != null || adapterState != null)
{
privateState = new Object[] { privateState, adapterState };
MobilePage.AddClientViewState(this, privateState);
}
}
internal void LoadPrivateViewStateInternal(Object state)
{
Debug.Assert(state != null);
Object[] privateState = (Object[])state;
if (privateState[0] != null)
{
LoadPrivateViewState(privateState[0]);
}
if (privateState[1] != null)
{
Adapter.LoadAdapterState(privateState[1]);
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.LoadPrivateViewState"]/*' />
protected virtual void LoadPrivateViewState(Object state)
{
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.SavePrivateViewState"]/*' />
protected virtual Object SavePrivateViewState()
{
return null;
}
/////////////////////////////////////////////////////////////////////////
// CUSTOM PROPERTIES
/////////////////////////////////////////////////////////////////////////
private StateBag _customAttributes;
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.CustomAttributes"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
public StateBag CustomAttributes
{
get
{
if (_customAttributes == null)
{
_customAttributes = new StateBag(true); // Ignore case
if (IsTrackingViewState)
{
((IStateManager)_customAttributes).TrackViewState();
}
}
return _customAttributes;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.IAttributeAccessor.GetAttribute"]/*' />
/// <internalonly/>
protected String GetAttribute(String name)
{
return (_customAttributes != null) ? (String)_customAttributes[name] : null;
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.IAttributeAccessor.SetAttribute"]/*' />
/// <internalonly/>
protected void SetAttribute(String name, String value)
{
CustomAttributes[name] = value;
}
/////////////////////////////////////////////////////////////////////////
// BEGIN STYLE PROPERTIES
/////////////////////////////////////////////////////////////////////////
Style _style;
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.Style"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
internal protected virtual Style Style
{
get
{
if (_style == null)
{
_style = CreateStyle();
_style.SetControl(this);
}
return _style;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.CreateStyle"]/*' />
protected virtual Style CreateStyle()
{
return new Style();
}
internal void RefreshStyle()
{
this.Style.Refresh();
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.StyleReference"]/*' />
[
Bindable(false),
DefaultValue(null),
MobileCategory(SR.Category_Appearance),
MobileSysDescription(SR.MobileControl_StyleReference),
TypeConverter(typeof(System.Web.UI.Design.MobileControls.Converters.StyleReferenceConverter))
]
public virtual String StyleReference
{
get
{
return this.Style.StyleReference;
}
set
{
this.Style.StyleReference = value;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.Font"]/*' />
[
DefaultValue(null),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
MobileCategory(SR.Category_Appearance),
MobileSysDescription(SR.MobileControl_Font),
NotifyParentProperty(true)
]
public virtual FontInfo Font
{
get
{
return this.Style.Font;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.Alignment"]/*' />
[
Bindable(true),
DefaultValue(Alignment.NotSet),
MobileCategory(SR.Category_Appearance),
MobileSysDescription(SR.MobileControl_Alignment),
]
public virtual Alignment Alignment
{
get
{
return this.Style.Alignment;
}
set
{
this.Style.Alignment = value;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.Wrapping"]/*' />
[
Bindable(true),
DefaultValue(Wrapping.NotSet),
MobileCategory(SR.Category_Appearance),
MobileSysDescription(SR.MobileControl_Wrapping),
]
public virtual Wrapping Wrapping
{
get
{
return this.Style.Wrapping;
}
set
{
this.Style.Wrapping = value;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.ForeColor"]/*' />
[
Bindable(true),
DefaultValue(typeof(Color), ""),
MobileCategory(SR.Category_Appearance),
MobileSysDescription(SR.Style_ForeColor),
TypeConverterAttribute(typeof(WebColorConverter))
]
public virtual Color ForeColor
{
get
{
return this.Style.ForeColor;
}
set
{
this.Style.ForeColor = value;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.BackColor"]/*' />
[
Bindable(true),
DefaultValue(typeof(Color), ""),
MobileCategory(SR.Category_Appearance),
MobileSysDescription(SR.MobileControl_BackColor),
TypeConverterAttribute(typeof(WebColorConverter))
]
public virtual Color BackColor
{
get
{
return this.Style.BackColor;
}
set
{
this.Style.BackColor = value;
}
}
/////////////////////////////////////////////////////////////////////////
// END STYLE PROPERTIES
/////////////////////////////////////////////////////////////////////////
private String _cachedInnerText = null;
private bool _containsDataboundLiteral = false;
private static char[] _newlineChars = { '\r', '\n' };
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.InnerText"]/*' />
[
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Never),
]
protected String InnerText
{
get
{
String text = null;
String innerTextAttribute = (String)ViewState[InnerTextViewStateKey];
if (_cachedInnerText != null)
{
text = _cachedInnerText;
}
else if (HasControls())
{
_containsDataboundLiteral = false;
bool containTag;
bool trimInnerText = TrimInnerText;
bool trimNewlines = TrimNewlines;
text = GetControlText(out containTag, out _containsDataboundLiteral, trimInnerText);
// Cannot throw exceptions from properties at designtime,
// this will break property browser.
if (containTag &&
!AllowInnerMarkup &&
(MobilePage == null || !MobilePage.DesignMode))
{
throw new Exception(
SR.GetString(SR.MobileControl_InnerTextCannotContainTags,
GetType().ToString(),
UniqueID));
}
// Reset text to empty string at design time if the control
// contains DataBoundLiteral child control.
if (MobilePage != null &&
MobilePage.DesignMode &&
_containsDataboundLiteral)
{
text = String.Empty;
}
if (trimNewlines)
{
// Need to trim leading and trailing whitespace, but only up to last newline.
int start = 0;
int finish = text.Length;
int length = text.Length;
int i;
for (i = 0; i < length; i++)
{
char c = text[i];
if (c == '\n')
{
start = i + 1;
}
else if (!Char.IsWhiteSpace(c))
{
break;
}
}
for (int i2 = length - 1; i2 > i; i2--)
{
char c = text[i2];
if (c == '\r')
{
finish = i2;
}
else if (!Char.IsWhiteSpace(c))
{
break;
}
}
text = text.Substring(start, finish - start);
}
if ((trimInnerText || trimNewlines) && text.IndexOf('\r') != -1)
{
// Replace newlines with spaces.
text = text.Replace("\r\n", " ");
}
if (trimNewlines && text.Trim().Length == 0)
{
text = String.Empty;
}
_cachedInnerText = text;
}
if (text == null || text.Length == 0)
{
text = innerTextAttribute;
if (text == null)
{
text = String.Empty;
}
}
return text;
}
set
{
if (!AllowMultiLines && value != null && value.IndexOf('\r') >= 0)
{
throw new ArgumentException(
SR.GetString(SR.MobileControl_TextCannotContainNewlines,
GetType().ToString(),
UniqueID));
}
ViewState[InnerTextViewStateKey] = value;
// There may be other types of child controls and they should
// be preserved. Removing the specific controls in backward
// direction so they can be removed properly.
for (int i = Controls.Count - 1; i >= 0; i--)
{
Control child = Controls[i];
if (child is LiteralControl ||
child is DataBoundLiteralControl ||
child is DesignerDataBoundLiteralControl)
{
Controls.RemoveAt(i);
}
}
_cachedInnerText = null;
}
}
// make this an internal method so designer could reuse the same logic.
internal String GetControlText(out bool containTag, out bool containDataboundLiteral)
{
return GetControlText(out containTag, out containDataboundLiteral, false);
}
private String GetControlText(out bool containTag, out bool containDataboundLiteral, bool trim)
{
containTag = false;
containDataboundLiteral = false;
bool allowInnerMarkup = AllowInnerMarkup;
String returnedText = null;
// PERF: Optimized to avoid constructing builder and writer, unless
// needed.
StringBuilder builder = null;
StringWriter writer = null;
foreach (Control child in Controls)
{
String text;
bool translate;
if (child is LiteralControl)
{
text = ((LiteralControl)child).Text;
containTag = containTag || text.IndexOf('<') != -1;
if (allowInnerMarkup)
{
translate = false;
}
else
{
translate = text.IndexOf('&') != -1;
}
}
else if (child is DataBoundLiteralControl)
{
text = ((DataBoundLiteralControl)child).Text;
containDataboundLiteral = true;
// Databound text is not in the persistence format, and thus should not
// be translated.
translate = false;
}
else if (child is DesignerDataBoundLiteralControl)
{
text = ((DesignerDataBoundLiteralControl)child).Text;
// If the DesignerDataBoundLiteralControl is not databound, we simply
// return empty string for the Text property.
if (text == null || text.Length == 0)
{
containDataboundLiteral = true;
}
// Databound text is not in the persistence format, and thus should not
// be translated.
translate = false;
}
else if (child is HtmlContainerControl)
{
containTag = true;
break;
}
else
{
continue;
}
if (trim)
{
text = text.Trim ();
}
if (translate || returnedText != null)
{
builder = new StringBuilder();
writer = new StringWriter(builder, CultureInfo.InvariantCulture);
if (returnedText != null)
{
writer.Write(returnedText);
returnedText = null;
}
}
if (writer != null)
{
if (translate)
{
TranslateAndAppendText(text, writer);
}
else
{
writer.Write(text);
}
}
else
{
returnedText = text;
}
}
if (returnedText != null)
{
return returnedText;
}
else if (builder == null)
{
return String.Empty;
}
else
{
return builder.ToString();
}
}
static internal void TranslateAndAppendText(String text, StringWriter writer)
{
// Can't quite use HtmlDecode, because HtmlDecode doesn't
// parse the way we'd like it to.
if (text.IndexOf('&') != -1)
{
if (text.IndexOf(" ", StringComparison.Ordinal) != -1)
{
text = text.Replace(" ", "\u00A0");
}
HttpUtility.HtmlDecode(text, writer);
}
else
{
writer.Write(text);
}
}
internal virtual bool AllowMultiLines
{
get
{
return false;
}
}
internal virtual bool AllowInnerMarkup
{
get
{
return false;
}
}
internal virtual bool TrimInnerText
{
get
{
return true;
}
}
internal virtual bool TrimNewlines
{
get
{
return false;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.AddLinkedForms"]/*' />
public virtual void AddLinkedForms(IList linkedForms)
{
}
// convenience method for returning a non-null string value
internal String ToString(Object o)
{
if (o == null)
return String.Empty;
if (o is String)
return (String)o;
return o.ToString();
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.IsVisibleOnPage"]/*' />
public bool IsVisibleOnPage(int pageNumber)
{
if (!EnablePagination)
{
return true;
}
if (FirstPage < 0 || LastPage < 0)
{
return true;
}
return pageNumber >= FirstPage && pageNumber <= LastPage;
}
private int _firstPage = -1;
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.FirstPage"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
public int FirstPage
{
get
{
return _firstPage;
}
set
{
_firstPage = value;
}
}
private int _lastPage = -1;
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.LastPage"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
public int LastPage
{
get
{
return _lastPage;
}
set
{
_lastPage = value;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.VisibleWeight"]/*' />
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
public virtual int VisibleWeight
{
get
{
int weight = 0;
if (HasControls())
{
foreach (Control child in Controls)
{
if (child is MobileControl && child.Visible)
{
MobileControl control = (MobileControl)child;
weight += control.GetVisibleWeight();
}
}
}
if (weight == 0)
{
weight = ControlPager.DefaultWeight;
}
return weight;
}
}
internal int GetVisibleWeight()
{
int weight = Adapter.VisibleWeight;
if (weight == ControlPager.UseDefaultWeight)
{
weight = VisibleWeight;
}
return weight;
}
private bool _enablePagination = true;
internal bool EnablePagination
{
get
{
return _enablePagination;
}
set
{
_enablePagination = value;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.PaginateChildren"]/*' />
protected virtual bool PaginateChildren
{
get
{
return true;
}
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.PaginateRecursive"]/*' />
public virtual void PaginateRecursive(ControlPager pager)
{
if (!EnablePagination)
{
return;
}
if (PaginateChildren || this.Form.ControlToPaginate == this)
{
int firstAssignedPage = -1;
DoPaginateChildren(pager, this, ref firstAssignedPage);
if (firstAssignedPage != -1)
{
this.FirstPage = firstAssignedPage;
}
else
{
this.FirstPage = pager.GetPage(GetVisibleWeight());
}
this.LastPage = pager.PageCount;
}
else
{
int pageNumber = pager.GetPage(GetVisibleWeight());
SetControlPageRecursive(this, pageNumber);
this.FirstPage = pageNumber;
this.LastPage = pageNumber;
}
}
internal static void DoPaginateChildren(ControlPager pager, Control ctl, ref int firstAssignedPage)
{
if (ctl.HasControls())
{
foreach (Control child in ctl.Controls)
{
if (child.Visible)
{
MobileControl mobileCtl = child as MobileControl;
if (mobileCtl != null)
{
mobileCtl.PaginateRecursive(pager);
if (firstAssignedPage == -1)
{
firstAssignedPage = mobileCtl.FirstPage;
}
}
else if (child is UserControl)
{
DoPaginateChildren(pager, child, ref firstAssignedPage);
}
}
}
}
}
internal static void SetControlPageRecursive(Control control, int page)
{
if (control.HasControls())
{
foreach (Control child in control.Controls)
{
MobileControl mobileChild = child as MobileControl;
if (mobileChild != null)
{
mobileChild.SetControlPage(page);
}
else
{
SetControlPageRecursive(child, page);
}
}
}
}
internal static void SetEnablePaginationRecursive(Control control, bool pagination)
{
if(control.HasControls()) {
foreach(Control child in control.Controls) {
SetEnablePaginationRecursive(child,pagination);
}
}
MobileControl mobileControl = control as MobileControl;
if(mobileControl != null) {
mobileControl.EnablePagination = pagination;
}
}
internal virtual void SetControlPage(int page)
{
FirstPage = page;
LastPage = page;
SetControlPageRecursive(this, page);
}
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.OnPageChange"]/*' />
protected virtual void OnPageChange(int oldPageIndex, int newPageIndex)
{
MobileControl.OnPageChangeRecursive(this, oldPageIndex, newPageIndex);
}
private static void OnPageChangeRecursive(Control ctl, int oldPageIndex, int newPageIndex)
{
if (ctl.HasControls())
{
foreach (Control child in ctl.Controls)
{
MobileControl mobileCtl = child as MobileControl;
if (mobileCtl != null)
{
mobileCtl.OnPageChange(oldPageIndex, newPageIndex);
}
else
{
OnPageChangeRecursive(child, oldPageIndex, newPageIndex);
}
}
}
}
internal bool _breakAfter = true;
/// <include file='doc\MobileControl.uex' path='docs/doc[@for="MobileControl.BreakAfter"]/*' />
[
Browsable(true),
Bindable(true),
DefaultValue(true),
MobileCategory(SR.Category_Behavior),
MobileSysDescription(SR.MobileControl_BreakAfter)
]
public virtual bool BreakAfter
{
get
{
return _breakAfter;
}
set
{
_breakAfter = value;
}
}
// BEGIN: logic to check for infinite cycles when control trees are instantiated
// through templates.
// InstantiatingTemplate refers to template that instantiated this control
// (or null if not instantiated by template).
private ITemplate _instantiatingTemplate = null;
private ITemplate InstantiatingTemplate
{
get
{
return _instantiatingTemplate;
}
}
// The prospective parent of this control is passed as a parameter. Typically this
// control has not been added to parent.Controls, so cannot use Parent property.
private void SetInstantiatingTemplateAndVerify (ITemplate instantiatingTemplate, MobileControl parent)
{
for (MobileControl c = parent; c != null; c = c.Parent as MobileControl)
{
if (c.InstantiatingTemplate == instantiatingTemplate)
{
throw new Exception (SR.GetString(SR.MobileControl_InfiniteTemplateRecursion));
}
}
_instantiatingTemplate = instantiatingTemplate;
}
// Typically target has not been added to targetParent.Controls collection yet.
internal void CheckedInstantiateTemplate(ITemplate template, MobileControl target, MobileControl targetParent)
{
template.InstantiateIn (target);
target.SetInstantiatingTemplateAndVerify (template, targetParent);
}
#region IAttributeAccessor implementation
String IAttributeAccessor.GetAttribute(String name) {
return GetAttribute(name);
}
void IAttributeAccessor.SetAttribute(String name, String value) {
SetAttribute(name, value);
}
#endregion
}
}
|