@@ -33,6 +33,7 @@ public class AutoSettingGenerator : IIncrementalGenerator
3333 private const string PasswordAttributeName = "PasswordAttribute" ;
3434 private const string NumericUpDownAttributeName = "NumericUpDownAttribute" ; // Special handling needed - type depends on property type
3535 private const string ControlBindingDefaultsAttributeName = "ControlBindingDefaultsAttribute" ;
36+ private const string DisplayOrderAttributeName = "DisplayOrderAttribute" ;
3637
3738 // Diagnostic descriptors
3839 private static readonly DiagnosticDescriptor NonPublicClassWarning = new (
@@ -333,8 +334,17 @@ private static void AppendRegisterMethod(StringBuilder sb, INamedTypeSymbol cls,
333334 sb . AppendLine ( " string? currentSubTitle = null;" ) ;
334335 sb . AppendLine ( ) ;
335336
336- foreach ( var prop in GetPublicInstanceProperties ( cls , context ) )
337+ var allProps = GetPublicInstanceProperties ( cls , context ) . ToList ( ) ;
338+ var propsWithOrder = allProps . Select ( ( prop , index ) => new
337339 {
340+ Property = prop ,
341+ DisplayOrder = GetDisplayOrder ( prop ) ,
342+ DeclarationOrder = prop . DeclarationOrder
343+ } ) . ToList ( ) ;
344+
345+ foreach ( var item in propsWithOrder . OrderBy ( p => p . DisplayOrder ) . ThenBy ( p => p . DeclarationOrder ) )
346+ {
347+ var prop = item . Property ;
338348 if ( GetAttr ( prop , HideAttributeName ) != null ) continue ;
339349
340350 var subHeaderAttr = GetAttr ( prop , SubHeaderAttributeName ) ;
@@ -514,6 +524,15 @@ private static void AppendRegisterMethod(StringBuilder sb, INamedTypeSymbol cls,
514524 numericInc = TryGetNamedArgDouble ( cbAttr , "Increment" ) ?? 1.0 ;
515525 }
516526
527+ // DisplayOrder
528+ var displayOrderAttr = GetAttr ( prop , DisplayOrderAttributeName ) ;
529+ int displayOrder = 0 ;
530+ if ( displayOrderAttr != null && displayOrderAttr . ConstructorArguments . Length > 0 )
531+ {
532+ if ( displayOrderAttr . ConstructorArguments [ 0 ] . Value is int orderVal )
533+ displayOrder = orderVal ;
534+ }
535+
517536 // CollectionEditor
518537 var collEditorAttr = GetAttr ( prop , CollectionEditorAttributeName ) ;
519538 string ? collEditorTypeName = null ;
@@ -615,7 +634,8 @@ private static void AppendRegisterMethod(StringBuilder sb, INamedTypeSymbol cls,
615634 sb . AppendLine ( $ " { ( isNumericUpDown ? "true" : "false" ) } ,") ;
616635 sb . AppendLine ( $ " { numericMin } ,") ;
617636 sb . AppendLine ( $ " { numericMax } ,") ;
618- sb . AppendLine ( $ " { numericInc } );") ;
637+ sb . AppendLine ( $ " { numericInc } ,") ;
638+ sb . AppendLine ( $ " { displayOrder } );") ;
619639
620640 var varName = $ "pd_{ safeName } _{ EscapeName ( prop . Name ) } ";
621641 sb . AppendLine ( $ " if (currentSub != null) currentSub.Add({ varName } ); else directProps.Add({ varName } );") ;
@@ -676,6 +696,7 @@ private sealed class PropertyInfo
676696 public Location ? Location { get ; }
677697 public bool IsFromObservableProperty { get ; }
678698 public IFieldSymbol ? SourceField { get ; }
699+ public int DeclarationOrder { get ; }
679700
680701 public PropertyInfo (
681702 string name ,
@@ -685,7 +706,8 @@ public PropertyInfo(
685706 ImmutableArray < AttributeData > attributes ,
686707 Location ? location ,
687708 bool isFromObservableProperty ,
688- IFieldSymbol ? sourceField )
709+ IFieldSymbol ? sourceField ,
710+ int declarationOrder = 0 )
689711 {
690712 Name = name ;
691713 Type = type ;
@@ -695,11 +717,13 @@ public PropertyInfo(
695717 Location = location ;
696718 IsFromObservableProperty = isFromObservableProperty ;
697719 SourceField = sourceField ;
720+ DeclarationOrder = declarationOrder ;
698721 }
699722 }
700723
701724 private static IEnumerable < PropertyInfo > GetPublicInstanceProperties ( INamedTypeSymbol cls , SourceProductionContext context )
702725 {
726+ int order = 0 ;
703727 var properties = cls . GetMembers ( )
704728 . OfType < IPropertySymbol > ( )
705729 . Where ( p => p . DeclaredAccessibility == Accessibility . Public && ! p . IsStatic )
@@ -711,7 +735,8 @@ private static IEnumerable<PropertyInfo> GetPublicInstanceProperties(INamedTypeS
711735 p . GetAttributes ( ) ,
712736 p . Locations . FirstOrDefault ( ) ,
713737 false ,
714- null ) ) ;
738+ null ,
739+ order ++ ) ) ;
715740
716741 var allFields = cls . GetMembers ( ) . OfType < IFieldSymbol > ( ) . ToList ( ) ;
717742 var observableFields = new List < PropertyInfo > ( ) ;
@@ -728,7 +753,8 @@ private static IEnumerable<PropertyInfo> GetPublicInstanceProperties(INamedTypeS
728753 f . GetAttributes ( ) ,
729754 f . Locations . FirstOrDefault ( ) ,
730755 true ,
731- f ) ) ;
756+ f ,
757+ order ++ ) ) ;
732758 }
733759 }
734760
@@ -845,6 +871,17 @@ private static string GetPropertyNameFromField(string fieldName)
845871 } ) ;
846872 }
847873
874+ private static int GetDisplayOrder ( PropertyInfo prop )
875+ {
876+ var attr = GetAttr ( prop , DisplayOrderAttributeName ) ;
877+ if ( attr != null && attr . ConstructorArguments . Length > 0 )
878+ {
879+ if ( attr . ConstructorArguments [ 0 ] . Value is int orderVal )
880+ return orderVal ;
881+ }
882+ return 0 ;
883+ }
884+
848885 private static AttributeData ? GetAttrInherited ( ISymbol symbol , string baseName )
849886 {
850887 return symbol . GetAttributes ( ) . FirstOrDefault ( a =>
0 commit comments