public override List <AutoGeneratedField> CreateAutoGeneratedFields(object dataObject, Control control) { if (!(control is GridView)) { throw new ArgumentException(SR.GetString(SR.InvalidDefaultAutoFieldGenerator, GetType().FullName, typeof(GridView).FullName)); } Debug.Assert(dataObject == null || dataObject is PagedDataSource); PagedDataSource dataSource = dataObject as PagedDataSource; GridView gridView = control as GridView; if (dataSource == 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; // try ITypedList first // A PagedDataSource implements this, but returns null, if the underlying data source // does not implement it. propDescs = ((ITypedList)dataSource).GetItemProperties(new PropertyDescriptor[0]); if (propDescs == null) { Type sampleItemType = null; object sampleItem = null; IEnumerable realDataSource = dataSource.DataSource; Debug.Assert(realDataSource != null, "Must have a real data source when calling CreateAutoGeneratedColumns"); Type dataSourceType = realDataSource.GetType(); // try for a typed Row property, which should be present on strongly typed collections PropertyInfo itemProp = dataSourceType.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, null, new Type[] { typeof(int) }, null); if (itemProp != null) { sampleItemType = itemProp.PropertyType; } if ((sampleItemType == null) || (sampleItemType == typeof(object))) { // last resort... try to get ahold of the first item by beginning the // enumeration IEnumerator e = dataSource.GetEnumerator(); if (e.MoveNext()) { sampleItem = e.Current; } else { // we don't want to throw an exception if we're bound to an IEnumerable // data source with no records... we'll simply bail and not show any data throwException = false; } if (sampleItem != null) { sampleItemType = sampleItem.GetType(); } // We must store the enumerator regardless of whether we got back an item from it // because we cannot start the enumeration again, in the case of a DataReader. // Code in CreateChildControls must deal appropriately for the case where // there is a stored enumerator, but a null object as the first item. gridView.StoreEnumerator(e, sampleItem); } if ((sampleItem != null) && (sampleItem is ICustomTypeDescriptor)) { // Get the custom properties of the object propDescs = TypeDescriptor.GetProperties(sampleItem); } else if (sampleItemType != 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(sampleItemType, gridView)) { AutoGeneratedFieldProperties fieldProps = new AutoGeneratedFieldProperties(); ((IStateManager)fieldProps).TrackViewState(); fieldProps.Type = sampleItemType; fieldProps.Name = "Item"; fieldProps.DataField = AutoGeneratedField.ThisExpression; AutoGeneratedField field = CreateAutoGeneratedFieldFromFieldProperties(fieldProps); if (field != null) { generatedFields.Add(field); AutoGeneratedFieldProperties.Add(fieldProps); } } else { // complex type... we get its properties propDescs = TypeDescriptor.GetProperties(sampleItemType); } } } else { if (propDescs.Count == 0) { // we don't want to throw an exception if we're bound to an ITypedList // data source with no records... we'll simply bail and not show any data throwException = false; } } if ((propDescs != null) && (propDescs.Count != 0)) { string[] dataKeyNames = gridView.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, gridView)) { 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.GridView_NoAutoGenFields, gridView.ID)); } return(generatedFields); }