using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Web.Util; namespace System.Web.UI.WebControls { public class DetailsViewRowsGenerator : AutoFieldsGenerator { public override List CreateAutoGeneratedFields(object dataItem, Control control) { if (!(control is DetailsView)) { throw new ArgumentException(SR.GetString(SR.InvalidDefaultAutoFieldGenerator, GetType().FullName, typeof(DetailsView).FullName)); } DetailsView detailsView = control as DetailsView; if (dataItem == null) { // note that we're not throwing an exception in this case, and the calling // code should be able to handle a null arraylist being returned return null; } List generatedFields = new List(); PropertyDescriptorCollection propDescs = null; bool throwException = true; Type dataItemType = null; //The base class ensures that the AutoGeneratedFieldProperties collection is reset before this method is called. //However we are doing this again in here because we have another caller DetailsView.CreateAutoGeneratedRows which is //not being used anywhere today but kept for backward compatibility. if (AutoGeneratedFieldProperties.Count > 0) { AutoGeneratedFieldProperties.Clear(); } if (dataItem != null) dataItemType = dataItem.GetType(); if ((dataItem != null) && (dataItem is ICustomTypeDescriptor)) { // Get the custom properties of the object propDescs = TypeDescriptor.GetProperties(dataItem); } else if (dataItemType != null) { // directly bindable types: strings, ints etc. get treated specially, since we // don't care about their properties, but rather we care about them directly if (ShouldGenerateField(dataItemType, detailsView)) { AutoGeneratedFieldProperties fieldProps = new AutoGeneratedFieldProperties(); ((IStateManager)fieldProps).TrackViewState(); fieldProps.Name = "Item"; fieldProps.DataField = AutoGeneratedField.ThisExpression; fieldProps.Type = dataItemType; AutoGeneratedField field = CreateAutoGeneratedFieldFromFieldProperties(fieldProps); if (field != null) { generatedFields.Add(field); AutoGeneratedFieldProperties.Add(fieldProps); } } else { // complex type... we get its properties propDescs = TypeDescriptor.GetProperties(dataItemType); } } if ((propDescs != null) && (propDescs.Count != 0)) { string[] dataKeyNames = detailsView.DataKeyNames; int keyNamesLength = dataKeyNames.Length; string[] dataKeyNamesCaseInsensitive = new string[keyNamesLength]; for (int i = 0; i < keyNamesLength; i++) { dataKeyNamesCaseInsensitive[i] = dataKeyNames[i].ToLowerInvariant(); } foreach (PropertyDescriptor pd in propDescs) { Type propertyType = pd.PropertyType; if (ShouldGenerateField(propertyType, detailsView)) { string name = pd.Name; bool isKey = ((IList)dataKeyNamesCaseInsensitive).Contains(name.ToLowerInvariant()); AutoGeneratedFieldProperties fieldProps = new AutoGeneratedFieldProperties(); ((IStateManager)fieldProps).TrackViewState(); fieldProps.Name = name; fieldProps.IsReadOnly = isKey; fieldProps.Type = propertyType; fieldProps.DataField = name; AutoGeneratedField field = CreateAutoGeneratedFieldFromFieldProperties(fieldProps); if (field != null) { generatedFields.Add(field); AutoGeneratedFieldProperties.Add(fieldProps); } } } } if ((generatedFields.Count == 0) && throwException) { // this handles the case where we got back something that either had no // properties, or all properties were not bindable. throw new InvalidOperationException(SR.GetString(SR.DetailsView_NoAutoGenFields, detailsView.ID)); } return generatedFields; } private bool ShouldGenerateField(Type propertyType, DetailsView detailsView) { if (detailsView.RenderingCompatibility < VersionUtil.Framework45 && AutoGenerateEnumFields == null) { //This is for backward compatibility. Before 4.5, auto generating fields used to call into this method //and if someone has overriden this method to force generation of columns, the scenario should still //work. return detailsView.IsBindableType(propertyType); } else { //If AutoGenerateEnumFileds is null here, the rendering compatibility must be 4.5 return DataBoundControlHelper.IsBindableType(propertyType, enableEnums: AutoGenerateEnumFields ?? true); } } } }