├── .editorconfig
├── .gitattributes
├── .gitignore
├── Avalonia.PropertyGrid.sln
├── Directory.Build.props
├── Docs
└── Images
│ ├── ChangeSize.png
│ ├── CheckList.png
│ ├── CustomObject.png
│ ├── DynamicVisibility.png
│ ├── Multi-Objects.png
│ ├── Styles.png
│ ├── custom-label.png
│ ├── data-sync.png
│ ├── extends.png
│ ├── operation-example.png
│ ├── painter-demo.png
│ ├── self-properties.png
│ ├── settings-demo.png
│ └── undoredo.png
├── LICENSE
├── README-CHS.md
├── README.md
├── Samples
├── Avalonia.PropertyGrid.Samples.Android
│ ├── Avalonia.PropertyGrid.Samples.Android.csproj
│ ├── Icon.png
│ ├── MainActivity.cs
│ ├── Properties
│ │ └── AndroidManifest.xml
│ └── Resources
│ │ ├── AboutResources.txt
│ │ ├── drawable-night-v31
│ │ └── avalonia_anim.xml
│ │ ├── drawable-v31
│ │ └── avalonia_anim.xml
│ │ ├── drawable
│ │ └── splash_screen.xml
│ │ ├── values-night
│ │ └── colors.xml
│ │ ├── values-v31
│ │ └── styles.xml
│ │ └── values
│ │ ├── colors.xml
│ │ └── styles.xml
├── Avalonia.PropertyGrid.Samples.Browser
│ ├── Avalonia.PropertyGrid.Samples.Browser.csproj
│ ├── Program.cs
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── launchSettings.json
│ ├── runtimeconfig.template.json
│ └── wwwroot
│ │ ├── app.css
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── main.js
├── Avalonia.PropertyGrid.Samples.Desktop
│ ├── Avalonia.PropertyGrid.Samples.Desktop.csproj
│ ├── Program.cs
│ └── app.manifest
├── Avalonia.PropertyGrid.Samples.iOS
│ ├── AppDelegate.cs
│ ├── Avalonia.PropertyGrid.Samples.iOS.csproj
│ ├── Entitlements.plist
│ ├── Info.plist
│ ├── Main.cs
│ └── Resources
│ │ └── LaunchScreen.xib
├── Avalonia.PropertyGrid.Samples
│ ├── App.axaml
│ ├── App.axaml.cs
│ ├── Assets
│ │ ├── Localizations
│ │ │ ├── en-US.json
│ │ │ ├── ru-RU.json
│ │ │ └── zh-CN.json
│ │ ├── avalonia-banner.png
│ │ ├── avalonia-logo.ico
│ │ ├── country-flags
│ │ │ ├── au.png
│ │ │ ├── bl.png
│ │ │ ├── ca.png
│ │ │ ├── cn.png
│ │ │ ├── de.png
│ │ │ ├── gb.png
│ │ │ ├── ua.png
│ │ │ └── us.png
│ │ └── images
│ │ │ ├── colormixer.png
│ │ │ ├── home.png
│ │ │ └── technology.png
│ ├── Avalonia.PropertyGrid.Samples.csproj
│ ├── FeatureDemos
│ │ ├── Models
│ │ │ ├── CancelableObject.cs
│ │ │ ├── DynamicVisibilityObject.cs
│ │ │ ├── LoginInfo.cs
│ │ │ ├── ScriptableObject.cs
│ │ │ ├── ScriptableOptions.cs
│ │ │ ├── SimpleObject.cs
│ │ │ ├── TestExtendsObject.cs
│ │ │ ├── TypeDescriptionProvider.cs
│ │ │ └── Vector3.cs
│ │ ├── ViewModels
│ │ │ └── FeatureDemoViewModel.cs
│ │ └── Views
│ │ │ ├── CountryView.axaml
│ │ │ ├── CountryView.axaml.cs
│ │ │ ├── FeatureDemoView.axaml
│ │ │ ├── FeatureDemoView.axaml.cs
│ │ │ ├── TestExtendPropertyGrid.cs
│ │ │ ├── Vector3View.axaml
│ │ │ └── Vector3View.axaml.cs
│ ├── PainterDemo
│ │ ├── Models
│ │ │ ├── ArrowShape.cs
│ │ │ ├── BrushConfiguration.cs
│ │ │ ├── EllipseShape.cs
│ │ │ ├── FreehandShape.cs
│ │ │ ├── LineShape.cs
│ │ │ ├── RectangleShape.cs
│ │ │ ├── ShapeBase.cs
│ │ │ └── StarShape.cs
│ │ ├── ViewModel
│ │ │ └── PainterViewModel.cs
│ │ └── Views
│ │ │ ├── GradientStopView.axaml
│ │ │ ├── GradientStopView.axaml.cs
│ │ │ ├── PainterView.axaml
│ │ │ └── PainterView.axaml.cs
│ ├── SettingsDemo
│ │ ├── Models
│ │ │ ├── AboutSettings.cs
│ │ │ ├── AccountSettings.cs
│ │ │ ├── AppearanceSettings.cs
│ │ │ ├── FirewallSettings.cs
│ │ │ ├── GeneralSettings.cs
│ │ │ └── ThemeSettings.cs
│ │ ├── ViewModels
│ │ │ └── SettingsViewModel.cs
│ │ └── Views
│ │ │ ├── SettingsView.axaml
│ │ │ └── SettingsView.axaml.cs
│ └── Views
│ │ ├── MainView.axaml
│ │ ├── MainView.axaml.cs
│ │ ├── MainWindow.axaml
│ │ ├── MainWindow.axaml.cs
│ │ └── SampleLocalizationService.cs
└── Directory.Packages.props
├── Sources
├── Avalonia.PropertyGrid
│ ├── Assets
│ │ ├── Images
│ │ │ ├── add.png
│ │ │ ├── clear.png
│ │ │ ├── delete.png
│ │ │ ├── new.png
│ │ │ └── options.png
│ │ └── Localizations
│ │ │ ├── en-US.json
│ │ │ ├── ru-RU.json
│ │ │ └── zh-CN.json
│ ├── Avalonia.PropertyGrid.csproj
│ ├── Controls
│ │ ├── ButtonEdit.axaml
│ │ ├── ButtonEdit.axaml.cs
│ │ ├── CheckedListEdit.axaml
│ │ ├── CheckedListEdit.axaml.cs
│ │ ├── CheckedMask.axaml
│ │ ├── CheckedMask.axaml.cs
│ │ ├── Factories
│ │ │ ├── AbstractCellEditFactory.cs
│ │ │ └── Builtins
│ │ │ │ ├── BooleanCellEditFactory.cs
│ │ │ │ ├── CheckedListCellEditFactory.cs
│ │ │ │ ├── CollectionCellEditFactory.cs
│ │ │ │ ├── ColorCellEditFactory.cs
│ │ │ │ ├── CommonCellEditFactory.cs
│ │ │ │ ├── DateTimeCellEditFactory.cs
│ │ │ │ ├── EnumCellEditFactory.cs
│ │ │ │ ├── ExpandableCellEditFactory.cs
│ │ │ │ ├── FontFamilyCellEditFactory.cs
│ │ │ │ ├── ImageCellEditFactory.cs
│ │ │ │ ├── NumericCellEditFactory.cs
│ │ │ │ ├── PathCellEditFactory.cs
│ │ │ │ ├── ProgressCellEditFactory.cs
│ │ │ │ ├── SelectableListCellEditFactory.cs
│ │ │ │ ├── StringCellEditFactory.cs
│ │ │ │ ├── TimeCellEditFactory.cs
│ │ │ │ └── TrackableCellEditFactory.cs
│ │ ├── ICellEditFactory.cs
│ │ ├── ICellEditFactoryCollection.cs
│ │ ├── IPropertyGrid.cs
│ │ ├── IPropertyGridCellInfo.cs
│ │ ├── IPropertyGridFilterContext.cs
│ │ ├── Implements
│ │ │ ├── CellEditFactoryCollection.cs
│ │ │ ├── PropertyGridCellInfo.cs
│ │ │ ├── PropertyGridExpandableCache.cs
│ │ │ └── PropertyGridFilterPattern.cs
│ │ ├── ListEdit.axaml
│ │ ├── ListEdit.axaml.cs
│ │ ├── ListElementEdit.axaml
│ │ ├── ListElementEdit.axaml.cs
│ │ ├── ListElementPlaceholderEdit.axaml
│ │ ├── ListElementPlaceholderEdit.axaml.cs
│ │ ├── PropertyGrid.axaml
│ │ ├── PropertyGrid.axaml.cs
│ │ ├── RadioButtonListEdit.axaml
│ │ ├── RadioButtonListEdit.axaml.cs
│ │ ├── ToggleButtonGroupListEdit.axaml
│ │ ├── ToggleButtonGroupListEdit.axaml.cs
│ │ ├── TrackableEdit.axaml
│ │ └── TrackableEdit.axaml.cs
│ ├── Localization
│ │ ├── AssemblyJsonAssetLocalizationService.cs
│ │ ├── AssetCultureData.cs
│ │ ├── LocalizationExtensions.cs
│ │ └── LocalizeExtension.cs
│ ├── Services
│ │ ├── CellEditFactoryService.cs
│ │ └── LocalizationService.cs
│ ├── Utils
│ │ ├── EnumUtils.cs
│ │ ├── FontUtils.cs
│ │ ├── InverseBooleanConverter.cs
│ │ ├── PathBrowserUtils.cs
│ │ ├── PropertyObserver.cs
│ │ └── TextBlockInlinesUtils.cs
│ └── ViewModels
│ │ ├── PropertyGridViewModel.cs
│ │ ├── ReferencePath.cs
│ │ └── SingleSelectListViewModel.cs
├── PropertyModels
│ ├── Collections
│ │ ├── CheckedList.cs
│ │ └── SelectableList.cs
│ ├── ComponentModel
│ │ ├── AutoCollapseCategoriesAttribute.cs
│ │ ├── CancelableCommandRecorder.cs
│ │ ├── CheckedMaskModel.cs
│ │ ├── ControlClassesAttribute.cs
│ │ ├── DataAnnotations
│ │ │ ├── DependsOnPropertyAttribute.cs
│ │ │ ├── EnumValueAuthorizeAttribute.cs
│ │ │ ├── FileNameValidationAttribute.cs
│ │ │ ├── FloatingNumberEqualToleranceAttribute.cs
│ │ │ ├── ImagePreviewModeAttribute.cs
│ │ │ ├── PathBrowsableAttribute.cs
│ │ │ ├── ValidationResultExtensions.cs
│ │ │ ├── ValidatorUtils.cs
│ │ │ └── VisiblityDependencyAttribute.cs
│ │ ├── EnumDisplayNameAttribute.cs
│ │ ├── ExpandableObjectDisplayModeAttribute.cs
│ │ ├── FloatPrecisionAttribute.cs
│ │ ├── FormatStringAttribute.cs
│ │ ├── ICheckedMaskModel.cs
│ │ ├── ICommand.cs
│ │ ├── IFilterPattern.cs
│ │ ├── INotifyCommandExecuting.cs
│ │ ├── INotifyPropertyChanged.cs
│ │ ├── INotifyPropertyChanging.cs
│ │ ├── IReactiveObject.cs
│ │ ├── IntegerIncrementAttribute.cs
│ │ ├── ListElementPropertyDescriptor.cs
│ │ ├── MultiObjectPropertyDescriptor.cs
│ │ ├── MultilineTextAttribute.cs
│ │ ├── ObjectCreator.cs
│ │ ├── ProgressAttribute.cs
│ │ ├── PropertyOperationVisibilityAttribute.cs
│ │ ├── ReactiveCommand.cs
│ │ ├── SelectableListDisplayModeAttribute.cs
│ │ ├── SingleSelectionModeAttribute.cs
│ │ ├── TrackableAttribute.cs
│ │ ├── UnitAttribute.cs
│ │ └── WatermarkAttribute.cs
│ ├── Extensions
│ │ ├── LinqExtensions.cs
│ │ ├── PropertyDescriptorExtensions.cs
│ │ ├── StringExtensions.cs
│ │ └── TypeExtensions.cs
│ ├── Localization
│ │ ├── CultureData.cs
│ │ └── ILocalizationService.cs
│ ├── PropertyModels.csproj
│ └── Utils
│ │ ├── DecimalConvertUtils.cs
│ │ └── PropertyDescriptorBuilder.cs
├── README_NUGET.md
└── README_PropertyModels.md
├── UnitTests
└── Avalonia.PropertyGrid.UnitTests
│ ├── Avalonia.PropertyGrid.UnitTests.csproj
│ ├── Model
│ ├── UnitTest_DecimalConvert.cs
│ └── UnitTest_Utils.cs
│ └── Usings.cs
└── publish-web.bat
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 | indent_style = space
3 | indent_size = 4
4 |
5 | csharp_style_expression_bodied_methods = true
6 | csharp_style_expression_bodied_properties = when_on_single_line
7 | csharp_style_expression_bodied_accessors = true
8 | csharp_style_expression_bodied_indexers = true
9 | csharp_style_expression_bodied_lambdas = true
10 | csharp_style_expression_bodied_operators = true
11 | csharp_style_unused_value_assignment_preference = discard_variable
12 |
13 | dotnet_sort_system_directives_first = true
14 | dotnet_diagnostic.IDE0046.severity = none
15 |
16 | resharper_convert_to_primary_constructor_highlighting = none
17 | csharp_style_prefer_primary_constructors = false
18 | dotnet_diagnostic.IDE0290.severity = none
19 |
20 | resharper_member_can_be_private_global_highlighting = none
21 | resharper_class_never_instantiated_global_highlighting = none
22 | resharper_event_never_subscribed_to_global_highlighting = none
23 | resharper_unused_member_global_highlighting = none
24 | resharper_unused_type_global_highlighting = none
25 | resharper_unused_member_in_super_global_highlighting = none
26 | resharper_not_accessed_field_global_highlighting = none
27 | resharper_member_can_be_protected_global_highlighting = none
28 | resharper_virtual_member_never_overridden_global_highlighting = none
29 | dotnet_diagnostic.IDE0051.severity = none
30 |
31 | resharper_unused_parameter_global_highlighting = none
32 | resharper_unused_parameter_local_highlighting = none
33 | dotnet_diagnostic.IDE0060.severity = none
34 |
35 | resharper_convert_if_statement_to_switch_statement_highlighting = none
36 | dotnet_diagnostic.IDE0010.severity = none
37 |
38 | resharper_unused_method_return_value_global_highlighting = none
39 | dotnet_diagnostic.IDE0058.severity = none
40 |
41 | resharper_arrange_redundant_parentheses_highlighting = none
42 | dotnet_diagnostic.IDE0004.severity = none
43 |
44 | # resharper-specific
45 | resharper_loop_can_be_converted_to_query_highlighting = none
46 | resharper_foreach_can_be_partly_converted_to_query_using_another_get_enumerator_highlighting = none
47 | resharper_arrange_namespace_body_highlighting = none
48 | resharper_base_object_get_hash_code_call_in_get_hash_code_highlighting = none
49 | resharper_invert_if_highlighting = none
50 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.bin filter=lfs diff=lfs merge=lfs -text
2 | *.vsix filter=lfs diff=lfs merge=lfs -text
3 | *.exe filter=lfs diff=lfs merge=lfs -text
4 | *.dll filter=lfs diff=lfs merge=lfs -text
5 | *.dylib filter=lfs diff=lfs merge=lfs -text
6 | *.msi filter=lfs diff=lfs merge=lfs -text
7 | *.zip filter=lfs diff=lfs merge=lfs -text
8 | *.7z filter=lfs diff=lfs merge=lfs -text
9 | *.rar filter=lfs diff=lfs merge=lfs -text
10 | *.pdb filter=lfs diff=lfs merge=lfs -text
11 | *.lib filter=lfs diff=lfs merge=lfs -text
12 | *.so filter=lfs diff=lfs merge=lfs -text
13 | *.pdf filter=lfs diff=lfs merge=lfs -text
14 | *.chm filter=lfs diff=lfs merge=lfs -text
15 | *.pyd filter=lfs diff=lfs merge=lfs -text
16 | *.dmg filter=lfs diff=lfs merge=lfs -text
17 | *.mdb filter=lfs diff=lfs merge=lfs -text
18 | *.psd filter=lfs diff=lfs merge=lfs -text
19 | *.png filter=lfs diff=lfs merge=lfs -text
20 | *.tga filter=lfs diff=lfs merge=lfs -text
21 | *.jpg filter=lfs diff=lfs merge=lfs -text
22 | *.bmp filter=lfs diff=lfs merge=lfs -text
23 | *.mp3 filter=lfs diff=lfs merge=lfs -text
24 | *.mp4 filter=lfs diff=lfs merge=lfs -text
25 | *.mov filter=lfs diff=lfs merge=lfs -text
26 | *.ogg filter=lfs diff=lfs merge=lfs -text
27 | *.svg filter=lfs diff=lfs merge=lfs -text
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | enable
4 | 11.0.0
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Docs/Images/ChangeSize.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:4a3276a8e06dfda335308436a4162854a6188cbaa719492b62a555a1735d7614
3 | size 750904
4 |
--------------------------------------------------------------------------------
/Docs/Images/CheckList.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:4f447870b6568ff16052ade3de1bd725ea606e3e6a3a6d0728b47dcc847bb4a9
3 | size 62848
4 |
--------------------------------------------------------------------------------
/Docs/Images/CustomObject.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:a7001d5c419311ec3f926616aa2c6d90174e48c7c8c63d93af753f1e9829e731
3 | size 302942
4 |
--------------------------------------------------------------------------------
/Docs/Images/DynamicVisibility.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:42b82d7eb769f23d10e81176dfcf099725824202a369fc220dc860ac0ff77098
3 | size 240380
4 |
--------------------------------------------------------------------------------
/Docs/Images/Multi-Objects.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:66be7457d9fa3b7ef9f10f55b9bd00d512a439d56235c810d27628a2ab77dea6
3 | size 432864
4 |
--------------------------------------------------------------------------------
/Docs/Images/Styles.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:2da23d1501aca917bc281cff6956dd2dd77302184754206be72a966b1b77e6ff
3 | size 973646
4 |
--------------------------------------------------------------------------------
/Docs/Images/custom-label.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:8a29312167f11e46d2849ec38a011a147b814b32a9553a4ef355580f36dce945
3 | size 47551
4 |
--------------------------------------------------------------------------------
/Docs/Images/data-sync.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:9b181a99e5aa6e9d0b5e9edc4a5a68d0a2a298550a1c91f5a974a7f3bce3f443
3 | size 333673
4 |
--------------------------------------------------------------------------------
/Docs/Images/extends.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:e1212436015fdb4d9d58d7575b736afb931313a23d7ae430f5f3be7f72842f94
3 | size 325923
4 |
--------------------------------------------------------------------------------
/Docs/Images/operation-example.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:7341824fdd7cf2905c54a99cb3775f6dc3dda58c2fac9640f3affcd1ddf7b3c1
3 | size 390274
4 |
--------------------------------------------------------------------------------
/Docs/Images/painter-demo.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:dca2b21b2f5a00fcf37bd85c41b7add31a4aa8e92b927a47bc95ecfbc9207e9a
3 | size 344380
4 |
--------------------------------------------------------------------------------
/Docs/Images/self-properties.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:18a968df65af9afdf90c565317e18b469ac56bf120e2ae1f760e27bab4c526bd
3 | size 163397
4 |
--------------------------------------------------------------------------------
/Docs/Images/settings-demo.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:f8c6c5af64ea8efa3870d4f86a2282b27008bb1cf89435c6b43ca3463b00240a
3 | size 182754
4 |
--------------------------------------------------------------------------------
/Docs/Images/undoredo.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:71e68448c23715e4d991207ff4cf9d50bfcb1290cd61e3c068cb22583adc50ec
3 | size 276442
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 bodong
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Avalonia.PropertyGrid.Samples.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net8.0-android
5 | 21
6 | enable
7 | com.CompanyName.Avalonia.PropertyGrid.Samples
8 | 1
9 | 1.0
10 | apk
11 | false
12 | Debug;Release;Development
13 |
14 |
15 |
16 | DEBUG;TRACE
17 |
18 |
19 |
20 |
21 | Resources\drawable\Icon.png
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Icon.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:1821e7bd48a6f407bddcbc1fd789132a3d5b6a5b787951114e3360b4bd650c96
3 | size 14349
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content.PM;
3 | using Avalonia.Android;
4 |
5 | namespace Avalonia.PropertyGrid.Samples.Android;
6 |
7 | [Activity(
8 | Label = "Avalonia.PropertyGrid.Samples.Android",
9 | Theme = "@style/MyTheme.NoActionBar",
10 | Icon = "@drawable/icon",
11 | MainLauncher = true,
12 | ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
13 | public class MainActivity : AvaloniaMainActivity
14 | {
15 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
16 | {
17 | return base.CustomizeAppBuilder(builder)
18 | .WithInterFont();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.axml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Resources/drawable-night-v31/avalonia_anim.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
11 |
15 |
16 |
20 |
25 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
42 |
43 |
44 |
45 |
46 |
53 |
54 |
55 |
56 |
57 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Resources/drawable/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Resources/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #212121
4 |
5 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Resources/values-v31/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
5 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Browser/Avalonia.PropertyGrid.Samples.Browser.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0-browser
4 | Exe
5 | true
6 | enable
7 | Debug;Release;Development
8 | browser-wasm
9 | false
10 |
11 |
12 |
13 | DEBUG;TRACE
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Browser/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using Avalonia;
3 | using Avalonia.Browser;
4 | using Avalonia.PropertyGrid.Samples;
5 |
6 | internal sealed partial class Program
7 | {
8 | private static Task Main(string[] args) => BuildAvaloniaApp()
9 | .WithInterFont()
10 | .StartBrowserAppAsync("out");
11 |
12 | public static AppBuilder BuildAvaloniaApp()
13 | => AppBuilder.Configure().WithFont_SourceHanSansCN();
14 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Browser/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly: System.Runtime.Versioning.SupportedOSPlatform("browser")]
2 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Browser/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "Avalonia.PropertyGrid.Samples.Browser": {
4 | "commandName": "Project",
5 | "launchBrowser": true,
6 | "environmentVariables": {
7 | "ASPNETCORE_ENVIRONMENT": "Development"
8 | },
9 | "applicationUrl": "https://localhost:7178;http://localhost:5278",
10 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Browser/runtimeconfig.template.json:
--------------------------------------------------------------------------------
1 | {
2 | "wasmHostProperties": {
3 | "perHostConfig": [
4 | {
5 | "name": "browser",
6 | "host": "browser"
7 | }
8 | ]
9 | }
10 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Browser/wwwroot/app.css:
--------------------------------------------------------------------------------
1 | /* HTML styles for the splash screen */
2 | .avalonia-splash {
3 | position: absolute;
4 | height: 100%;
5 | width: 100%;
6 | background: white;
7 | font-family: 'Outfit', sans-serif;
8 | justify-content: center;
9 | align-items: center;
10 | display: flex;
11 | pointer-events: none;
12 | }
13 |
14 | /* Light theme styles */
15 | @media (prefers-color-scheme: light) {
16 | .avalonia-splash {
17 | background: white;
18 | }
19 |
20 | .avalonia-splash h2 {
21 | color: #1b2a4e;
22 | }
23 |
24 | .avalonia-splash a {
25 | color: #0D6EFD;
26 | }
27 | }
28 |
29 | @media (prefers-color-scheme: dark) {
30 | .avalonia-splash {
31 | background: #1b2a4e;
32 | }
33 |
34 | .avalonia-splash h2 {
35 | color: white;
36 | }
37 |
38 | .avalonia-splash a {
39 | color: white;
40 | }
41 | }
42 |
43 | .avalonia-splash h2 {
44 | font-weight: 400;
45 | font-size: 1.5rem;
46 | }
47 |
48 | .avalonia-splash a {
49 | text-decoration: none;
50 | font-size: 2.5rem;
51 | display: block;
52 | }
53 |
54 | .avalonia-splash.splash-close {
55 | transition: opacity 200ms, display 200ms;
56 | display: none;
57 | opacity: 0;
58 | }
59 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Browser/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bodong1987/Avalonia.PropertyGrid/8e1ccd0c7e40ec1f01df6b753315318a3a103d36/Samples/Avalonia.PropertyGrid.Samples.Browser/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Browser/wwwroot/main.js:
--------------------------------------------------------------------------------
1 | import { dotnet } from './_framework/dotnet.js'
2 |
3 | const is_browser = typeof window != "undefined";
4 | if (!is_browser) throw new Error(`Expected to be running in a browser`);
5 |
6 | const dotnetRuntime = await dotnet
7 | .withDiagnosticTracing(false)
8 | .withApplicationArgumentsFromQuery()
9 | .create();
10 |
11 | const config = dotnetRuntime.getConfig();
12 |
13 | await dotnetRuntime.runMain(config.mainAssemblyName, [globalThis.location.href]);
14 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Desktop/Avalonia.PropertyGrid.Samples.Desktop.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 |
6 | net8.0;net9.0
7 | enable
8 | true
9 | Debug;Release;Development
10 |
11 |
12 |
13 | DEBUG;TRACE
14 |
15 |
16 |
17 | app.manifest
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Desktop/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia;
3 | using Avalonia.Platform;
4 |
5 | namespace Avalonia.PropertyGrid.Samples.Desktop;
6 |
7 | internal sealed class Program
8 | {
9 | // Initialization code. Don't use any Avalonia, third-party APIs or any
10 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
11 | // yet and stuff might break.
12 | [STAThread]
13 | public static void Main(string[] args) => BuildAvaloniaApp()
14 | .StartWithClassicDesktopLifetime(args);
15 |
16 | // Avalonia configuration, don't remove; also used by visual designer.
17 | public static AppBuilder BuildAvaloniaApp()
18 | => AppBuilder.Configure()
19 | .UsePlatformDetect()
20 | .WithInterFont()
21 | .LogToTrace().AfterSetup(builder=>
22 | {
23 | builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions()
24 | {
25 | StartupScreenIndex = 1,
26 | });
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.Desktop/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.iOS;
2 | using Foundation;
3 |
4 | namespace Avalonia.PropertyGrid.Samples.iOS;
5 |
6 | // The UIApplicationDelegate for the application. This class is responsible for launching the
7 | // User Interface of the application, as well as listening (and optionally responding) to
8 | // application events from iOS.
9 | [Register("AppDelegate")]
10 | #pragma warning disable CA1711 // Identifiers should not have incorrect suffix
11 | public partial class AppDelegate : AvaloniaAppDelegate
12 | #pragma warning restore CA1711 // Identifiers should not have incorrect suffix
13 | {
14 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
15 | {
16 | return base.CustomizeAppBuilder(builder)
17 | .WithInterFont();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.iOS/Avalonia.PropertyGrid.Samples.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net8.0-ios
5 | 13.0
6 | enable
7 | Debug;Release;Development
8 |
9 |
10 |
11 | DEBUG;TRACE
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | Avalonia.PropertyGrid.Samples
7 | CFBundleIdentifier
8 | companyName.Avalonia.PropertyGrid.Samples
9 | CFBundleShortVersionString
10 | 1.0
11 | CFBundleVersion
12 | 1.0
13 | LSRequiresIPhoneOS
14 |
15 | MinimumOSVersion
16 | 13.0
17 | UIDeviceFamily
18 |
19 | 1
20 | 2
21 |
22 | UILaunchStoryboardName
23 | LaunchScreen
24 | UIRequiredDeviceCapabilities
25 |
26 | armv7
27 |
28 | UISupportedInterfaceOrientations
29 |
30 | UIInterfaceOrientationPortrait
31 | UIInterfaceOrientationPortraitUpsideDown
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace Avalonia.PropertyGrid.Samples.iOS;
4 |
5 | public class Application
6 | {
7 | // This is the main entry point of the application.
8 | private static void Main(string[] args)
9 | {
10 | // if you want to use a different Application Delegate class from "AppDelegate"
11 | // you can specify it here.
12 | UIApplication.Main(args, null, typeof(AppDelegate));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples.iOS/Resources/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/App.axaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | #33000000
16 | #99000000
17 | #FFE6E6E6
18 | #FF000000
19 |
20 |
21 | #33FFFFFF
22 | #99FFFFFF
23 | #FF1F1F1F
24 | #FFFFFFFF
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/Localizations/en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "Dynamic_Visibility": "Dynamic Visibility",
3 | "Self_s_Properties": "Self's Properties",
4 | "Show_Category": "Show Category",
5 | "Allow_Filter": "Allow Filter",
6 | "Allow_Quick_Filter": "Allow Quick Filter",
7 | "Show_Title": "Show Title",
8 | "Name_Width": "Name Width",
9 | "Show_Style": "Show Style",
10 | "All_Expand": "All Expand",
11 | "Display_Mode": "Display Mode",
12 | "customLabel": "Custom Label",
13 | "Show_Property_Operation": "Show Property Operations",
14 | "CellEdit_Alignment": "CellEdit Alignment",
15 | "ServiceDefaultView": "Service[Default View]",
16 | "ServiceVerticalView": "Service[Vertical View]",
17 | "ServiceHorizontalView": "Service[Horizontal View]",
18 | "CheckedListString": "Checkable String[Default View]",
19 | "CheckedListInt": "Checkable Number",
20 | "CheckedListStringVerticalView": "Checkable String[Vertical View]",
21 | "CheckedListStringHorizontalView": "Checkable String[Horizontal View]",
22 | "PlatformDefaultView": "Platform[Default View]",
23 | "PlatformRadioButtonDefaultView": "Platform[Radio+Default View]",
24 | "PlatformRadioButtonVerticalView": "Platform[Radio+Vertical View]",
25 | "PlatformRadioButtonHorizontalView": "Platform[Radio+Horizontal View]",
26 | "PlatformToggleButtonDefaultView": "Platform[Button+Default View]",
27 | "PlatformToggleButtonVerticalView": "Platform[Button+Vertical View]",
28 | "PlatformToggleButtonHorizontalView": "Platform[Button+Horizontal View]",
29 | "LoginNameToggleGroupModeVerticalView": "Login Name[Button+Vertical View]",
30 | "ArrowShape": "Arrow",
31 | "EllipseShape": "Ellipse",
32 | "LineShape": "Segment",
33 | "RectangleShape": "Rectangle",
34 | "StarShape": "Star",
35 | "CreateRectangle": "Create Rectangle",
36 | "CreateEllipse": "Create Ellipse",
37 | "CreateLine": "Create Line",
38 | "CreateStar": "Create Star",
39 | "CreateArrow": "Create Arrow",
40 | "DeleteShape": "Delete Shape",
41 | "FreehandShape": "Freehand",
42 | "Add_Shapes": "Add Shapes",
43 | "Delete_Shape": "Delete Shape",
44 | "PainterDemo_HelpText": "Select the working mode in the toolbar on the left, right-click to delete the element, click the element in the selection mode to view and edit the element properties, and you can also drag the element."
45 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/avalonia-banner.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:3cf6986fe87c909c5003ff1ff90f821b3f9888e755d49c8c24e71f7e6dc09ac1
3 | size 949838
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/avalonia-logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bodong1987/Avalonia.PropertyGrid/8e1ccd0c7e40ec1f01df6b753315318a3a103d36/Samples/Avalonia.PropertyGrid.Samples/Assets/avalonia-logo.ico
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/country-flags/au.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:4cfb3a5cfd1cb5736c41aa4318552b1aa7834cd165773356f98ff78354730f04
3 | size 1643
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/country-flags/bl.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:3cea4188fe697208358e1d648688e3856ca615324a20d76c4d0dd602e1121d56
3 | size 167
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/country-flags/ca.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:18ce040eff501b5d448989fb9ec168b6a14fc1a31c00aace5c08881c22700126
3 | size 832
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/country-flags/cn.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:cd70d32c9a9f6ebeaa821a9df846222ab7540fdb9ce98279fde8efdba5650366
3 | size 755
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/country-flags/de.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:91a6912f55fe250dc0e1c82a8cbf3889caa822a763ce8419fd5721d576cbec95
3 | size 106
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/country-flags/gb.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:3945b5f183e0729ffb90ee38ff78aba7916e09d172232623d0ffdac6409932e8
3 | size 500
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/country-flags/ua.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:010e4ea25f1da4d066a218606867aee772a7f6ad3d1a2370e8306f245759a7a1
3 | size 115
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/country-flags/us.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:25be2de75e2d2e55620068642f3225a7f90ff68fad65b6d1dc9d63daeafdbb74
3 | size 756
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/images/colormixer.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:e7ca09ed40d4bde1fcd1fa0531fde93188af2567f3f445a8530e27e891ef15cc
3 | size 1218
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/images/home.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:91e6dc34364ce7a159442573f12b019ecd7c65dfc19f4f6f47b3a82d0ced85bd
3 | size 1067
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Assets/images/technology.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:2b41a318cc211c8b596bf7e015ddcfaa6e44e4188445d8dc57fffcd8d667ca82
3 | size 1383
4 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Avalonia.PropertyGrid.Samples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0;net9.0
4 | enable
5 | latest
6 | Debug;Release;Development
7 | false
8 |
9 |
10 |
11 | DEBUG;TRACE
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | CountryView.axaml
40 | Code
41 |
42 |
43 | Vector3View.axaml
44 | Code
45 |
46 |
47 | FeatureDemoView.axaml
48 | Code
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/FeatureDemos/Models/CancelableObject.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Windows.Input;
3 | using Avalonia.PropertyGrid.Controls;
4 | using PropertyModels.ComponentModel;
5 |
6 | namespace Avalonia.PropertyGrid.Samples.FeatureDemos.Models
7 | {
8 | public class CancelableObject : SimpleObject
9 | {
10 | private readonly CancelableCommandRecorder _recorder = new();
11 |
12 | [Browsable(false)]
13 | public bool CanUndo => _recorder.CanUndo;
14 |
15 | [Browsable(false)]
16 | public bool CanRedo => _recorder.CanRedo;
17 |
18 | [Browsable(false)]
19 | public string UndoDescription => _recorder.UndoCommandDescription;
20 |
21 | [Browsable(false)]
22 | public string RedoDescription => _recorder.RedoCommandDescription;
23 |
24 | [Browsable(false)]
25 | public ICommand UndoCommand { get; set; }
26 |
27 | [Browsable(false)]
28 | public ICommand RedoCommand { get; set; }
29 |
30 | [Browsable(false)]
31 | public ICommand ClearCommand { get; set; }
32 |
33 | public CancelableObject(string description) : base(description)
34 | {
35 | UndoCommand = ReactiveCommand.Create(() => _recorder.Undo());
36 | RedoCommand = ReactiveCommand.Create(() => _recorder.Redo());
37 | ClearCommand = ReactiveCommand.Create(_recorder.Clear);
38 |
39 | _recorder.OnNewCommandAdded += (s, e) => RefreshFlags();
40 | _recorder.OnCommandCanceled += (s, e) => RefreshFlags();
41 | _recorder.OnCommandCleared += (s, e) => RefreshFlags();
42 | _recorder.OnCommandRedo += (s, e) => RefreshFlags();
43 | }
44 |
45 | private void RefreshFlags()
46 | {
47 | RaisePropertyChanged(nameof(CanUndo));
48 | RaisePropertyChanged(nameof(CanRedo));
49 | RaisePropertyChanged(nameof(UndoDescription));
50 | RaisePropertyChanged(nameof(RedoDescription));
51 | }
52 |
53 | public void OnCommandExecuted(object? sender, RoutedCommandExecutedEventArgs e) => _recorder.PushCommand(e.Command);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/FeatureDemos/Models/DynamicVisibilityObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using PropertyModels.ComponentModel;
4 | using PropertyModels.ComponentModel.DataAnnotations;
5 | using PropertyModels.Extensions;
6 | // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
7 |
8 | namespace Avalonia.PropertyGrid.Samples.FeatureDemos.Models
9 | {
10 | public class DynamicVisibilityObject : ReactiveObject
11 | {
12 | [ConditionTarget]
13 | public bool IsShowPath { get; set; } = true;
14 |
15 | [PropertyVisibilityCondition(nameof(IsShowPath), true)]
16 | [PathBrowsable(Filters = "Image Files(*.jpg;*.png;*.bmp;*.tag)|*.jpg;*.png;*.bmp;*.tag")]
17 | public string Path { get; set; } = string.Empty;
18 |
19 | [ConditionTarget]
20 | public PlatformID Platform { get; set; } = PlatformID.Win32NT;
21 |
22 | [PropertyVisibilityCondition(nameof(Platform), PlatformID.Unix)]
23 | [ConditionTarget]
24 | public string UnixVersion { get; set; } = string.Empty;
25 |
26 | // show more complex conditions...
27 | [Browsable(false)]
28 | [DependsOnProperty(nameof(IsShowPath), nameof(Platform), nameof(UnixVersion))]
29 | [ConditionTarget]
30 | public bool IsShowUnixLoginInfo => IsShowPath && Platform == PlatformID.Unix && UnixVersion.IsNotNullOrEmpty();
31 |
32 | [PropertyVisibilityCondition(nameof(IsShowUnixLoginInfo), true)]
33 | [TypeConverter(typeof(ExpandableObjectConverter))]
34 | // ReSharper disable once InconsistentNaming
35 | public LoginInfo unixLogInInfo { get; set; } = new();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/FeatureDemos/Models/LoginInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Net.Security;
4 | using System.Security.Cryptography;
5 | using PropertyModels.ComponentModel;
6 |
7 | namespace Avalonia.PropertyGrid.Samples.FeatureDemos.Models
8 | {
9 | public class LoginInfo : MiniReactiveObject
10 | {
11 | [Watermark("Your Login Name")]
12 | public string? UserName { get; set; }
13 |
14 | [PasswordPropertyText(true)]
15 | [Watermark("Your Password")]
16 | public string? Password { get; set; }
17 |
18 | [MultilineText]
19 | public string? HelpText { get; set; } = $"This is multiline Text{Environment.NewLine}Try edit me.";
20 |
21 | public PlatformID ServerType { get; set; } = PlatformID.Unix;
22 |
23 | [ExpandableObjectDisplayMode(IsCategoryVisible = NullableBooleanType.No)]
24 | public EncryptData EncryptPolicy { get; set; } = new();
25 | }
26 |
27 | [TypeConverter(typeof(ExpandableObjectConverter))]
28 | public class EncryptData : MiniReactiveObject
29 | {
30 | public EncryptionPolicy Policy { get; set; } = EncryptionPolicy.RequireEncryption;
31 |
32 | public RSAEncryptionPaddingMode PaddingMode { get; set; } = RSAEncryptionPaddingMode.Pkcs1;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/FeatureDemos/Models/Vector3.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using PropertyModels.ComponentModel;
3 | // ReSharper disable PropertyCanBeMadeInitOnly.Global
4 |
5 | namespace Avalonia.PropertyGrid.Samples.FeatureDemos.Models
6 | {
7 | [TypeConverter(typeof(ExpandableObjectConverter))]
8 | [ExpandableObjectDisplayMode(IsCategoryVisible = NullableBooleanType.No)]
9 | public class Vector3 : MiniReactiveObject
10 | {
11 | private double _x, _y, _z;
12 |
13 | public double X
14 | {
15 | get => _x;
16 | set => this.RaiseAndSetIfChanged(ref _x, value);
17 | }
18 |
19 | public double Y
20 | {
21 | get => _y;
22 | set => this.RaiseAndSetIfChanged(ref _y, value);
23 | }
24 |
25 | public double Z
26 | {
27 | get => _z;
28 | set => this.RaiseAndSetIfChanged(ref _z, value);
29 | }
30 |
31 | public Vector3()
32 | {
33 | }
34 |
35 | public Vector3(double x, double y, double z)
36 | {
37 | X = x;
38 | Y = y;
39 | Z = z;
40 | }
41 |
42 | public override string ToString() => $"{X},{Y},{Z}";
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/FeatureDemos/Views/CountryView.axaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
23 |
24 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/FeatureDemos/Views/CountryView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls.Primitives;
2 |
3 | namespace Avalonia.PropertyGrid.Samples.FeatureDemos.Views
4 | {
5 | public class CountryView : TemplatedControl;
6 | }
7 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/FeatureDemos/Views/Vector3View.axaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
32 |
33 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/FeatureDemos/Views/Vector3View.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls.Primitives;
2 |
3 | namespace Avalonia.PropertyGrid.Samples.FeatureDemos.Views
4 | {
5 | public class Vector3View : TemplatedControl;
6 | }
7 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/PainterDemo/Models/ArrowShape.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using Avalonia.PropertyGrid.Samples.PainterDemo.ViewModel;
5 | using PropertyModels.ComponentModel;
6 | // ReSharper disable CompareOfFloatsByEqualityOperator
7 | // ReSharper disable PropertyCanBeMadeInitOnly.Global
8 |
9 | namespace Avalonia.PropertyGrid.Samples.PainterDemo.Models;
10 |
11 | [ShapeDescription(ToolMode.CreateArrow)]
12 | public class ArrowShape : ShapeGenericPolygon
13 | {
14 | private double _length = 10;
15 | private double _shaftWidth = 5;
16 | private double _headWidth = 10;
17 | private double _headHeight = 5;
18 |
19 | [Category("Transform")]
20 | [FloatPrecision(0)]
21 | public double Length
22 | {
23 | get => _length;
24 | set => SetProperty(ref _length, value);
25 | }
26 |
27 | [Category("Transform")]
28 | [FloatPrecision(0)]
29 | public double ShaftWidth
30 | {
31 | get => _shaftWidth;
32 | set => SetProperty(ref _shaftWidth, value);
33 | }
34 |
35 | [Category("Transform")]
36 | [FloatPrecision(0)]
37 | public double HeadWidth
38 | {
39 | get => _headWidth;
40 | set => SetProperty(ref _headWidth, value);
41 | }
42 |
43 | [Category("Transform")]
44 | [FloatPrecision(0)]
45 | public double HeadHeight
46 | {
47 | get => _headHeight;
48 | set => SetProperty(ref _headHeight, value);
49 | }
50 |
51 | protected override List GeneratePoints() => CalculateArrowPoints();
52 |
53 | private List CalculateArrowPoints()
54 | {
55 | var points = new List
56 | {
57 | new(0, -ShaftWidth / 2), // Start of the shaft
58 | new(Length - HeadWidth, -ShaftWidth / 2), // End of the shaft
59 | new(Length - HeadWidth, -HeadHeight / 2), // Top of the arrowhead
60 | new(Length, 0), // Tip of the arrowhead
61 | new(Length - HeadWidth, HeadHeight / 2), // Bottom of the arrowhead
62 | new(Length - HeadWidth, ShaftWidth / 2), // End of the shaft
63 | new(0, ShaftWidth / 2), // Start of the shaft
64 | new(0, -ShaftWidth / 2) // Close the shape
65 | };
66 |
67 | return points;
68 | }
69 |
70 | protected override void OnFinishCreate(Point endPoint)
71 | {
72 | try
73 | {
74 | BeginBatchUpdate();
75 |
76 | // Calculate the length of the arrow from start to end point
77 | Length = Math.Sqrt((endPoint.X - CreatingStartX) * (endPoint.X - CreatingStartX) + (endPoint.Y - CreatingStartY) * (endPoint.Y - CreatingStartY));
78 |
79 | // Set default values for head and shaft dimensions
80 | HeadWidth = Length * 0.2;
81 | HeadHeight = Length * 0.1;
82 | ShaftWidth = Length * 0.05;
83 |
84 | // Set the arrow's position to the starting point
85 | X = CreatingStartX;
86 | Y = CreatingStartY;
87 | }
88 | finally
89 | {
90 | EndBatchUpdate();
91 | RaisePropertyChanged(nameof(Length));
92 | }
93 | }
94 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/PainterDemo/Models/EllipseShape.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using Avalonia.Controls.Shapes;
4 | using Avalonia.PropertyGrid.Samples.PainterDemo.ViewModel;
5 | using PropertyModels.ComponentModel;
6 |
7 | // ReSharper disable CompareOfFloatsByEqualityOperator
8 | // ReSharper disable PropertyCanBeMadeInitOnly.Global
9 |
10 | namespace Avalonia.PropertyGrid.Samples.PainterDemo.Models;
11 |
12 | [ShapeDescription(ToolMode.CreateEllipse)]
13 | public class EllipseShape : ShapeGeneric
14 | {
15 | private double _width;
16 | [Category("Transform")]
17 | [FloatPrecision(0)]
18 | public double Width
19 | {
20 | get => _width;
21 | set => SetProperty(ref _width, value);
22 | }
23 |
24 | private double _height;
25 | [Category("Transform")]
26 | [FloatPrecision(0)]
27 | public double Height
28 | {
29 | get => _height;
30 | set => SetProperty(ref _height, value);
31 | }
32 |
33 | protected override void ApplyProperties(Ellipse shape)
34 | {
35 | shape.Width = Width;
36 | shape.Height = Height;
37 | }
38 |
39 | protected override void OnFinishCreate(Point endPoint)
40 | {
41 | try
42 | {
43 | BeginBatchUpdate();
44 |
45 | X = Math.Min(endPoint.X, CreatingStartX);
46 | Y = Math.Min(endPoint.Y, CreatingStartY);
47 |
48 | _width = Math.Abs(endPoint.X - CreatingStartX);
49 | _height = Math.Abs(endPoint.Y - CreatingStartY);
50 | }
51 | finally
52 | {
53 | EndBatchUpdate();
54 | RaisePropertyChanged(nameof(Width));
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/PainterDemo/Models/FreehandShape.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using Avalonia.Collections;
3 | using Avalonia.Controls.Shapes;
4 | using Avalonia.PropertyGrid.Samples.PainterDemo.ViewModel;
5 |
6 | namespace Avalonia.PropertyGrid.Samples.PainterDemo.Models;
7 |
8 | [ShapeDescription(ToolMode.Brush)]
9 | public class FreehandShape : ShapeGeneric
10 | {
11 | private BindingList _points = [];
12 |
13 | [Category("Geometry")]
14 | [Browsable(false)]
15 | public BindingList Points
16 | {
17 | get => _points;
18 | set => SetProperty(ref _points, value);
19 | }
20 |
21 | public FreehandShape()
22 | {
23 | FillMode = ShapeFillMode.Blank;
24 | }
25 |
26 | protected override void ApplyProperties(Polyline shape)
27 | {
28 | shape.Points = new AvaloniaList(_points);
29 | }
30 |
31 | protected override void OnFinishCreate(Point endPoint)
32 | {
33 | Points.Add(endPoint - new Point(CreatingStartX, CreatingStartY));
34 | RaisePropertyChanged(nameof(Points));
35 | }
36 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/PainterDemo/Models/LineShape.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using Avalonia.Controls.Shapes;
3 | using Avalonia.PropertyGrid.Samples.PainterDemo.ViewModel;
4 | using PropertyModels.ComponentModel;
5 | // ReSharper disable CompareOfFloatsByEqualityOperator
6 | // ReSharper disable PropertyCanBeMadeInitOnly.Global
7 |
8 | namespace Avalonia.PropertyGrid.Samples.PainterDemo.Models;
9 |
10 | [ShapeDescription(ToolMode.CreateLine)]
11 | public class LineShape : ShapeGeneric
12 | {
13 | private double _x2;
14 | private double _y2;
15 |
16 | [Category("Transform")]
17 | [FloatPrecision(0)]
18 | public double X2
19 | {
20 | get => _x2;
21 | set => SetProperty(ref _x2, value);
22 | }
23 |
24 | [Category("Transform")]
25 | [FloatPrecision(0)]
26 | public double Y2
27 | {
28 | get => _y2;
29 | set => SetProperty(ref _y2, value);
30 | }
31 |
32 | public LineShape()
33 | {
34 | IsFillModeVisible = false;
35 | }
36 |
37 | protected override void ApplyProperties(Line shape)
38 | {
39 | shape.StartPoint = new Point(0, 0);
40 | shape.EndPoint = new Point(X2, Y2);
41 | }
42 |
43 | protected override void OnFinishCreate(Point endPoint)
44 | {
45 | X2 = endPoint.X - CreatingStartX;
46 | Y2 = endPoint.Y - CreatingStartY;
47 | }
48 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/PainterDemo/Models/RectangleShape.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using Avalonia.Controls.Shapes;
4 | using Avalonia.PropertyGrid.Samples.PainterDemo.ViewModel;
5 | using PropertyModels.ComponentModel;
6 |
7 | // ReSharper disable CompareOfFloatsByEqualityOperator
8 | // ReSharper disable PropertyCanBeMadeInitOnly.Global
9 |
10 | namespace Avalonia.PropertyGrid.Samples.PainterDemo.Models;
11 |
12 | [ShapeDescription(ToolMode.CreateRectangle)]
13 | public class RectangleShape : ShapeGeneric
14 | {
15 | private double _width;
16 | [Category("Transform")]
17 | [FloatPrecision(0)]
18 | public double Width
19 | {
20 | get => _width;
21 | set => SetProperty(ref _width, value);
22 | }
23 |
24 | private double _height;
25 | [Category("Transform")]
26 | [FloatPrecision(0)]
27 | public double Height
28 | {
29 | get => _height;
30 | set => SetProperty(ref _height, value);
31 | }
32 |
33 | protected override void ApplyProperties(Rectangle shape)
34 | {
35 | shape.Width = Width;
36 | shape.Height = Height;
37 | }
38 |
39 | protected override void OnFinishCreate(Point endPoint)
40 | {
41 | try
42 | {
43 | BeginBatchUpdate();
44 |
45 | X = Math.Min(endPoint.X, CreatingStartX);
46 | Y = Math.Min(endPoint.Y, CreatingStartY);
47 |
48 | Width = Math.Abs(endPoint.X - CreatingStartX);
49 | Height = Math.Abs(endPoint.Y - CreatingStartY);
50 | }
51 | finally
52 | {
53 | EndBatchUpdate();
54 | RaisePropertyChanged(nameof(Width));
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/PainterDemo/Models/StarShape.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using Avalonia.PropertyGrid.Samples.PainterDemo.ViewModel;
5 | using PropertyModels.ComponentModel;
6 | // ReSharper disable CompareOfFloatsByEqualityOperator
7 | // ReSharper disable PropertyCanBeMadeInitOnly.Global
8 |
9 | namespace Avalonia.PropertyGrid.Samples.PainterDemo.Models;
10 |
11 | [ShapeDescription(ToolMode.CreateStar)]
12 | public class StarShape : ShapeGenericPolygon
13 | {
14 | private double _radius;
15 |
16 | [Category("Transform")]
17 | [FloatPrecision(0)]
18 | public double Radius
19 | {
20 | get => _radius;
21 | set => SetProperty(ref _radius, value);
22 | }
23 |
24 | protected override List GeneratePoints() => CalculateStarPoints(0, 0, Radius);
25 |
26 | private static List CalculateStarPoints(double centerX, double centerY, double outerRadius)
27 | {
28 | var points = new List();
29 | const int numPoints = 5;
30 | var innerRadius = outerRadius * 0.5; // Inner radius for the star
31 |
32 | for (var i = 0; i < numPoints * 2; i++)
33 | {
34 | var angle = Math.PI / numPoints * i;
35 | var radius = (i % 2 == 0) ? outerRadius : innerRadius;
36 | points.Add(new Point(centerX + radius * Math.Cos(angle), centerY + radius * Math.Sin(angle)));
37 | }
38 |
39 | return points;
40 | }
41 |
42 | protected override void OnFinishCreate(Point endPoint)
43 | {
44 | try
45 | {
46 | BeginBatchUpdate();
47 |
48 | Radius = Math.Sqrt((endPoint.X - X) * (endPoint.X - X) + (endPoint.Y - Y) * (endPoint.Y - Y));
49 | }
50 | finally
51 | {
52 | EndBatchUpdate();
53 | RaisePropertyChanged(nameof(Radius));
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/PainterDemo/Views/GradientStopView.axaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
23 |
24 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/PainterDemo/Views/GradientStopView.axaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia.Controls;
3 | using Avalonia.Controls.Primitives;
4 | using Avalonia.Media;
5 | using Avalonia.PropertyGrid.Controls;
6 | using Avalonia.PropertyGrid.Controls.Factories;
7 |
8 | namespace Avalonia.PropertyGrid.Samples.PainterDemo.Views;
9 |
10 | public class GradientStopView : TemplatedControl
11 | {
12 | public EventHandler? GradientStopChanged;
13 |
14 | protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
15 | {
16 | if (change.Property == DataContextProperty)
17 | {
18 | if (change.OldValue is GradientStop oldValue)
19 | oldValue.PropertyChanged -= OnGradientStopValuePropertyChanged;
20 |
21 | if (change.NewValue is GradientStop newValue)
22 | newValue.PropertyChanged += OnGradientStopValuePropertyChanged;
23 | }
24 |
25 | base.OnPropertyChanged(change);
26 | }
27 |
28 | private void OnGradientStopValuePropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) =>
29 | GradientStopChanged?.Invoke(sender, e);
30 | }
31 |
32 | internal class GradientStopCellEditFactory : AbstractCellEditFactory
33 | {
34 | public override Control? HandleNewProperty(PropertyCellContext context)
35 | {
36 | if (context.Property.PropertyType != typeof(GradientStop)) return null;
37 |
38 | var value = (context.GetValue() as GradientStop)!;
39 |
40 | var control = new GradientStopView
41 | {
42 | DataContext = new GradientStop(value.Color, value.Offset) // make a copy
43 | };
44 |
45 | control.GradientStopChanged += (s, e) =>
46 | {
47 | var currentValue = (control.DataContext as GradientStop)!;
48 |
49 | // make a copy, so it will save the changed command in command queue...
50 | SetAndRaise(context, control, new GradientStop(currentValue.Color, currentValue.Offset));
51 | };
52 |
53 | return control;
54 | }
55 |
56 |
57 | public override bool HandlePropertyChanged(PropertyCellContext context)
58 | {
59 | if (context.Property.PropertyType != typeof(GradientStop)) return false;
60 |
61 | if (context.CellEdit is GradientStopView control)
62 | {
63 | var value = (context.GetValue() as GradientStop)!;
64 | control.DataContext = new GradientStop(value.Color, value.Offset);
65 | return true;
66 | }
67 |
68 | return false;
69 | }
70 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/Models/AboutSettings.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using PropertyModels.ComponentModel;
3 | using PropertyModels.ComponentModel.DataAnnotations;
4 |
5 | namespace Avalonia.PropertyGrid.Samples.SettingsDemo.Models;
6 |
7 | public class AboutSettings : ReactiveObject
8 | {
9 | [Category("System Info")]
10 | [DisplayName("OS Version")]
11 | [ReadOnly(true)]
12 | #pragma warning disable CA1822
13 | public string OsVersion => "Windows 10 Build 19044";
14 | #pragma warning restore CA1822
15 |
16 | [Category("System Info")]
17 | [DisplayName("Manufacturer")]
18 | [ReadOnly(true)]
19 | #pragma warning disable CA1822
20 | public string Manufacturer => "Contoso Electronics";
21 | #pragma warning restore CA1822
22 |
23 | [Category("License")]
24 | [DisplayName("Activation Status")]
25 | [Description("Check license status online")]
26 | [PathBrowsable(Filters = "Web Link|*.url")]
27 | public string LicenseUrl { get; set; } = "https://contoso.com/activation";
28 |
29 | [Category("Support")]
30 | [DisplayName("Technical Support")]
31 | [PathBrowsable(Filters = "Web Link|*.url")]
32 | public string SupportUrl { get; set; } = "https://support.contoso.com";
33 |
34 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/Models/AccountSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using PropertyModels.ComponentModel;
4 |
5 | namespace Avalonia.PropertyGrid.Samples.SettingsDemo.Models;
6 |
7 | public class AccountSettings : ReactiveObject
8 | {
9 | [Category("Credentials")]
10 | [DisplayName("Username")]
11 | [ReadOnly(true)]
12 | public string Username { get; set; } = "Admin";
13 |
14 | [Category("Credentials")]
15 | [DisplayName("Password")]
16 | [PasswordPropertyText(true)]
17 | public string Password { get; set; } = "********";
18 |
19 | [Category("Security")]
20 | [DisplayName("2FA Enabled")]
21 | public bool TwoFactorEnabled { get; set; }
22 |
23 | [Category("Security")]
24 | [DisplayName("Last Login")]
25 | public DateTime LastLogin { get; set; } = DateTime.Now.AddDays(-2);
26 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/Models/AppearanceSettings.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.ComponentModel.DataAnnotations;
3 | using Avalonia.Media;
4 | using PropertyModels.ComponentModel;
5 | using PropertyModels.ComponentModel.DataAnnotations;
6 |
7 | namespace Avalonia.PropertyGrid.Samples.SettingsDemo.Models;
8 |
9 | public class AppearanceSettings : ReactiveObject
10 | {
11 | [Category("Theme")]
12 | [DisplayName("Accent Color")]
13 | public Color AccentColor { get; set; } = Colors.Blue;
14 |
15 | [Category("Theme")]
16 | [DisplayName("Dark Mode")]
17 | [ConditionTarget]
18 | // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
19 | public bool UseDarkTheme { get; set; } = true;
20 |
21 | [Category("Theme")]
22 | [Range(0.3f, 1.0f)]
23 | [Trackable(0.3f,1.0f)]
24 | public float Transparency { get; set; } = 1.0f;
25 |
26 | [Category("Fonts")]
27 | [DisplayName("Custom Font")]
28 | [ConditionTarget]
29 | public bool UseCustomFont { get; set; } = false;
30 |
31 | [Category("Fonts")]
32 | [DisplayName("System Font")]
33 | [PropertyVisibilityCondition(nameof(UseCustomFont), true)]
34 | public FontFamily SystemFont { get; set; } = FontFamily.Default;
35 |
36 | [Category("Effects")]
37 | [DisplayName("Transparency Effects")]
38 | [DependsOnProperty(nameof(UseDarkTheme))]
39 | public bool EnableTransparencyEffects => UseDarkTheme;
40 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/Models/FirewallSettings.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.ComponentModel.DataAnnotations;
3 | using PropertyModels.Collections;
4 | using PropertyModels.ComponentModel;
5 | using PropertyModels.ComponentModel.DataAnnotations;
6 |
7 | namespace Avalonia.PropertyGrid.Samples.SettingsDemo.Models;
8 |
9 | public class FirewallSettings : ReactiveObject
10 | {
11 | [Category("General")]
12 | [DisplayName("Firewall Status")]
13 | public bool IsEnabled { get; set; } = true;
14 |
15 | [Category("Notifications")]
16 | [DisplayName("Block Notifications")]
17 | public bool BlockAllNotifications { get; set; }
18 |
19 | [Category("Rules")]
20 | [DisplayName("Allowed Ports")]
21 | public CheckedList AllowedPorts { get; set; } = new( [80, 443] );
22 |
23 | [Category("Rules")]
24 | [DisplayName("Custom Port Range")]
25 | [Range(1, 65535)]
26 | public int CustomPortStart { get; set; } = 8000;
27 |
28 | [Range(1, 65535)]
29 | public int CustomPortEnd { get; set; } = 9000;
30 |
31 | [Category("Advanced")]
32 | [DisplayName("Allowed IPs")]
33 | [Description("CIDR format (e.g. 192.168.1.0/24)")]
34 | [CIDRValidation]
35 | public BindingList AllowedIPs { get; set; } = ["192.168.1.0/24"];
36 |
37 | [Category("Logging")]
38 | [DisplayName("Enable Logging")]
39 | public bool EnableLogging { get; set; } = true;
40 |
41 | [Category("Logging")]
42 | [DisplayName("Log Retention (days)")]
43 | [Range(1, 365)]
44 | [PropertyVisibilityCondition(nameof(EnableLogging), true)]
45 | public int LogRetentionDays { get; set; } = 30;
46 | }
47 |
48 | // ReSharper disable once InconsistentNaming
49 | public class CIDRValidationAttribute : ValidationAttribute
50 | {
51 | protected override ValidationResult? IsValid(object? value, ValidationContext context)
52 | {
53 | if (value is string cidr)
54 | {
55 | #pragma warning disable SYSLIB1045
56 | if (!System.Text.RegularExpressions.Regex.IsMatch(cidr, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}$"))
57 | #pragma warning restore SYSLIB1045
58 | {
59 | return new ValidationResult("Invalid CIDR format");
60 | }
61 | }
62 | return ValidationResult.Success;
63 | }
64 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/Models/GeneralSettings.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.ComponentModel.DataAnnotations;
3 | using PropertyModels.Collections;
4 | using PropertyModels.ComponentModel;
5 |
6 | namespace Avalonia.PropertyGrid.Samples.SettingsDemo.Models;
7 |
8 | public class GeneralSettings : ReactiveObject
9 | {
10 | [Category("Update")]
11 | [DisplayName("Auto Update")]
12 | [Description("Enable automatic system updates")]
13 | public bool EnableAutoUpdate { get; set; } = true;
14 |
15 | [Category("Update")]
16 | [DisplayName("Update Interval")]
17 | [Range(1, 30)]
18 | public int UpdateCheckIntervalDays { get; set; } = 7;
19 |
20 | [Category("Region")]
21 | [DisplayName("Time Zone")]
22 | public SelectableList TimeZone { get; set; } = new (["UTC", "UTC+08:00", "UTC-05:00", "UTC+01:00"], "UTC+08:00");
23 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/Models/ThemeSettings.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.ComponentModel.DataAnnotations;
3 | using Avalonia.Media;
4 | using PropertyModels.Collections;
5 | using PropertyModels.ComponentModel;
6 | using PropertyModels.ComponentModel.DataAnnotations;
7 |
8 | namespace Avalonia.PropertyGrid.Samples.SettingsDemo.Models;
9 |
10 | public class ThemeSettings : ReactiveObject
11 | {
12 | [Category("Color Scheme")]
13 | [DisplayName("Primary Color")]
14 | public Color PrimaryColor { get; set; } = Color.FromRgb(0, 120, 215);
15 |
16 | [Category("Color Scheme")]
17 | [DisplayName("Secondary Color")]
18 | public Color SecondaryColor { get; set; } = Color.FromRgb(153, 235, 255);
19 |
20 | [Category("Appearance")]
21 | [DisplayName("Theme Mode")]
22 | [SingleSelectionMode(SingleSelectionMode.ToggleButtonGroup)]
23 | public SelectableList ThemeMode { get; set; } = new (["Auto", "Light", "Dark"], "Auto");
24 |
25 | [Category("Advanced")]
26 | [DisplayName("Custom Font")]
27 | [PropertyVisibilityCondition(nameof(UseCustomFont), true)]
28 | public FontFamily CustomFont { get; set; } = FontFamily.Default;
29 |
30 | [Category("Advanced")]
31 | [DisplayName("Enable Custom Font")]
32 | public bool UseCustomFont { get; set; }
33 |
34 | [Category("Effects")]
35 | [DisplayName("Transparency Level")]
36 | [Range(0.3, 1.0)]
37 | [FloatPrecision(2)]
38 | [Trackable(0.3, 1)]
39 | public double Transparency { get; set; } = 0.8;
40 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/ViewModels/SettingsViewModel.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Collections;
2 | using Avalonia.PropertyGrid.Samples.SettingsDemo.Models;
3 | using Avalonia.PropertyGrid.Services;
4 | using PropertyModels.ComponentModel;
5 |
6 | namespace Avalonia.PropertyGrid.Samples.SettingsDemo.ViewModels;
7 |
8 | public class SettingsViewModel : ReactiveObject
9 | {
10 | public AvaloniaList FlatCategories { get; } = [];
11 |
12 | public SettingsViewModel()
13 | {
14 | InitializeCategories();
15 |
16 | LocalizationService.Default.OnCultureChanged += (sender, args) =>
17 | {
18 | foreach (var category in FlatCategories)
19 | {
20 | category.Translate();
21 | }
22 | };
23 | }
24 |
25 | private void InitializeCategories()
26 | {
27 | var categories = new[]
28 | {
29 | CreateCategory("General", new GeneralSettings()),
30 | CreateCategory("AppearanceSettings", new AppearanceSettings()),
31 | CreateCategory("Themes", new ThemeSettings()),
32 | CreateCategory("Accounts", new AccountSettings()),
33 | CreateCategory("Firewall", new FirewallSettings()),
34 | CreateCategory("About", new AboutSettings())
35 | };
36 |
37 | FlatCategories.AddRange(categories);
38 | }
39 |
40 | private static FlatSettingCategory CreateCategory(string title, object settings)
41 | {
42 | return new FlatSettingCategory(title, settings);
43 | }
44 | }
45 |
46 | public class FlatSettingCategory : ReactiveObject
47 | {
48 | public string Key { get; }
49 | public string Title { get; private set; }
50 | // ReSharper disable once UnusedAutoPropertyAccessor.Global
51 | public object Settings { get; }
52 |
53 | public FlatSettingCategory(string key, object settings)
54 | {
55 | Key = key;
56 | Title = LocalizationService.Default[key];
57 | Settings = settings;
58 | }
59 |
60 | public void Translate()
61 | {
62 | Title = LocalizationService.Default[Key];
63 | RaisePropertyChanged(nameof(Title));
64 | }
65 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/Views/SettingsView.axaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/SettingsDemo/Views/SettingsView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using Avalonia.PropertyGrid.Samples.SettingsDemo.ViewModels;
3 |
4 | namespace Avalonia.PropertyGrid.Samples.SettingsDemo.Views;
5 |
6 | public partial class SettingsView : UserControl
7 | {
8 | public SettingsView()
9 | {
10 | InitializeComponent();
11 |
12 | DataContext = new SettingsViewModel();
13 | }
14 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Views/MainView.axaml.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Avalonia.Controls;
3 | using Avalonia.PropertyGrid.Services;
4 | using Avalonia.Reactive;
5 | using Avalonia.Styling;
6 | using PropertyModels.Localization;
7 |
8 | namespace Avalonia.PropertyGrid.Samples.Views;
9 |
10 | public partial class MainView : UserControl
11 | {
12 | private readonly List _allCultures = [];
13 |
14 | public ICultureData[] AllCultures => [.. _allCultures];
15 |
16 | public static readonly StyledProperty CurrentCultureProperty =
17 | AvaloniaProperty.Register(
18 | nameof(CurrentCulture),
19 | defaultValue: LocalizationService.Default.CultureData);
20 |
21 | public ICultureData CurrentCulture
22 | {
23 | get => GetValue(CurrentCultureProperty);
24 | set => SetValue(CurrentCultureProperty, value);
25 | }
26 |
27 | public static string Version => $"v{typeof(Utils.FontUtils).Assembly.GetName().Version?.ToString() ?? "Unknown Version"}";
28 |
29 | public MainView()
30 | {
31 | LocalizationService.Default.AddExtraService(new SampleLocalizationService());
32 | _allCultures.AddRange(LocalizationService.Default.GetCultures());
33 |
34 | InitializeComponent();
35 |
36 | this.GetObservable(CurrentCultureProperty).Subscribe(new AnonymousObserver(OnCurrentCultureChanged));
37 |
38 |
39 | ThemeBox.SelectedItem = App.CurrentTheme;
40 | ThemeBox.SelectionChanged += (sender, e) =>
41 | {
42 | if (ThemeBox.SelectedItem is ThemeType theme)
43 | {
44 | App.SetThemes(theme);
45 | }
46 | };
47 |
48 | ThemeVariantsBox.SelectionChanged += (sender, e) =>
49 | {
50 | if (ThemeVariantsBox.SelectedItem is ThemeVariant themeVariant)
51 | {
52 | Application.Current!.RequestedThemeVariant = themeVariant;
53 | }
54 | };
55 | }
56 |
57 | private static void OnCurrentCultureChanged(ICultureData? newCulture)
58 | {
59 | if (newCulture != null)
60 | {
61 | LocalizationService.Default.SelectCulture(newCulture.Culture.Name);
62 | }
63 | }
64 | }
65 |
66 | public enum ThemeType
67 | {
68 | Fluent,
69 | Simple
70 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Views/MainWindow.axaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Views/MainWindow.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace Avalonia.PropertyGrid.Samples.Views;
4 |
5 | public partial class MainWindow : Window
6 | {
7 | public MainWindow() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/Samples/Avalonia.PropertyGrid.Samples/Views/SampleLocalizationService.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.PropertyGrid.Localization;
2 |
3 | namespace Avalonia.PropertyGrid.Samples.Views
4 | {
5 | internal class SampleLocalizationService : AssemblyJsonAssetLocalizationService
6 | {
7 | public SampleLocalizationService()
8 | : base(typeof(SampleLocalizationService).Assembly)
9 | {
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Samples/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Assets/Images/add.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:c79c171aaee0b40515e2c4da832bd3824ed692a464d42efa1b0b31ca7b147858
3 | size 305
4 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Assets/Images/clear.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:045039873317026be896f22ead78ffcb763e024c23c6c2750d039035cf5e954c
3 | size 1199
4 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Assets/Images/delete.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:fe96c65c3590bf9f5c98ca25c213d9f8c7da0957a32050d5eaba029beb5b687e
3 | size 487
4 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Assets/Images/new.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:b5133133421da495342abfded901c86eed96e1b9af328e8c01fd1034c875e675
3 | size 682
4 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Assets/Images/options.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:87791061d56c5779881aa8c96e870500de9303fa3375de50a47584765cece23b
3 | size 791
4 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Assets/Localizations/en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "ShowGroup": "Show Category",
3 | "ShowStyle": "Show Style",
4 | "IsCategoryView": "Is Category View",
5 | "AllowQuickFilter": "Allow Quick Filter",
6 | "IgnoreCase": "Ignore Case",
7 | "UseRegex": "Use Regex",
8 | "DisplayMode": "Display Mode",
9 | "ShowTitle": "Show Title",
10 | "CategoryOrder": "Category Order",
11 | "PropertyOrder": "Property Order",
12 | "ExpandAll": "Expand All",
13 | "CollapseAll": "Collapse All",
14 | "InsertNewElement": "Insert a new element before this element",
15 | "RemoveElement": "Remove this element",
16 | "AppendNewElement": "Append a new element",
17 | "ClearAllElements": "Clear this list",
18 | "MainOptionSettingsTooltip": "Choose your display mode and use some shortcuts"
19 | }
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Assets/Localizations/ru-RU.json:
--------------------------------------------------------------------------------
1 | {
2 | "ShowGroup": "Показывать категорию",
3 | "ShowStyle": "Стиль отображения",
4 | "IgnoreCase": "Игнорировать регистр",
5 | "UseRegex": "Использовать Regex",
6 | "Search": "Поиск",
7 | "All": "Все",
8 | "Name": "Название",
9 | "Properties": "Свойства",
10 | "Misc": "Разное",
11 | "{0} Elements": "{0} элементов",
12 | "InsertNewElement": "Вставить элемент перед этим элементом",
13 | "RemoveElement": "Удалить элемент",
14 | "AppendNewElement": "Добавить новый элемент",
15 | "ClearAllElements": "Очистить список",
16 | "Please select some folders": "Пожалуйста, выберите папки",
17 | "Please select a folder": "Пожалуйста, выберите папку",
18 | "Please select some files": "Пожалуйста, выберите файлы",
19 | "Please select a file": "Пожалуйста, выберите файл",
20 | "Remove array element at {0}": "Удалить элемент массива в {0}",
21 | "Clear all elements of the array": "Очистить все элементы массива",
22 | "Insert a new element at {0}": "Вставить новый элемент в {0}",
23 | "Insert a new element at the end of the array": "Вставить новый элемент в конец массива",
24 | "Change {0} form {1} to {2}": "Изменить {0} с {1} на {2}",
25 | "Change {0} selection from {1} to {2}": "Изменить выбор {0} с {1} на {2}",
26 | "ReadOnly": "Только чтение",
27 | "Readonly": "Только чтение"
28 | }
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Assets/Localizations/zh-CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "ShowGroup": "显示分类",
3 | "ShowStyle": "显示风格",
4 | "IsCategoryView": "分类视图",
5 | "AllowQuickFilter": "允许快速过滤",
6 | "IgnoreCase": "忽略大小写",
7 | "UseRegex": "使用正则表达式",
8 | "Search": "搜索",
9 | "DisplayMode": "显示模式",
10 | "Tree": "树形",
11 | "Inline": "内联",
12 | "CategoryOrder": "分类排序",
13 | "PropertyOrder": "属性排序",
14 | "Builtin": "内置",
15 | "Alphabetic": "字母顺序",
16 | "ShowTitle": "显示标题",
17 | "ExpandAll": "全部展开",
18 | "CollapseAll": "全部折叠",
19 | "All": "所有",
20 | "Name": "名称",
21 | "Properties": "属性",
22 | "Misc": "杂项",
23 | "{0} Elements": "{0}个数据",
24 | "InsertNewElement": "在当前元素前新增一个元素",
25 | "RemoveElement": "删除当前元素",
26 | "AppendNewElement": "在尾部增加一个新元素",
27 | "ClearAllElements": "清空整个列表",
28 | "Please select some folders": "请选择文件夹",
29 | "Please select a folder": "请选择一个文件夹",
30 | "Please select some files": "请选择一些文件",
31 | "Please select a file": "请选择一个文件",
32 | "Remove array element at {0}": "从数组{0}处移除一个元素",
33 | "Clear all elements of the array": "清空数组",
34 | "Insert a new element at {0}": "在数组{0}处插入一个新的元素",
35 | "Insert a new element at the end of the array": "在数组尾部新增一个新的元素",
36 | "Change {0} form {1} to {2}": "将属性[{0}]从<{1}>修改为<{2}>",
37 | "Change {0} selection from {1} to {2}": "属性[{0}]选择项从<{1}>变更为<{2}>",
38 | "ReadOnly": "只读",
39 | "Readonly": "只读",
40 | "MainOptionSettingsTooltip": "选择你的显示模式和使用一些快捷功能"
41 | }
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Avalonia.PropertyGrid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1;net6.0;net8.0;net9.0
5 | preview
6 | True
7 | bodong.Avalonia.PropertyGrid
8 | 11.3.0.22
9 | bodong
10 | enable
11 | A PropertyGrid control implementation for Avalonia
12 | https://github.com/bodong1987/Avalonia.PropertyGrid
13 | https://github.com/bodong1987/Avalonia.PropertyGrid.git
14 | git
15 | Avalonia;PropertyGrid;AvaloniaControls;AvaloniaSamples
16 | False
17 | Debug;Release;Development
18 |
19 |
20 |
21 | DEBUG;TRACE
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | True
44 | \
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | BindiListElementPlaceholderEdit.axaml
63 |
64 |
65 |
66 |
67 | bodong.Avalonia.PropertyGrid
68 | bodong.Avalonia.PropertyGrid
69 | MIT
70 | False
71 | README_NUGET.md
72 | True
73 | enable
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/ButtonEdit.axaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
38 |
39 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/CheckedListEdit.axaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
32 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/CheckedMask.axaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/Factories/Builtins/BooleanCellEditFactory.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using Avalonia.Controls;
3 | using PropertyModels.ComponentModel;
4 |
5 | namespace Avalonia.PropertyGrid.Controls.Factories.Builtins
6 | {
7 | ///
8 | /// Class BooleanCellEditFactory.
9 | /// Implements the
10 | ///
11 | ///
12 | public class BooleanCellEditFactory : AbstractCellEditFactory
13 | {
14 | ///
15 | /// Gets the import priority.
16 | /// The larger the value, the earlier the object will be processed
17 | ///
18 | /// The import priority.
19 | public override int ImportPriority => base.ImportPriority - 100000;
20 |
21 | ///
22 | /// Handles the new property.
23 | ///
24 | /// The context.
25 | /// Control.
26 | public override Control? HandleNewProperty(PropertyCellContext context)
27 | {
28 | var propertyDescriptor = context.Property;
29 |
30 | if (propertyDescriptor.PropertyType != typeof(bool) && propertyDescriptor.PropertyType != typeof(bool?))
31 | {
32 | return null;
33 | }
34 |
35 | var control = new CheckBox
36 | {
37 | IsThreeState = propertyDescriptor.PropertyType == typeof(bool?) || propertyDescriptor is MultiObjectPropertyDescriptor
38 | };
39 |
40 | control.IsCheckedChanged += (s, e) =>
41 | {
42 | SetAndRaise(context, control, control.IsChecked);
43 | };
44 |
45 | return control;
46 | }
47 |
48 | ///
49 | /// Handles the property changed.
50 | ///
51 | /// The context.
52 | /// true if success, false otherwise.
53 | public override bool HandlePropertyChanged(PropertyCellContext context)
54 | {
55 | var propertyDescriptor = context.Property;
56 | var target = context.Target;
57 | var control = context.CellEdit;
58 |
59 | if (propertyDescriptor.PropertyType != typeof(bool) && propertyDescriptor.PropertyType != typeof(bool?))
60 | {
61 | return false;
62 | }
63 |
64 | Debug.Assert(control != null);
65 |
66 | ValidateProperty(control, propertyDescriptor, target);
67 |
68 | if (control is CheckBox ts)
69 | {
70 | if (ts.IsThreeState)
71 | {
72 | var obj = propertyDescriptor.GetValue(target);
73 |
74 | if (obj != null)
75 | {
76 | ts.IsChecked = (bool)obj;
77 | }
78 | else
79 | {
80 | ts.IsChecked = null;
81 | }
82 | }
83 | else
84 | {
85 | ts.IsChecked = (bool)propertyDescriptor.GetValue(target)!;
86 | }
87 |
88 | return true;
89 | }
90 |
91 | return false;
92 | }
93 | }
94 | }
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/Factories/Builtins/FontFamilyCellEditFactory.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Avalonia.Controls;
3 | using Avalonia.Controls.Templates;
4 | using Avalonia.Data;
5 | using Avalonia.Layout;
6 | using Avalonia.Media;
7 |
8 | namespace Avalonia.PropertyGrid.Controls.Factories.Builtins
9 | {
10 | ///
11 | /// Class FontFamilyCellEditFactory.
12 | /// Implements the
13 | ///
14 | ///
15 | public class FontFamilyCellEditFactory : AbstractCellEditFactory
16 | {
17 | ///
18 | /// Gets the import priority.
19 | /// The larger the value, the earlier the object will be processed
20 | ///
21 | /// The import priority.
22 | public override int ImportPriority => base.ImportPriority - 1000000;
23 |
24 | ///
25 | /// Handles the new property.
26 | ///
27 | /// The context.
28 | /// Control.
29 | public override Control? HandleNewProperty(PropertyCellContext context)
30 | {
31 | var propertyDescriptor = context.Property;
32 | var target = context.Target;
33 |
34 | if (propertyDescriptor.PropertyType != typeof(FontFamily))
35 | {
36 | return null;
37 | }
38 |
39 | var control = new ComboBox
40 | {
41 | ItemsSource = FontManager.Current.SystemFonts.ToArray(),
42 | HorizontalAlignment = HorizontalAlignment.Stretch,
43 | ItemTemplate = new FuncDataTemplate((value, nameScope) =>
44 | new TextBlock
45 | {
46 | [!TextBlock.TextProperty] = new Binding("Name"),
47 | [!TextBlock.FontFamilyProperty] = new Binding()
48 | }
49 | )
50 | };
51 |
52 | control.SelectionChanged += (s, e) =>
53 | {
54 | var item = control.SelectedItem;
55 |
56 | if (item is FontFamily ff)
57 | {
58 | if (ff != (propertyDescriptor.GetValue(target) as FontFamily))
59 | {
60 | SetAndRaise(context, control, ff);
61 | }
62 | }
63 | };
64 |
65 | return control;
66 | }
67 |
68 | ///
69 | /// Handles the property changed.
70 | ///
71 | /// The context.
72 | /// true if success, false otherwise.
73 | public override bool HandlePropertyChanged(PropertyCellContext context)
74 | {
75 | var propertyDescriptor = context.Property;
76 | var target = context.Target;
77 | var control = context.CellEdit!;
78 |
79 | if (propertyDescriptor.PropertyType != typeof(FontFamily))
80 | {
81 | return false;
82 | }
83 |
84 | ValidateProperty(control, propertyDescriptor, target);
85 |
86 | if (control is ComboBox cb)
87 | {
88 | var value = propertyDescriptor.GetValue(target) as FontFamily;
89 | cb.SelectedItem = value;
90 | return true;
91 | }
92 |
93 | return false;
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/Factories/Builtins/ImageCellEditFactory.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using Avalonia.Layout;
3 | using Avalonia.Media;
4 | using PropertyModels.ComponentModel;
5 | using PropertyModels.ComponentModel.DataAnnotations;
6 | using PropertyModels.Extensions;
7 |
8 | namespace Avalonia.PropertyGrid.Controls.Factories.Builtins
9 | {
10 | ///
11 | /// Class ImageCellEditFactory.
12 | /// Implements the
13 | ///
14 | ///
15 | public class ImageCellEditFactory : AbstractCellEditFactory
16 | {
17 | ///
18 | /// Gets the import priority.
19 | /// The larger the value, the earlier the object will be processed
20 | ///
21 | /// The import priority.
22 | public override int ImportPriority => base.ImportPriority - 1000000;
23 |
24 | ///
25 | /// Handles the new property.
26 | ///
27 | /// The context.
28 | /// Control.
29 | public override Control? HandleNewProperty(PropertyCellContext context)
30 | {
31 | var propertyDescriptor = context.Property;
32 | // var target = context.Target;
33 |
34 | if (propertyDescriptor is MultiObjectPropertyDescriptor)
35 | {
36 | return null;
37 | }
38 |
39 | if (propertyDescriptor.PropertyType != typeof(IImage) && !propertyDescriptor.PropertyType.IsImplementFrom())
40 | {
41 | return null;
42 | }
43 |
44 | var attr = propertyDescriptor.GetCustomAttribute();
45 |
46 | var control = new Image
47 | {
48 | VerticalAlignment = VerticalAlignment.Center,
49 | HorizontalAlignment = HorizontalAlignment.Center,
50 | Stretch = attr != null ? (Stretch)(int)attr.Stretch : Stretch.Uniform,
51 | StretchDirection = attr != null ? (StretchDirection)(int)attr.StretchDirection : StretchDirection.Both
52 | };
53 |
54 | return control;
55 | }
56 |
57 | ///
58 | /// Handles the property changed.
59 | ///
60 | /// The context.
61 | /// true if success, false otherwise.
62 | public override bool HandlePropertyChanged(PropertyCellContext context)
63 | {
64 | var propertyDescriptor = context.Property;
65 | var target = context.Target;
66 | var control = context.CellEdit!;
67 |
68 | if (propertyDescriptor.PropertyType != typeof(IImage) && !propertyDescriptor.PropertyType.IsImplementFrom())
69 | {
70 | return false;
71 | }
72 |
73 | ValidateProperty(control, propertyDescriptor, target);
74 |
75 | if (control is Image imageControl)
76 | {
77 | var imageData = propertyDescriptor.GetValue(target);
78 |
79 | if (imageData == null)
80 | {
81 | imageControl.Source = null;
82 | return false;
83 | }
84 |
85 | if (imageData is IImage iImage)
86 | {
87 | imageControl.Source = iImage;
88 | }
89 | }
90 |
91 | return false;
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/Factories/Builtins/ProgressCellEditFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia.Controls;
3 | using PropertyModels.ComponentModel;
4 | using PropertyModels.Extensions;
5 |
6 | namespace Avalonia.PropertyGrid.Controls.Factories.Builtins
7 | {
8 | ///
9 | /// Class ProgressCellEditFactory.
10 | /// Implements the
11 | ///
12 | ///
13 | public class ProgressCellEditFactory : AbstractCellEditFactory
14 | {
15 | ///
16 | /// Gets the import priority.
17 | /// The larger the value, the earlier the object will be processed
18 | ///
19 | /// The import priority.
20 | public override int ImportPriority => base.ImportPriority - 900000;
21 |
22 | ///
23 | /// Handles the new property.
24 | ///
25 | /// The context.
26 | /// Control.
27 | public override Control? HandleNewProperty(PropertyCellContext context)
28 | {
29 | var propertyDescriptor = context.Property;
30 | // var target = context.Target;
31 |
32 | if ((propertyDescriptor.PropertyType != typeof(double) && propertyDescriptor.PropertyType != typeof(float)) || !propertyDescriptor.IsDefined())
33 | {
34 | return null;
35 | }
36 |
37 | var control = new ProgressBar();
38 |
39 | var attr = propertyDescriptor.GetCustomAttribute()!;
40 | control.Minimum = attr.Minimum;
41 | control.Maximum = attr.Maximum;
42 | control.ProgressTextFormat = attr.FormatString;
43 | control.ShowProgressText = attr.ShowProgressText;
44 |
45 | return control;
46 | }
47 |
48 | ///
49 | /// Handles the property changed.
50 | ///
51 | /// The context.
52 | /// true if success, false otherwise.
53 | public override bool HandlePropertyChanged(PropertyCellContext context)
54 | {
55 | var propertyDescriptor = context.Property;
56 | var target = context.Target;
57 | var control = context.CellEdit!;
58 |
59 | if ((propertyDescriptor.PropertyType != typeof(double) && propertyDescriptor.PropertyType != typeof(float)) || !propertyDescriptor.IsDefined())
60 | {
61 | return false;
62 | }
63 |
64 | ValidateProperty(control, propertyDescriptor, target);
65 |
66 | if (control is ProgressBar progressBar)
67 | {
68 | try
69 | {
70 | var v = propertyDescriptor.GetValue(target)!;
71 |
72 | progressBar.Value = Type.GetTypeCode(v.GetType()) switch
73 | {
74 | TypeCode.Single => (float)v,
75 | TypeCode.Double => (double)v,
76 | _ => progressBar.Value
77 | };
78 | }
79 | catch (Exception ex)
80 | {
81 | DataValidationErrors.SetErrors(control, [ex.Message]);
82 | }
83 |
84 | return true;
85 | }
86 |
87 | return false;
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/Factories/Builtins/TimeCellEditFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia.Controls;
3 |
4 | namespace Avalonia.PropertyGrid.Controls.Factories.Builtins
5 | {
6 | ///
7 | /// Class TimeCellEditFactory.
8 | /// Implements the
9 | ///
10 | ///
11 | public class TimeCellEditFactory : AbstractCellEditFactory
12 | {
13 | ///
14 | /// Gets the import priority.
15 | /// The larger the value, the earlier the object will be processed
16 | ///
17 | /// The import priority.
18 | public override int ImportPriority => base.ImportPriority - 100000;
19 |
20 | ///
21 | /// Handles the new property.
22 | ///
23 | /// The context.
24 | /// Control.
25 | public override Control? HandleNewProperty(PropertyCellContext context)
26 | {
27 | var propertyDescriptor = context.Property;
28 | // var target = context.Target;
29 |
30 | var propertyType = propertyDescriptor.PropertyType;
31 |
32 | if (propertyType != typeof(TimeSpan) && propertyType != typeof(TimeSpan?))
33 | {
34 | return null;
35 | }
36 |
37 | var control = new TimePicker
38 | {
39 | ClockIdentifier = "24HourClock"
40 | };
41 |
42 | control.SelectedTimeChanged += (s, e) =>
43 | {
44 | if (propertyType == typeof(TimeSpan?))
45 | {
46 | SetAndRaise(context, control, control.SelectedTime);
47 | }
48 | else if (propertyType == typeof(TimeSpan) && control.SelectedTime is not null)
49 | {
50 | SetAndRaise(context, control, control.SelectedTime.Value);
51 | }
52 | };
53 |
54 | return control;
55 | }
56 |
57 | ///
58 | /// Handles the property changed.
59 | ///
60 | /// The context.
61 | /// true if success, false otherwise.
62 | public override bool HandlePropertyChanged(PropertyCellContext context)
63 | {
64 | var propertyDescriptor = context.Property;
65 | var target = context.Target;
66 | var control = context.CellEdit;
67 |
68 | var propertyType = propertyDescriptor.PropertyType;
69 |
70 | if (propertyType != typeof(TimeSpan) && propertyType != typeof(TimeSpan?))
71 | {
72 | return false;
73 | }
74 |
75 | if (control is TimePicker tp)
76 | {
77 | if (propertyType == typeof(TimeSpan?))
78 | {
79 | tp.SelectedTime = propertyDescriptor.GetValue(target) as TimeSpan?;
80 | }
81 | else if (propertyType == typeof(TimeSpan))
82 | {
83 | var value = propertyDescriptor.GetValue(target);
84 |
85 | if (value != null)
86 | {
87 | tp.SelectedTime = (TimeSpan)value;
88 | }
89 | }
90 |
91 | return true;
92 | }
93 |
94 | return false;
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/ICellEditFactoryCollection.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Avalonia.Controls;
3 |
4 | namespace Avalonia.PropertyGrid.Controls
5 | {
6 | ///
7 | /// Interface ICellEditFactoryCollection
8 | ///
9 | public interface ICellEditFactoryCollection
10 | {
11 | ///
12 | /// Gets the factories.
13 | ///
14 | /// The factories.
15 | IEnumerable Factories { get; }
16 |
17 | ///
18 | /// Clones the factories.
19 | ///
20 | /// The access token.
21 | /// IEnumerable<ICellEditFactory>.
22 | IEnumerable CloneFactories(object accessToken);
23 |
24 | ///
25 | /// Adds the factory.
26 | ///
27 | /// The factory.
28 | void AddFactory(ICellEditFactory factory);
29 |
30 | ///
31 | /// Removes the factory.
32 | ///
33 | /// The factory.
34 | void RemoveFactory(ICellEditFactory factory);
35 |
36 | ///
37 | /// Builds the property control.
38 | ///
39 | /// The context.
40 | /// Control.
41 | Control? BuildPropertyControl(PropertyCellContext context);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/IPropertyGridFilterContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia.PropertyGrid.ViewModels;
3 | using PropertyModels.ComponentModel;
4 |
5 | namespace Avalonia.PropertyGrid.Controls
6 | {
7 | ///
8 | /// Enum FilterCategory
9 | ///
10 | [Flags]
11 | public enum FilterCategory
12 | {
13 | ///
14 | /// The none
15 | ///
16 | None = 0,
17 | ///
18 | /// The property condition
19 | ///
20 | PropertyCondition = 1 << 0,
21 | ///
22 | /// The category
23 | ///
24 | Category = 1 << 1,
25 | ///
26 | /// The filter
27 | ///
28 | Filter = 1 << 2,
29 | ///
30 | /// The factory
31 | ///
32 | Factory = 1 << 4,
33 |
34 | ///
35 | /// The default
36 | ///
37 | Default = PropertyCondition | Category | Filter | Factory
38 | }
39 |
40 | ///
41 | /// Interface IPropertyGridFilterContext
42 | ///
43 | public interface IPropertyGridFilterContext
44 | {
45 | ///
46 | /// Gets the filter pattern.
47 | ///
48 | /// The filter pattern.
49 | IFilterPattern? FilterPattern { get; }
50 |
51 | ///
52 | /// Gets the fast filter pattern.
53 | ///
54 | /// The fast filter pattern.
55 | ICheckedMaskModel? FastFilterPattern { get; }
56 |
57 | ///
58 | /// Propagates the visibility.
59 | ///
60 | /// The information.
61 | /// The category.
62 | /// The filter text.
63 | /// Indicates whether the filter matches the parent category.
64 | /// PropertyVisibility.
65 | PropertyVisibility PropagateVisibility(
66 | IPropertyGridCellInfo cellInfo,
67 | FilterCategory category = FilterCategory.Default,
68 | string? filterText = null,
69 | bool filterMatchesParentCategory = false);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/Implements/CellEditFactoryCollection.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Avalonia.Controls;
4 | using PropertyModels.ComponentModel;
5 | using PropertyModels.Extensions;
6 |
7 | namespace Avalonia.PropertyGrid.Controls.Implements
8 | {
9 | ///
10 | /// Class CellEditFactoryCollection.
11 | /// Implements the
12 | ///
13 | ///
14 | internal class CellEditFactoryCollection : ICellEditFactoryCollection
15 | {
16 | ///
17 | /// The factories
18 | ///
19 | private readonly List _factories = [];
20 |
21 | ///
22 | /// Gets the factories.
23 | ///
24 | /// The factories.
25 | public IEnumerable Factories => [.. _factories];
26 |
27 | ///
28 | /// Initializes a new instance of the class.
29 | ///
30 | public CellEditFactoryCollection()
31 | {
32 | }
33 |
34 | ///
35 | /// Initializes a new instance of the class.
36 | ///
37 | /// The factories.
38 | public CellEditFactoryCollection(IEnumerable factories)
39 | {
40 | _factories.AddRange(factories);
41 | _factories.Sort((x, y) => Comparer.Default.Compare(y.ImportPriority, x.ImportPriority));
42 |
43 | foreach (var factory in _factories)
44 | {
45 | factory.Collection = this;
46 | }
47 | }
48 |
49 | ///
50 | /// Clones the factories.
51 | ///
52 | /// The access token.
53 | /// IEnumerable<ICellEditFactory>.
54 | public IEnumerable CloneFactories(object accessToken)
55 | => _factories
56 | .FindAll(x => x.Accept(accessToken))
57 | .Select(x => x.Clone())
58 | .Where(x => x != null)
59 | .Select(x => x!);
60 |
61 | ///
62 | /// Adds the factory.
63 | ///
64 | /// The factory.
65 | public void AddFactory(ICellEditFactory factory)
66 | {
67 | factory.Collection = this;
68 | _factories.Add(factory);
69 | _factories.Sort((x, y) => Comparer.Default.Compare(y.ImportPriority, x.ImportPriority));
70 | }
71 |
72 | ///
73 | /// Removes the factory.
74 | ///
75 | /// The factory.
76 | public void RemoveFactory(ICellEditFactory factory) => _ = _factories.Remove(factory);
77 |
78 | ///
79 | /// Builds the property control.
80 | ///
81 | /// The context.
82 | /// Control.
83 | public Control? BuildPropertyControl(PropertyCellContext context)
84 | {
85 | foreach (var factory in _factories)
86 | {
87 | var control = factory.HandleNewProperty(context);
88 |
89 | if (control != null)
90 | {
91 | var classesAttributes = context.Property.GetCustomAttributes();
92 | if (classesAttributes.Length > 0)
93 | {
94 | var classes = classesAttributes.SelectMany(a => a.Classes).Distinct();
95 | control.Classes.AddRange(classes);
96 | }
97 |
98 | context.CellEdit = control;
99 | context.Factory = factory;
100 |
101 | return control;
102 | }
103 | }
104 |
105 | return null;
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Sources/Avalonia.PropertyGrid/Controls/Implements/PropertyGridExpandableCache.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Avalonia.PropertyGrid.Controls.Implements
4 | {
5 | internal class PropertyGridExpandableCache : IExpandableObjectCache
6 | {
7 | private readonly List