private void Rebuild() { RowsProportions.Clear(); Widgets.Clear(); _records.Clear(); if (_object == null) { return; } var properties = from p in _object.GetType().GetProperties() select p; var records = new List <Record>(); foreach (var property in properties) { if (property.GetGetMethod() == null || !property.GetGetMethod().IsPublic || property.GetGetMethod().IsStatic) { continue; } var hasSetter = property.GetSetMethod() != null && property.GetSetMethod().IsPublic; var browsableAttr = property.FindAttribute <BrowsableAttribute>(); if (browsableAttr != null && !browsableAttr.Browsable) { continue; } var hiddenAttr = property.FindAttribute <HiddenInEditorAttribute>(); if (hiddenAttr != null) { continue; } var readOnlyAttr = property.FindAttribute <ReadOnlyAttribute>(); if (readOnlyAttr != null && readOnlyAttr.IsReadOnly) { hasSetter = false; } var record = new PropertyRecord(property) { HasSetter = hasSetter }; var selectionAttr = property.FindAttribute <SelectionAttribute>(); if (selectionAttr != null) { record.ItemsProvider = (IItemsProvider)Activator.CreateInstance(selectionAttr.ItemsProviderType, _object); } var categoryAttr = property.FindAttribute <EditCategoryAttribute>(); record.Category = categoryAttr != null ? categoryAttr.Name : DefaultCategoryName; records.Add(record); } var fields = from f in _object.GetType().GetFields() select f; foreach (var field in fields) { if (!field.IsPublic || field.IsStatic) { continue; } var categoryAttr = field.FindAttribute <EditCategoryAttribute>(); var hasSetter = true; var readOnlyAttr = field.FindAttribute <ReadOnlyAttribute>(); if (readOnlyAttr != null && readOnlyAttr.IsReadOnly) { hasSetter = false; } var record = new FieldRecord(field) { HasSetter = hasSetter, Category = categoryAttr != null ? categoryAttr.Name : DefaultCategoryName }; records.Add(record); } // Sort by categories for (var i = 0; i < records.Count; ++i) { var record = records[i]; List <Record> categoryRecords; if (!_records.TryGetValue(record.Category, out categoryRecords)) { categoryRecords = new List <Record>(); _records[record.Category] = categoryRecords; } categoryRecords.Add(record); } // Sort by names within categories foreach (var category in _records) { category.Value.Sort((a, b) => Comparer <string> .Default.Compare(a.Name, b.Name)); } var ordered = _records.OrderBy(key => key.Key); var y = 0; List <Record> defaultCategoryRecords; if (_records.TryGetValue(Category, out defaultCategoryRecords)) { FillSubGrid(ref y, defaultCategoryRecords); } if (Category != DefaultCategoryName) { return; } foreach (var category in ordered) { if (category.Key == DefaultCategoryName) { continue; } var subGrid = new SubGrid(this, Object, category.Key, category.Key, null) { GridSpanX = 2, GridPositionY = y }; Widgets.Add(subGrid); if (_expandedCategories.Contains(category.Key)) { subGrid.Mark.IsPressed = true; } var rp = new Proportion(ProportionType.Auto); RowsProportions.Add(rp); y++; } }