Skip to content

Commit 9258896

Browse files
committed
支持跨程序集
1 parent a1c00c5 commit 9258896

6 files changed

Lines changed: 833 additions & 72 deletions

File tree

Demo/AutoSettingUI.Avalonia.CrossPlatform.Demo/AutoSettingUI.Avalonia.CrossPlatform.Demo/Models/ApplicationSettings.cs

Lines changed: 138 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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")]
6367
public 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

336428
public 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

Comments
 (0)