Skip to content

Commit a2c2b53

Browse files
committed
add support to communitytoolkit.mvvm
1 parent 1d84e63 commit a2c2b53

8 files changed

Lines changed: 367 additions & 44 deletions

File tree

Demo/AutoSettingUI.Ursa.Demo/AutoSettingUI.Ursa.Demo.csproj

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
<IsAotCompatible>true</IsAotCompatible>
99
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
1010
<NoWarn>$(NoWarn);IL2026;IL2057;IL2067;IL2070;IL2072;IL2075;IL2104;IL3050</NoWarn>
11+
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
12+
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
1113

1214
<PublishAot>true</PublishAot>
1315
<SelfContained>true</SelfContained>
@@ -36,18 +38,21 @@
3638
</ItemGroup>
3739

3840
<ItemGroup>
41+
<ProjectReference Include="..\..\src\AutoSettingUI.Generator\AutoSettingUI.Generator.csproj"
42+
OutputItemType="Analyzer"
43+
ReferenceOutputAssembly="false" />
3944
<ProjectReference Include="..\..\src\Extensions\AutoSettingUI.Ursa\AutoSettingUI.Ursa.csproj"
4045
RemoveProperties="PublishAot" />
4146
</ItemGroup>
4247

4348
<!-- Generator: project reference for normal builds, prebuilt analyzer for AOT publish -->
44-
<ItemGroup Condition="'$(PublishAot)' != 'true'">
45-
<ProjectReference Include="..\..\src\AutoSettingUI.Generator\AutoSettingUI.Generator.csproj"
46-
OutputItemType="Analyzer"
47-
ReferenceOutputAssembly="false" />
48-
</ItemGroup>
49+
<!-- <ItemGroup Condition="'$(PublishAot)' != 'true'">-->
50+
<!-- <ProjectReference Include="..\..\src\AutoSettingUI.Generator\AutoSettingUI.Generator.csproj"-->
51+
<!-- OutputItemType="Analyzer"-->
52+
<!-- ReferenceOutputAssembly="false" />-->
53+
<!-- </ItemGroup>-->
4954

50-
<ItemGroup Condition="'$(PublishAot)' == 'true'">
51-
<Analyzer Include="..\..\src\AutoSettingUI.Generator\bin\Release\netstandard2.0\AutoSettingUI.Generator.dll" />
52-
</ItemGroup>
55+
<!-- <ItemGroup Condition="'$(PublishAot)' == 'true'">-->
56+
<!-- <Analyzer Include="..\..\src\AutoSettingUI.Generator\bin\Release\netstandard2.0\AutoSettingUI.Generator.dll" />-->
57+
<!-- </ItemGroup>-->
5358
</Project>

Demo/AutoSettingUI.Ursa.Demo/Models/ApplicationSettings.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,19 @@ namespace AutoSettingUI.Ursa.Demo.Models;
2020
/// Sample application settings class demonstrating various AutoSettingUI features.
2121
/// </summary>
2222
[SettingUI]
23-
[MainHeader("Application Settings")]
24-
public class ApplicationSettings
23+
public partial class ApplicationSettings:ObservableObject
2524
{
25+
2626
[Title("Application Name")]
27-
public string AppName { get; set; } = "My Application";
27+
[ObservableProperty]
28+
private string _appName= "My Application";
2829

29-
30-
public string Version { get; set; } = "1.0.0";
30+
[ObservableProperty]
31+
private string _version="1.0.0";
3132

3233
[Title("Enable Logging")]
33-
public bool EnableLogging { get; set; } = true;
34+
[ObservableProperty]
35+
private bool _enableLogging;
3436

3537
[Title("Log Level")]
3638
public LogLevel LogLevel { get; set; } = LogLevel.Info;
@@ -62,7 +64,7 @@ public Slider VolumeFactory()
6264
/// Sample user preferences class demonstrating delegate properties and collection editors.
6365
/// </summary>
6466
[SettingUI]
65-
[MainHeader("User Preferences")]
67+
6668
public class UserPreferences : INotifyPropertyChanged
6769
{
6870
private bool _isAdmin = true;
@@ -74,7 +76,8 @@ protected virtual void OnPropertyChanged(string propertyName)
7476
{
7577
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
7678
}
77-
79+
80+
7881
[SubHeader("Display")]
7982
[Title("Theme")]
8083
public Theme Theme { get; set; } = Theme.Light;

README.md

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- 🔌 **Extensible** — Inject your own `ISettingDescriptorProvider` or `IPropertyValueAccessor` to override the defaults.
1111
- 🧭 **Built-in navigation** — Sections are listed in a sidebar tree; clicking navigates directly to the section.
1212
- 🎯 **Extended Controls** — Built-in support for ColorPicker, DatePicker, TimePicker, NumericUpDown, and more.
13+
- 🔄 **MVVM Support** — Works seamlessly with CommunityToolkit.Mvvm `[ObservableProperty]` attribute on partial classes.
1314

1415
## Installation
1516

@@ -86,7 +87,52 @@ For AOT support, also add the generator:
8687
dotnet add package AutoSettingUI.Generator
8788
```
8889

89-
### 2. Define a Settings Model
90+
### 2. Add Style References (Required for Avalonia/Ursa)
91+
92+
> **⚠️ Important:** For Avalonia and Ursa projects, you **must** add the theme style reference to your `App.axaml` file. Without this, the controls will not render correctly.
93+
94+
#### Avalonia
95+
96+
Add to your `App.axaml`:
97+
98+
```xml
99+
<Application xmlns="https://github.com/avaloniaui"
100+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
101+
x:Class="YourApp.App">
102+
<Application.Styles>
103+
<FluentTheme />
104+
<!-- Required for ColorPicker support (optional) -->
105+
<StyleInclude Source="avares://Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml"/>
106+
<!-- Required for AutoSettingUI.Avalonia -->
107+
<StyleInclude Source="avares://AutoSettingUI.Avalonia/Themes/Generic.axaml"/>
108+
</Application.Styles>
109+
</Application>
110+
```
111+
112+
#### Ursa
113+
114+
Add to your `App.axaml`:
115+
116+
```xml
117+
<Application xmlns="https://github.com/avaloniaui"
118+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
119+
xmlns:u-semi="https://irihi.tech/ursa/themes/semi"
120+
x:Class="YourApp.App">
121+
<Application.Styles>
122+
<u-semi:SemiTheme Locale="zh-CN" />
123+
<!-- Required for ColorPicker support (optional) -->
124+
<StyleInclude Source="avares://Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml"/>
125+
<!-- Required for AutoSettingUI.Ursa -->
126+
<StyleInclude Source="avares://AutoSettingUI.Ursa/Themes/Generic.axaml"/>
127+
</Application.Styles>
128+
</Application>
129+
```
130+
131+
#### WPF
132+
133+
WPF does not require additional style references. The default styles are included automatically.
134+
135+
### 3. Define a Settings Model
90136

91137
```csharp
92138
using AutoSettingUI.Core.Attributes;
@@ -116,7 +162,34 @@ public sealed class AppSettings
116162
}
117163
```
118164

119-
### 3. Bind the Panel
165+
#### Using with CommunityToolkit.Mvvm
166+
167+
AutoSettingUI supports `[ObservableProperty]` from CommunityToolkit.Mvvm. Use partial classes with private fields:
168+
169+
```csharp
170+
using CommunityToolkit.Mvvm.ComponentModel;
171+
using AutoSettingUI.Core.Attributes;
172+
173+
[SettingUI]
174+
[MainHeader("Application Settings")]
175+
public partial class ApplicationSettings : ObservableObject
176+
{
177+
[Title("Application Name")]
178+
[ObservableProperty]
179+
private string _appName = "My Application";
180+
181+
[ObservableProperty]
182+
private string _version = "1.0.0";
183+
184+
[Title("Enable Logging")]
185+
[ObservableProperty]
186+
private bool _enableLogging;
187+
}
188+
```
189+
190+
> **Note:** The source generator automatically detects fields marked with `[ObservableProperty]` and generates UI for the corresponding properties. Field naming conventions (`_fieldName` or `m_fieldName`) are automatically converted to property names (`FieldName`).
191+
192+
### 4. Bind the Panel
120193

121194
Avalonia:
122195

@@ -154,7 +227,7 @@ public class MainViewModel
154227
}
155228
```
156229

157-
### 4. AOT Support (Optional)
230+
### 5. AOT Support (Optional)
158231

159232
For Native AOT or trimming, make sure the generator is referenced by the **app** project. In most cases the generated provider is picked up automatically. If you want to force it (or you see fallback-to-TextBox in AOT), do:
160233

@@ -167,7 +240,7 @@ AotSettingRegistry.Provider = provider;
167240
AotSettingRegistry.Accessor = provider;
168241
```
169242

170-
### 5. Publish AOT (Example)
243+
### 6. Publish AOT (Example)
171244

172245
```bash
173246
# Ursa demo

README.zh-CN.md

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,21 @@
1010
- 🔌 **高度可扩展** — 可注入自定义 `ISettingDescriptorProvider``IPropertyValueAccessor`,覆盖默认实现。
1111
- 🧭 **内置导航栏** — 各设置分组以树形列表展示在侧边栏,点击即可滚动定位到对应区域。
1212
- 🎯 **扩展控件支持** — 内置 ColorPicker、DatePicker、TimePicker、NumericUpDown 等扩展控件。
13+
- 🔄 **MVVM 支持** — 完美支持 CommunityToolkit.Mvvm 的 `[ObservableProperty]` 特性,可在 partial 类上使用。
1314

1415
## 安装
1516

1617
根据你的 UI 框架选择对应的包:
1718

1819
```xml
1920
<!-- Avalonia -->
20-
<PackageReference Include="AutoSettingUI.Avalonia" Version="1.0.0" />
21+
<PackageReference Include="AutoSettingUI.Avalonia" />
2122

2223
<!-- Ursa (带 Ursa 主题的 Avalonia) -->
23-
<PackageReference Include="AutoSettingUI.Ursa" Version="1.0.0" />
24+
<PackageReference Include="AutoSettingUI.Ursa" />
2425

2526
<!-- WPF -->
26-
<PackageReference Include="AutoSettingUI.WPF" Version="1.0.0" />
27+
<PackageReference Include="AutoSettingUI.WPF" />
2728
```
2829

2930
> **注意:** `AutoSettingUI.Core` 会作为依赖自动引入。`AutoSettingUI.Generator` 仅在 AOT 场景需要,需要在应用项目中单独引用。
@@ -40,13 +41,13 @@
4041

4142
```xml
4243
<!-- Avalonia -->
43-
<PackageReference Include="AutoSettingUI.Avalonia" Version="1.0.0" />
44+
<PackageReference Include="AutoSettingUI.Avalonia" />
4445

4546
<!-- Ursa (带 Ursa 主题的 Avalonia) -->
46-
<PackageReference Include="AutoSettingUI.Ursa" Version="1.0.0" />
47+
<PackageReference Include="AutoSettingUI.Ursa" />
4748

4849
<!-- WPF -->
49-
<PackageReference Include="AutoSettingUI.WPF" Version="1.0.0" />
50+
<PackageReference Include="AutoSettingUI.WPF" />
5051
```
5152

5253
如需 AOT 支持,请在 **应用项目** 中额外引用源代码生成器:
@@ -87,6 +88,33 @@ public sealed class AppSettings
8788
}
8889
```
8990

91+
#### 配合 CommunityToolkit.Mvvm 使用
92+
93+
AutoSettingUI 支持 CommunityToolkit.Mvvm 的 `[ObservableProperty]` 特性。使用 partial 类和私有字段:
94+
95+
```csharp
96+
using CommunityToolkit.Mvvm.ComponentModel;
97+
using AutoSettingUI.Core.Attributes;
98+
99+
[SettingUI]
100+
[MainHeader("应用程序设置")]
101+
public partial class ApplicationSettings : ObservableObject
102+
{
103+
[Title("应用程序名称")]
104+
[ObservableProperty]
105+
private string _appName = "我的应用程序";
106+
107+
[ObservableProperty]
108+
private string _version = "1.0.0";
109+
110+
[Title("启用日志")]
111+
[ObservableProperty]
112+
private bool _enableLogging;
113+
}
114+
```
115+
116+
> **注意:** 源码生成器会自动检测标记了 `[ObservableProperty]` 的字段,并为对应的属性生成 UI。字段命名约定(`_fieldName``m_fieldName`)会自动转换为属性名(`FieldName`)。
117+
90118
### 3. 绑定面板
91119

92120
Avalonia:

src/AutoSettingUI.Core/Attributes/MainHeaderAttribute.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace AutoSettingUI.Core.Attributes;
55
/// Main headers create a container that groups subsequent properties until the next MainHeader or end.
66
/// They also appear in the navigation table of contents.
77
/// </summary>
8-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
8+
[AttributeUsage(AttributeTargets.Class /*| AttributeTargets.Property | AttributeTargets.Field*/, Inherited = false, AllowMultiple = false)]
99
public sealed class MainHeaderAttribute : Attribute
1010
{
1111
/// <summary>

0 commit comments

Comments
 (0)