Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / DynamicData / DynamicData / FieldTemplateFactory.cs / 1305376 / FieldTemplateFactory.cs
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Globalization;
using System.Security.Permissions;
using System.Web.Compilation;
using System.Web.Hosting;
using System.Web.UI.WebControls;
namespace System.Web.DynamicData {
///
/// Default implementation of IFieldTemplateFactory. It uses user controls for the field templates.
///
public class FieldTemplateFactory : IFieldTemplateFactory {
private const string IntegerField = "Integer";
private const string ForeignKeyField = "ForeignKey";
private const string ChildrenField = "Children";
private const string ManyToManyField = "ManyToMany";
private const string EnumerationField = "Enumeration";
private const string EditModePathModifier = "_Edit";
private const string InsertModePathModifier = "_Insert";
private Dictionary _typesToTemplateNames;
private Dictionary _typesFallBacks;
private TemplateFactory _templateFactory;
///
///
public FieldTemplateFactory() {
InitTypesToTemplateNamesTable();
BuildTypeFallbackTable();
_templateFactory = new TemplateFactory("FieldTemplates");
}
// For unit test purpose
internal FieldTemplateFactory(VirtualPathProvider vpp)
: this() {
_templateFactory.VirtualPathProvider = vpp;
}
///
/// Sets the folder containing the user controls. By default, this is ~/DynamicData/FieldTemplates/
///
public string TemplateFolderVirtualPath {
get {
return _templateFactory.TemplateFolderVirtualPath;
}
set {
_templateFactory.TemplateFolderVirtualPath = value;
}
}
///
/// The MetaModel that the factory is associated with
///
public MetaModel Model {
get {
return _templateFactory.Model;
}
private set {
_templateFactory.Model = value;
}
}
private void InitTypesToTemplateNamesTable() {
_typesToTemplateNames = new Dictionary();
_typesToTemplateNames[typeof(int)] = FieldTemplateFactory.IntegerField;
_typesToTemplateNames[typeof(string)] = DataType.Text.ToString();
}
private void BuildTypeFallbackTable() {
_typesFallBacks = new Dictionary();
_typesFallBacks[typeof(float)] = typeof(decimal);
_typesFallBacks[typeof(double)] = typeof(decimal);
_typesFallBacks[typeof(Int16)] = typeof(int);
_typesFallBacks[typeof(byte)] = typeof(int);
_typesFallBacks[typeof(long)] = typeof(int);
// Fall back to strings for most types
_typesFallBacks[typeof(char)] = typeof(string);
_typesFallBacks[typeof(int)] = typeof(string);
_typesFallBacks[typeof(decimal)] = typeof(string);
_typesFallBacks[typeof(Guid)] = typeof(string);
_typesFallBacks[typeof(DateTime)] = typeof(string);
_typesFallBacks[typeof(DateTimeOffset)] = typeof(string);
_typesFallBacks[typeof(TimeSpan)] = typeof(string);
//
}
private Type GetFallBackType(Type t) {
// Check if there is a fallback type
Type fallbackType;
if (_typesFallBacks.TryGetValue(t, out fallbackType))
return fallbackType;
return null;
}
// Internal for unit test purpose
internal string GetFieldTemplateVirtualPathWithCaching(MetaColumn column, DataBoundControlMode mode, string uiHint) {
// Compute a cache key based on all the input paramaters
long cacheKey = Misc.CombineHashCodes(uiHint, column, mode);
Func templatePathFactoryFunction = () => GetFieldTemplateVirtualPath(column, mode, uiHint);
return _templateFactory.GetTemplatePath(cacheKey, templatePathFactoryFunction);
}
///
/// Returns the virtual path of the field template user control to be used, based on various pieces of data
///
/// The MetaColumn for which the field template is needed
/// The mode (Readonly, Edit, Insert) for which the field template is needed
/// The UIHint (if any) that should affect the field template lookup
///
public virtual string GetFieldTemplateVirtualPath(MetaColumn column, DataBoundControlMode mode, string uiHint) {
mode = PreprocessMode(column, mode);
bool hasDataTypeAttribute = column != null && column.DataTypeAttribute != null;
// Set the UIHint in some special cases, but don't do it if we already have one or
// if we have a DataTypeAttribute
if (String.IsNullOrEmpty(uiHint) && !hasDataTypeAttribute) {
// Check if it's an association
// Or if it is an enum
if (column is MetaForeignKeyColumn) {
uiHint = FieldTemplateFactory.ForeignKeyField;
} else if (column is MetaChildrenColumn) {
var childrenColumn = (MetaChildrenColumn)column;
if (childrenColumn.IsManyToMany) {
uiHint = FieldTemplateFactory.ManyToManyField;
}
else {
uiHint = FieldTemplateFactory.ChildrenField;
}
} else if (column.ColumnType.IsEnum) {
uiHint = FieldTemplateFactory.EnumerationField;
}
}
return GetVirtualPathWithModeFallback(uiHint, column, mode);
}
///
/// Gets a chance to change the mode. e.g. an Edit mode request can be turned into ReadOnly mode
/// if the column is a primary key
///
public virtual DataBoundControlMode PreprocessMode(MetaColumn column, DataBoundControlMode mode) {
if (column == null) {
throw new ArgumentNullException("column");
}
// Primary keys can't be edited, so put them in readonly mode. Note that this
// does not apply to Insert mode, which is fine
if (column.IsPrimaryKey && mode == DataBoundControlMode.Edit) {
mode = DataBoundControlMode.ReadOnly;
}
// Generated columns should never be editable/insertable
if (column.IsGenerated) {
mode = DataBoundControlMode.ReadOnly;
}
// ReadOnly columns cannot be edited nor inserted, and are always in Display mode
if (column.IsReadOnly) {
if (mode == DataBoundControlMode.Insert && column.AllowInitialValue) {
// but don't change the mode if we're in insert and an initial value is allowed
} else {
mode = DataBoundControlMode.ReadOnly;
}
}
// If initial value is not allowed set mode to ReadOnly
if (mode == DataBoundControlMode.Insert && !column.AllowInitialValue) {
mode = DataBoundControlMode.ReadOnly;
}
if (column is MetaForeignKeyColumn) {
// If the foreign key is part of the primary key (e.g. Order and Product in Order_Details table),
// change the mode to ReadOnly so that they can't be edited.
if (mode == DataBoundControlMode.Edit && ((MetaForeignKeyColumn)column).IsPrimaryKeyInThisTable) {
mode = DataBoundControlMode.ReadOnly;
}
}
return mode;
}
private string GetVirtualPathWithModeFallback(string templateName, MetaColumn column, DataBoundControlMode mode) {
// Try not only the requested mode, but others if needed. Basically:
// - an edit template can default to an item template
// - an insert template can default to an edit template, then to an item template
for (var currentMode = mode; currentMode >= 0; currentMode--) {
string virtualPath = GetVirtualPathForMode(templateName, column, currentMode);
if (virtualPath != null)
return virtualPath;
}
// We couldn't locate any field template at all, so give up
return null;
}
private string GetVirtualPathForMode(string templateName, MetaColumn column, DataBoundControlMode mode) {
// If we got a template name, try it
if (!String.IsNullOrEmpty(templateName)) {
string virtualPath = GetVirtualPathIfExists(templateName, column, mode);
if (virtualPath != null)
return virtualPath;
}
// Otherwise, use the column's type
return GetVirtualPathForTypeWithFallback(column.ColumnType, column, mode);
}
private string GetVirtualPathForTypeWithFallback(Type fieldType, MetaColumn column, DataBoundControlMode mode) {
string templateName;
string virtualPath;
// If we have a data type attribute
if (column.DataTypeAttribute != null) {
templateName = column.DataTypeAttribute.GetDataTypeName();
// Try to get the path from it
virtualPath = GetVirtualPathIfExists(templateName, column, mode);
if (virtualPath != null)
return virtualPath;
}
// Try the actual fully qualified type name (i.e. with the namespace)
virtualPath = GetVirtualPathIfExists(fieldType.FullName, column, mode);
if (virtualPath != null)
return virtualPath;
// Try the simple type name
virtualPath = GetVirtualPathIfExists(fieldType.Name, column, mode);
if (virtualPath != null)
return virtualPath;
// If our type name table has an entry for it, try it
if (_typesToTemplateNames.TryGetValue(fieldType, out templateName)) {
virtualPath = GetVirtualPathIfExists(templateName, column, mode);
if (virtualPath != null)
return virtualPath;
}
// Check if there is a fallback type
Type fallbackType = GetFallBackType(fieldType);
// If not, we've run out of options
if (fallbackType == null)
return null;
// If so, try it
return GetVirtualPathForTypeWithFallback(fallbackType, column, mode);
}
private string GetVirtualPathIfExists(string templateName, MetaColumn column, DataBoundControlMode mode) {
// Build the path
string virtualPath = BuildVirtualPath(templateName, column, mode);
// Check if it exists
if (_templateFactory.FileExists(virtualPath))
return virtualPath;
// If not, return null
return null;
}
///
/// Build the virtual path to the field template user control based on the template name and mode.
/// By default, it returns names that look like TemplateName_ModeName.ascx, in the folder specified
/// by TemplateFolderVirtualPath.
///
///
///
///
///
public virtual string BuildVirtualPath(string templateName, MetaColumn column, DataBoundControlMode mode) {
if (String.IsNullOrEmpty(templateName)) {
throw new ArgumentNullException("templateName");
}
string modePathModifier = null;
switch (mode) {
case DataBoundControlMode.ReadOnly:
modePathModifier = String.Empty;
break;
case DataBoundControlMode.Edit:
modePathModifier = FieldTemplateFactory.EditModePathModifier;
break;
case DataBoundControlMode.Insert:
modePathModifier = FieldTemplateFactory.InsertModePathModifier;
break;
default:
Debug.Assert(false);
break;
}
return String.Format(CultureInfo.InvariantCulture,
TemplateFolderVirtualPath + "{0}{1}.ascx", templateName, modePathModifier);
}
#region IFieldTemplateFactory Members
public virtual void Initialize(MetaModel model) {
Model = model;
}
///
/// See IFieldTemplateFactory for details.
///
///
public virtual IFieldTemplate CreateFieldTemplate(MetaColumn column, DataBoundControlMode mode, string uiHint) {
string fieldTemplatePath = GetFieldTemplateVirtualPathWithCaching(column, mode, uiHint);
if (fieldTemplatePath == null)
return null;
return (IFieldTemplate)BuildManager.CreateInstanceFromVirtualPath(
fieldTemplatePath, typeof(IFieldTemplate));
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Globalization;
using System.Security.Permissions;
using System.Web.Compilation;
using System.Web.Hosting;
using System.Web.UI.WebControls;
namespace System.Web.DynamicData {
///
/// Default implementation of IFieldTemplateFactory. It uses user controls for the field templates.
///
public class FieldTemplateFactory : IFieldTemplateFactory {
private const string IntegerField = "Integer";
private const string ForeignKeyField = "ForeignKey";
private const string ChildrenField = "Children";
private const string ManyToManyField = "ManyToMany";
private const string EnumerationField = "Enumeration";
private const string EditModePathModifier = "_Edit";
private const string InsertModePathModifier = "_Insert";
private Dictionary _typesToTemplateNames;
private Dictionary _typesFallBacks;
private TemplateFactory _templateFactory;
///
///
public FieldTemplateFactory() {
InitTypesToTemplateNamesTable();
BuildTypeFallbackTable();
_templateFactory = new TemplateFactory("FieldTemplates");
}
// For unit test purpose
internal FieldTemplateFactory(VirtualPathProvider vpp)
: this() {
_templateFactory.VirtualPathProvider = vpp;
}
///
/// Sets the folder containing the user controls. By default, this is ~/DynamicData/FieldTemplates/
///
public string TemplateFolderVirtualPath {
get {
return _templateFactory.TemplateFolderVirtualPath;
}
set {
_templateFactory.TemplateFolderVirtualPath = value;
}
}
///
/// The MetaModel that the factory is associated with
///
public MetaModel Model {
get {
return _templateFactory.Model;
}
private set {
_templateFactory.Model = value;
}
}
private void InitTypesToTemplateNamesTable() {
_typesToTemplateNames = new Dictionary();
_typesToTemplateNames[typeof(int)] = FieldTemplateFactory.IntegerField;
_typesToTemplateNames[typeof(string)] = DataType.Text.ToString();
}
private void BuildTypeFallbackTable() {
_typesFallBacks = new Dictionary();
_typesFallBacks[typeof(float)] = typeof(decimal);
_typesFallBacks[typeof(double)] = typeof(decimal);
_typesFallBacks[typeof(Int16)] = typeof(int);
_typesFallBacks[typeof(byte)] = typeof(int);
_typesFallBacks[typeof(long)] = typeof(int);
// Fall back to strings for most types
_typesFallBacks[typeof(char)] = typeof(string);
_typesFallBacks[typeof(int)] = typeof(string);
_typesFallBacks[typeof(decimal)] = typeof(string);
_typesFallBacks[typeof(Guid)] = typeof(string);
_typesFallBacks[typeof(DateTime)] = typeof(string);
_typesFallBacks[typeof(DateTimeOffset)] = typeof(string);
_typesFallBacks[typeof(TimeSpan)] = typeof(string);
//
}
private Type GetFallBackType(Type t) {
// Check if there is a fallback type
Type fallbackType;
if (_typesFallBacks.TryGetValue(t, out fallbackType))
return fallbackType;
return null;
}
// Internal for unit test purpose
internal string GetFieldTemplateVirtualPathWithCaching(MetaColumn column, DataBoundControlMode mode, string uiHint) {
// Compute a cache key based on all the input paramaters
long cacheKey = Misc.CombineHashCodes(uiHint, column, mode);
Func templatePathFactoryFunction = () => GetFieldTemplateVirtualPath(column, mode, uiHint);
return _templateFactory.GetTemplatePath(cacheKey, templatePathFactoryFunction);
}
///
/// Returns the virtual path of the field template user control to be used, based on various pieces of data
///
/// The MetaColumn for which the field template is needed
/// The mode (Readonly, Edit, Insert) for which the field template is needed
/// The UIHint (if any) that should affect the field template lookup
///
public virtual string GetFieldTemplateVirtualPath(MetaColumn column, DataBoundControlMode mode, string uiHint) {
mode = PreprocessMode(column, mode);
bool hasDataTypeAttribute = column != null && column.DataTypeAttribute != null;
// Set the UIHint in some special cases, but don't do it if we already have one or
// if we have a DataTypeAttribute
if (String.IsNullOrEmpty(uiHint) && !hasDataTypeAttribute) {
// Check if it's an association
// Or if it is an enum
if (column is MetaForeignKeyColumn) {
uiHint = FieldTemplateFactory.ForeignKeyField;
} else if (column is MetaChildrenColumn) {
var childrenColumn = (MetaChildrenColumn)column;
if (childrenColumn.IsManyToMany) {
uiHint = FieldTemplateFactory.ManyToManyField;
}
else {
uiHint = FieldTemplateFactory.ChildrenField;
}
} else if (column.ColumnType.IsEnum) {
uiHint = FieldTemplateFactory.EnumerationField;
}
}
return GetVirtualPathWithModeFallback(uiHint, column, mode);
}
///
/// Gets a chance to change the mode. e.g. an Edit mode request can be turned into ReadOnly mode
/// if the column is a primary key
///
public virtual DataBoundControlMode PreprocessMode(MetaColumn column, DataBoundControlMode mode) {
if (column == null) {
throw new ArgumentNullException("column");
}
// Primary keys can't be edited, so put them in readonly mode. Note that this
// does not apply to Insert mode, which is fine
if (column.IsPrimaryKey && mode == DataBoundControlMode.Edit) {
mode = DataBoundControlMode.ReadOnly;
}
// Generated columns should never be editable/insertable
if (column.IsGenerated) {
mode = DataBoundControlMode.ReadOnly;
}
// ReadOnly columns cannot be edited nor inserted, and are always in Display mode
if (column.IsReadOnly) {
if (mode == DataBoundControlMode.Insert && column.AllowInitialValue) {
// but don't change the mode if we're in insert and an initial value is allowed
} else {
mode = DataBoundControlMode.ReadOnly;
}
}
// If initial value is not allowed set mode to ReadOnly
if (mode == DataBoundControlMode.Insert && !column.AllowInitialValue) {
mode = DataBoundControlMode.ReadOnly;
}
if (column is MetaForeignKeyColumn) {
// If the foreign key is part of the primary key (e.g. Order and Product in Order_Details table),
// change the mode to ReadOnly so that they can't be edited.
if (mode == DataBoundControlMode.Edit && ((MetaForeignKeyColumn)column).IsPrimaryKeyInThisTable) {
mode = DataBoundControlMode.ReadOnly;
}
}
return mode;
}
private string GetVirtualPathWithModeFallback(string templateName, MetaColumn column, DataBoundControlMode mode) {
// Try not only the requested mode, but others if needed. Basically:
// - an edit template can default to an item template
// - an insert template can default to an edit template, then to an item template
for (var currentMode = mode; currentMode >= 0; currentMode--) {
string virtualPath = GetVirtualPathForMode(templateName, column, currentMode);
if (virtualPath != null)
return virtualPath;
}
// We couldn't locate any field template at all, so give up
return null;
}
private string GetVirtualPathForMode(string templateName, MetaColumn column, DataBoundControlMode mode) {
// If we got a template name, try it
if (!String.IsNullOrEmpty(templateName)) {
string virtualPath = GetVirtualPathIfExists(templateName, column, mode);
if (virtualPath != null)
return virtualPath;
}
// Otherwise, use the column's type
return GetVirtualPathForTypeWithFallback(column.ColumnType, column, mode);
}
private string GetVirtualPathForTypeWithFallback(Type fieldType, MetaColumn column, DataBoundControlMode mode) {
string templateName;
string virtualPath;
// If we have a data type attribute
if (column.DataTypeAttribute != null) {
templateName = column.DataTypeAttribute.GetDataTypeName();
// Try to get the path from it
virtualPath = GetVirtualPathIfExists(templateName, column, mode);
if (virtualPath != null)
return virtualPath;
}
// Try the actual fully qualified type name (i.e. with the namespace)
virtualPath = GetVirtualPathIfExists(fieldType.FullName, column, mode);
if (virtualPath != null)
return virtualPath;
// Try the simple type name
virtualPath = GetVirtualPathIfExists(fieldType.Name, column, mode);
if (virtualPath != null)
return virtualPath;
// If our type name table has an entry for it, try it
if (_typesToTemplateNames.TryGetValue(fieldType, out templateName)) {
virtualPath = GetVirtualPathIfExists(templateName, column, mode);
if (virtualPath != null)
return virtualPath;
}
// Check if there is a fallback type
Type fallbackType = GetFallBackType(fieldType);
// If not, we've run out of options
if (fallbackType == null)
return null;
// If so, try it
return GetVirtualPathForTypeWithFallback(fallbackType, column, mode);
}
private string GetVirtualPathIfExists(string templateName, MetaColumn column, DataBoundControlMode mode) {
// Build the path
string virtualPath = BuildVirtualPath(templateName, column, mode);
// Check if it exists
if (_templateFactory.FileExists(virtualPath))
return virtualPath;
// If not, return null
return null;
}
///
/// Build the virtual path to the field template user control based on the template name and mode.
/// By default, it returns names that look like TemplateName_ModeName.ascx, in the folder specified
/// by TemplateFolderVirtualPath.
///
///
///
///
///
public virtual string BuildVirtualPath(string templateName, MetaColumn column, DataBoundControlMode mode) {
if (String.IsNullOrEmpty(templateName)) {
throw new ArgumentNullException("templateName");
}
string modePathModifier = null;
switch (mode) {
case DataBoundControlMode.ReadOnly:
modePathModifier = String.Empty;
break;
case DataBoundControlMode.Edit:
modePathModifier = FieldTemplateFactory.EditModePathModifier;
break;
case DataBoundControlMode.Insert:
modePathModifier = FieldTemplateFactory.InsertModePathModifier;
break;
default:
Debug.Assert(false);
break;
}
return String.Format(CultureInfo.InvariantCulture,
TemplateFolderVirtualPath + "{0}{1}.ascx", templateName, modePathModifier);
}
#region IFieldTemplateFactory Members
public virtual void Initialize(MetaModel model) {
Model = model;
}
///
/// See IFieldTemplateFactory for details.
///
///
public virtual IFieldTemplate CreateFieldTemplate(MetaColumn column, DataBoundControlMode mode, string uiHint) {
string fieldTemplatePath = GetFieldTemplateVirtualPathWithCaching(column, mode, uiHint);
if (fieldTemplatePath == null)
return null;
return (IFieldTemplate)BuildManager.CreateInstanceFromVirtualPath(
fieldTemplatePath, typeof(IFieldTemplate));
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TextureBrush.cs
- ItemDragEvent.cs
- NullableConverter.cs
- LayoutManager.cs
- CalendarAutoFormat.cs
- SiteMapSection.cs
- XmlSchemaImport.cs
- SiteMapProvider.cs
- CompilerError.cs
- ScaleTransform3D.cs
- HiddenFieldPageStatePersister.cs
- ValidateNames.cs
- DateTimeSerializationSection.cs
- StatusBarItemAutomationPeer.cs
- ToolboxBitmapAttribute.cs
- SolidColorBrush.cs
- PeerContact.cs
- XPathCompileException.cs
- ProvidersHelper.cs
- DataGridViewLayoutData.cs
- PointUtil.cs
- UnsafePeerToPeerMethods.cs
- PropertyIdentifier.cs
- PolyBezierSegment.cs
- PenCursorManager.cs
- IssuanceLicense.cs
- TemplateParser.cs
- Parser.cs
- Command.cs
- CompilationUnit.cs
- FixedSOMGroup.cs
- SymbolEqualComparer.cs
- PathGeometry.cs
- __TransparentProxy.cs
- HttpRequestTraceRecord.cs
- CharAnimationUsingKeyFrames.cs
- PartialTrustVisibleAssembliesSection.cs
- XmlResolver.cs
- ObjectDataProvider.cs
- CodeDirectoryCompiler.cs
- ProcessHostMapPath.cs
- GlobalizationSection.cs
- FormClosingEvent.cs
- DriveNotFoundException.cs
- SmtpClient.cs
- SystemWebSectionGroup.cs
- CompilerScopeManager.cs
- XmlReaderSettings.cs
- unitconverter.cs
- PropertyEmitter.cs
- FixedSOMLineRanges.cs
- COM2IDispatchConverter.cs
- CodeSnippetExpression.cs
- SctClaimSerializer.cs
- SmtpClient.cs
- ObjectQueryState.cs
- Set.cs
- HostedHttpRequestAsyncResult.cs
- ProcessModelSection.cs
- CodeAttributeArgumentCollection.cs
- FormViewPagerRow.cs
- TextStore.cs
- CommandBinding.cs
- EncodingDataItem.cs
- ToolStripSeparatorRenderEventArgs.cs
- Internal.cs
- UserValidatedEventArgs.cs
- Literal.cs
- AppDomainGrammarProxy.cs
- SchemaHelper.cs
- GreaterThan.cs
- CommonGetThemePartSize.cs
- RemotingAttributes.cs
- EncryptedPackageFilter.cs
- ScriptMethodAttribute.cs
- TypedReference.cs
- TypeConverterHelper.cs
- Timeline.cs
- ConnectorRouter.cs
- ResolvedKeyFrameEntry.cs
- ProtocolsConfiguration.cs
- ECDsaCng.cs
- FixedTextPointer.cs
- TraceInternal.cs
- Message.cs
- UnicodeEncoding.cs
- HtmlToClrEventProxy.cs
- HostingEnvironment.cs
- XmlChildEnumerator.cs
- PropertyItem.cs
- RelationshipEndCollection.cs
- MimeTypeAttribute.cs
- RadioButtonList.cs
- ActiveDesignSurfaceEvent.cs
- Overlapped.cs
- ParameterCollection.cs
- SQLBinaryStorage.cs
- DocumentGrid.cs
- MulticastDelegate.cs
- ByteKeyFrameCollection.cs