@@ -32,10 +32,12 @@ public partial class ApplicationSettings : ObservableObject
3232 private bool _enableLogging ;
3333
3434 [ Title ( "Settings.LogLevel" , UseResourceKey = true ) ]
35+ [ Hide ( nameof ( ShouldHideLogging ) ) ]
3536 public LogLevel LogLevel { get ; set ; } = LogLevel . Info ;
3637
3738 [ Title ( "Settings.MaxLogSize" , UseResourceKey = true ) ]
3839 [ Range ( 1 , 100 ) ]
40+ [ Hide ( nameof ( ShouldHideLogging ) ) ]
3941 public int MaxLogSize { get ; set ; } = 10 ;
4042
4143 [ Title ( "Settings.Volume" , UseResourceKey = true ) ]
@@ -45,6 +47,8 @@ public partial class ApplicationSettings : ObservableObject
4547 [ Hide ]
4648 public string InternalId { get ; set ; } = Guid . NewGuid ( ) . ToString ( ) ;
4749
50+ public bool ShouldHideLogging => ! EnableLogging ;
51+
4852 public Slider VolumeFactory ( )
4953 {
5054 var slider = new Slider
@@ -62,11 +66,8 @@ public Slider VolumeFactory()
6266[ MainHeader ( "User Preferences" ) ]
6367public partial class UserPreferences : ObservableObject
6468{
65- private bool _isAdmin = true ;
6669 private string _email = "" ;
6770
68-
69-
7071 [ SubHeader ( "Display" ) ]
7172 [ Title ( "Theme" ) ]
7273 public Theme Theme { get ; set ; } = Theme . Light ;
@@ -97,33 +98,41 @@ public partial class UserPreferences : ObservableObject
9798 [ SubHeader ( "ReadOnly Examples" ) ]
9899 [ Title ( "Read-Only Field" ) ]
99100 [ ReadOnly ( true ) ]
100- public string ReadOnlyField { get ; set ; } = "This field is read-only" ;
101+ [ ObservableProperty ]
102+ private string _readOnlyField = "This field is read-only" ;
101103
102104 [ Title ( "Dynamic ReadOnly" ) ]
103105 [ ReadOnly ( nameof ( CanEdit ) ) ]
104- public string DynamicReadOnlyField { get ; set ; } = "Only editable by admins" ;
106+ [ ObservableProperty ]
107+ private string _dynamicReadOnlyField = "Only editable by admins" ;
108+
109+ [ Title ( "Dynamic ReadOnly" ) ]
110+ [ ReadOnly ( nameof ( CanEdit ) ) ]
111+ [ ObservableProperty ]
112+ [ NumericUpDown ( Minimum = 0 , Maximum = 100 , Increment = 1 ) ]
113+ private int _dynamicReadOnlyFieldInt = 42 ;
105114
106115 [ ControlBinding ( typeof ( CheckBox ) , "IsChecked" ) ]
107- public bool IsAdmin
108- {
109- get => _isAdmin ;
110- set
111- {
112- if ( _isAdmin != value )
113- {
114- _isAdmin = value ;
115- OnPropertyChanged ( nameof ( IsAdmin ) ) ;
116- }
117- }
118- }
116+ [ ObservableProperty ]
117+ private bool _isAdmin = true ;
119118
120119 [ SubHeader ( "Notifications" ) ]
121120 [ Title ( "Enable Notifications" ) ]
122- public bool EnableNotifications { get ; set ; } = true ;
121+ [ ObservableProperty ]
122+ private bool _enableNotifications = true ;
123123
124124 [ Title ( "Notification Sound" ) ]
125+ [ Hide ( nameof ( ShouldHideNotifications ) ) ]
125126 public bool NotificationSound { get ; set ; } = true ;
126127
128+ [ Title ( "Notification Email" ) ]
129+ [ Description ( "Email address for sending notifications" ) ]
130+ [ Hide ( nameof ( ShouldHideNotifications ) ) ]
131+ [ Placeholder ( "notifications@example.com" ) ]
132+ public string NotificationEmail { get ; set ; } = "" ;
133+
134+ public bool ShouldHideNotifications => ! EnableNotifications ;
135+
127136 [ Title ( "Email Address" ) ]
128137 [ Description ( "Your email address for notifications and account recovery" ) ]
129138 [ Placeholder ( "example@domain.com" ) ]
@@ -181,7 +190,8 @@ public string Email
181190 [ CollectionEditor ( SelectedItemProperty = nameof ( SelectedTag ) ) ]
182191 public ObservableCollection < string > Tags { get ; set ; } = [ "Important" , "Work" ] ;
183192
184- [ Title ( "Selected Tag" ) ] [ Description ( "The currently selected tag from the list above" ) ]
193+ [ Title ( "Selected Tag" ) ]
194+ [ Description ( "The currently selected tag from the list above" ) ]
185195 [ ObservableProperty ]
186196 private string ? _selectedTag ;
187197
@@ -197,7 +207,9 @@ public string Email
197207 new Person { Name = "Jane Smith" , Age = 25 , Email = "jane@example.com" }
198208 ] ;
199209
200- [ Title ( "Selected Person" ) ] [ Description ( "The currently selected person - edit details below" ) ] [ ObservableProperty ]
210+ [ Title ( "Selected Person" ) ]
211+ [ Description ( "The currently selected person - edit details below" ) ]
212+ [ ObservableProperty ]
201213 private Person ? _selectedPerson ;
202214
203215 public UserPreferences ( )
@@ -331,6 +343,86 @@ public partial class ExtendedControlsSettings : ObservableObject
331343 [ ObservableProperty ]
332344 [ DisplayOrder ( 1 ) ]
333345 private int _itemCount = 40 ;
346+
347+ #region ControlBinding Examples
348+
349+ [ SubHeader ( "ControlBinding Examples" ) ]
350+
351+ [ Title ( "Progress (Auto-bind)" ) ]
352+ [ Description ( "Uses ControlBinding with BindingProperty - auto binds to Value" ) ]
353+ [ ControlBinding ( typeof ( global ::Avalonia . Controls . ProgressBar ) , "Value" ) ]
354+ public double ProgressValue { get ; set ; } = 50.0 ;
355+
356+ [ Title ( "Custom Slider (Factory Method)" ) ]
357+ [ Description ( "Factory method handles binding manually - can customize converter, etc." ) ]
358+ [ ControlBinding ( typeof ( global ::Avalonia . Controls . Slider ) , FactoryMethod = nameof ( CreateCustomSlider ) ) ]
359+ public double CustomSliderValue { get ; set ; } = 75.0 ;
360+
361+ public global ::Avalonia . Controls . Slider CreateCustomSlider ( )
362+ {
363+ var slider = new global ::Avalonia . Controls . Slider
364+ {
365+ Minimum = 0 ,
366+ Maximum = 100 ,
367+ Width = 200
368+ } ;
369+
370+ slider . Bind ( global ::Avalonia . Controls . Slider . ValueProperty ,
371+ new global ::Avalonia . Data . Binding ( nameof ( CustomSliderValue ) )
372+ {
373+ Source = this ,
374+ Mode = global ::Avalonia . Data . BindingMode . TwoWay
375+ } ) ;
376+
377+ return slider ;
378+ }
379+
380+ [ Title ( "Auto-detected TextBox" ) ]
381+ [ Description ( "Only control type specified - auto-detects Text property" ) ]
382+ [ ControlBinding ( typeof ( global ::Avalonia . Controls . TextBox ) ) ]
383+ public string AutoDetectedText { get ; set ; } = "Auto-detected binding" ;
384+
385+ [ Title ( "Rating (Complex Factory)" ) ]
386+ [ Description ( "Factory creates a custom rating control with full customization" ) ]
387+ [ ControlBinding ( typeof ( global ::Avalonia . Controls . StackPanel ) , FactoryMethod = nameof ( CreateRatingControl ) ) ]
388+ [ ObservableProperty ]
389+ private int _rating = 3 ;
390+
391+ public global ::Avalonia . Controls . StackPanel CreateRatingControl ( )
392+ {
393+ var panel = new global ::Avalonia . Controls . StackPanel
394+ {
395+ Orientation = global ::Avalonia . Layout . Orientation . Horizontal ,
396+ Spacing = 5
397+ } ;
398+
399+ for ( int i = 1 ; i <= 5 ; i ++ )
400+ {
401+ var starIndex = i ;
402+ var button = new global ::Avalonia . Controls . Button
403+ {
404+ Content = "★" ,
405+ FontSize = 24 ,
406+ Width = 40 ,
407+ Height = 40
408+ } ;
409+
410+ button . Click += ( s , e ) => Rating = starIndex ;
411+
412+ button . Bind ( global ::Avalonia . Controls . Button . ForegroundProperty ,
413+ new global ::Avalonia . Data . Binding ( nameof ( Rating ) )
414+ {
415+ Source = this ,
416+ Converter = new RatingConverter ( starIndex )
417+ } ) ;
418+
419+ panel . Children . Add ( button ) ;
420+ }
421+
422+ return panel ;
423+ }
424+
425+ #endregion
334426}
335427
336428public enum AppTheme
@@ -384,3 +476,29 @@ private void ApplyTheme(AppTheme theme)
384476 }
385477 }
386478}
479+
480+ public class RatingConverter : global ::Avalonia . Data . Converters . IValueConverter
481+ {
482+ private readonly int _starIndex ;
483+
484+ public RatingConverter ( int starIndex )
485+ {
486+ _starIndex = starIndex ;
487+ }
488+
489+ public object ? Convert ( object ? value , Type targetType , object ? parameter , System . Globalization . CultureInfo culture )
490+ {
491+ if ( value is int rating )
492+ {
493+ return rating >= _starIndex
494+ ? global ::Avalonia . Media . Brushes . Gold
495+ : global ::Avalonia . Media . Brushes . Gray ;
496+ }
497+ return global ::Avalonia . Media . Brushes . Gray ;
498+ }
499+
500+ public object ? ConvertBack ( object ? value , Type targetType , object ? parameter , System . Globalization . CultureInfo culture )
501+ {
502+ throw new NotImplementedException ( ) ;
503+ }
504+ }
0 commit comments