|
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<AutoGeneratedField> 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<AutoGeneratedField> generatedFields = new List<AutoGeneratedField>();
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);
}
}
}
}
|