├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── dependabot.yml ├── stale.yml └── workflows │ └── build.yml ├── .gitignore ├── .nuke ├── build.schema.json └── parameters.json ├── LICENSE.TXT ├── README.md ├── SECURITY.md ├── TemplatedDataGrid.sln ├── azure-pipelines.yml ├── build.cmd ├── build.ps1 ├── build.sh ├── build ├── Avalonia.Desktop.props ├── Avalonia.Diagnostics.props ├── Avalonia.Fonts.Inter.props ├── Avalonia.ReactiveUI.props ├── Avalonia.Themes.Fluent.props ├── Avalonia.props ├── Base.props ├── ReferenceAssemblies.props ├── SignAssembly.props ├── SourceLink.props ├── System.Reactive.props ├── XUnit.props ├── build │ ├── Build.cs │ └── _build.csproj └── templateddatagrid.public.snk ├── global.json ├── nuget.config ├── samples └── TemplatedDataGridDemo │ ├── App.axaml │ ├── App.axaml.cs │ ├── Assets │ └── avalonia-logo.ico │ ├── Program.cs │ ├── TemplatedDataGridDemo.csproj │ ├── ViewLocator.cs │ ├── ViewModels │ ├── ItemViewModel.cs │ ├── MainWindowViewModel.cs │ └── ViewModelBase.cs │ └── Views │ ├── MainWindow.axaml │ └── MainWindow.axaml.cs ├── src └── TemplatedDataGrid │ ├── Controls │ ├── TemplatedListBox.cs │ └── TemplatedListBoxItem.cs │ ├── Internal │ └── AvaloniaObjectExtensions.cs │ ├── Primitives │ ├── TemplatedDataGridCellsPresenter.cs │ ├── TemplatedDataGridColumnHeadersPresenter.cs │ ├── TemplatedDataGridDetailsPresenter.cs │ └── TemplatedDataGridRowsPresenter.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── TemplatedDataGrid.cs │ ├── TemplatedDataGrid.csproj │ ├── TemplatedDataGridBoundColumn.cs │ ├── TemplatedDataGridCell.cs │ ├── TemplatedDataGridCheckBoxColumn.cs │ ├── TemplatedDataGridColumn.cs │ ├── TemplatedDataGridColumnHeader.cs │ ├── TemplatedDataGridGridLinesVisibility.cs │ ├── TemplatedDataGridRow.cs │ ├── TemplatedDataGridRowGroupHeader.cs │ ├── TemplatedDataGridRowHeader.cs │ ├── TemplatedDataGridTemplateColumn.cs │ ├── TemplatedDataGridTextColumn.cs │ └── Themes │ └── Fluent.axaml └── tests └── TemplatedDataGrid.UnitTests ├── Properties └── AssemblyInfo.cs └── TemplatedDataGrid.UnitTests.csproj /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Default settings: 7 | # A newline ending every file 8 | # Use 4 spaces as indentation 9 | [*] 10 | insert_final_newline = true 11 | indent_style = space 12 | indent_size = 4 13 | 14 | # C# files 15 | [*.cs] 16 | # New line preferences 17 | csharp_new_line_before_open_brace = all 18 | csharp_new_line_before_else = true 19 | csharp_new_line_before_catch = true 20 | csharp_new_line_before_finally = true 21 | csharp_new_line_before_members_in_object_initializers = true 22 | csharp_new_line_before_members_in_anonymous_types = true 23 | csharp_new_line_between_query_expression_clauses = true 24 | 25 | # Indentation preferences 26 | csharp_indent_block_contents = true 27 | csharp_indent_braces = false 28 | csharp_indent_case_contents = true 29 | csharp_indent_switch_labels = true 30 | csharp_indent_labels = one_less_than_current 31 | 32 | # avoid this. unless absolutely necessary 33 | dotnet_style_qualification_for_field = false:suggestion 34 | dotnet_style_qualification_for_property = false:suggestion 35 | dotnet_style_qualification_for_method = false:suggestion 36 | dotnet_style_qualification_for_event = false:suggestion 37 | 38 | # prefer var 39 | csharp_style_var_for_built_in_types = true 40 | csharp_style_var_when_type_is_apparent = true 41 | csharp_style_var_elsewhere = true:suggestion 42 | 43 | # use language keywords instead of BCL types 44 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 45 | dotnet_style_predefined_type_for_member_access = true:suggestion 46 | 47 | # name all constant fields using PascalCase 48 | dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion 49 | dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields 50 | dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style 51 | 52 | dotnet_naming_symbols.constant_fields.applicable_kinds = field 53 | dotnet_naming_symbols.constant_fields.required_modifiers = const 54 | 55 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case 56 | 57 | # static fields should have s_ prefix 58 | dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion 59 | dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields 60 | dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style 61 | 62 | dotnet_naming_symbols.static_fields.applicable_kinds = field 63 | dotnet_naming_symbols.static_fields.required_modifiers = static 64 | 65 | dotnet_naming_style.static_prefix_style.required_prefix = s_ 66 | dotnet_naming_style.static_prefix_style.capitalization = camel_case 67 | 68 | # internal and private fields should be _camelCase 69 | dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion 70 | dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields 71 | dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style 72 | 73 | dotnet_naming_symbols.private_internal_fields.applicable_kinds = field 74 | dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal 75 | 76 | dotnet_naming_style.camel_case_underscore_style.required_prefix = _ 77 | dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case 78 | 79 | # use accessibility modifiers 80 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion 81 | 82 | # Code style defaults 83 | dotnet_sort_system_directives_first = true 84 | csharp_preserve_single_line_blocks = true 85 | csharp_preserve_single_line_statements = false 86 | 87 | # Expression-level preferences 88 | dotnet_style_object_initializer = true:suggestion 89 | dotnet_style_collection_initializer = true:suggestion 90 | dotnet_style_explicit_tuple_names = true:suggestion 91 | dotnet_style_coalesce_expression = true:suggestion 92 | dotnet_style_null_propagation = true:suggestion 93 | 94 | # Expression-bodied members 95 | csharp_style_expression_bodied_methods = false:none 96 | csharp_style_expression_bodied_constructors = false:none 97 | csharp_style_expression_bodied_operators = false:none 98 | csharp_style_expression_bodied_properties = true:none 99 | csharp_style_expression_bodied_indexers = true:none 100 | csharp_style_expression_bodied_accessors = true:none 101 | 102 | # Pattern matching 103 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 104 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 105 | csharp_style_inlined_variable_declaration = true:suggestion 106 | 107 | # Null checking preferences 108 | csharp_style_throw_expression = true:suggestion 109 | csharp_style_conditional_delegate_call = true:suggestion 110 | 111 | # Space preferences 112 | csharp_space_after_cast = false 113 | csharp_space_after_colon_in_inheritance_clause = true 114 | csharp_space_after_comma = true 115 | csharp_space_after_dot = false 116 | csharp_space_after_keywords_in_control_flow_statements = true 117 | csharp_space_after_semicolon_in_for_statement = true 118 | csharp_space_around_binary_operators = before_and_after 119 | csharp_space_around_declaration_statements = do_not_ignore 120 | csharp_space_before_colon_in_inheritance_clause = true 121 | csharp_space_before_comma = false 122 | csharp_space_before_dot = false 123 | csharp_space_before_open_square_brackets = false 124 | csharp_space_before_semicolon_in_for_statement = false 125 | csharp_space_between_empty_square_brackets = false 126 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 127 | csharp_space_between_method_call_name_and_opening_parenthesis = false 128 | csharp_space_between_method_call_parameter_list_parentheses = false 129 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 130 | csharp_space_between_method_declaration_name_and_open_parenthesis = false 131 | csharp_space_between_method_declaration_parameter_list_parentheses = false 132 | csharp_space_between_parentheses = false 133 | csharp_space_between_square_brackets = false 134 | 135 | # Xaml files 136 | [*.{xaml,axaml}] 137 | indent_style = space 138 | indent_size = 2 139 | 140 | # Xml project files 141 | [*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] 142 | indent_size = 2 143 | 144 | # Xml build files 145 | [*.builds] 146 | indent_size = 2 147 | 148 | # Xml files 149 | [*.{xml,stylecop,resx,ruleset}] 150 | indent_size = 2 151 | 152 | # Xml config files 153 | [*.{props,targets,config,nuspec}] 154 | indent_size = 2 155 | 156 | # Shell scripts 157 | [*.sh] 158 | end_of_line = lf 159 | [*.{cmd, bat}] 160 | end_of_line = crlf -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [wieslawsoltes] 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # https://probot.github.io/apps/stale/ 2 | 3 | # Number of days of inactivity before an issue becomes stale 4 | daysUntilStale: 60 5 | 6 | # Number of days of inactivity before a stale issue is closed 7 | daysUntilClose: 7 8 | 9 | # Issues with these labels will never be considered stale 10 | exemptLabels: 11 | - pinned 12 | - security 13 | 14 | # Label to use when marking an issue as stale 15 | staleLabel: stale 16 | 17 | # Comment to post when marking an issue as stale. Set to `false` to disable 18 | markComment: > 19 | This issue has been automatically marked as stale because it has not had 20 | recent activity. It will be closed if no further activity occurs. Thank you 21 | for your contributions. 22 | 23 | # Comment to post when closing a stale issue. Set to `false` to disable 24 | closeComment: true 25 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - release/* 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | build: 14 | strategy: 15 | matrix: 16 | os: [ubuntu-latest, windows-latest, macos-latest] 17 | name: Build ${{ matrix.os }} 18 | runs-on: ${{ matrix.os }} 19 | 20 | steps: 21 | - uses: actions/checkout@v1 22 | - name: Setup .NET Core 23 | uses: actions/setup-dotnet@v1 24 | - name: Build Release 25 | run: dotnet build --configuration Release 26 | - name: Test Release 27 | run: dotnet test --configuration Release 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | -------------------------------------------------------------------------------- /.nuke/build.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "Build Schema", 4 | "$ref": "#/definitions/build", 5 | "definitions": { 6 | "build": { 7 | "type": "object", 8 | "properties": { 9 | "Configuration": { 10 | "type": "string", 11 | "description": "configuration" 12 | }, 13 | "Continue": { 14 | "type": "boolean", 15 | "description": "Indicates to continue a previously failed build attempt" 16 | }, 17 | "Help": { 18 | "type": "boolean", 19 | "description": "Shows the help text for this build assembly" 20 | }, 21 | "Host": { 22 | "type": "string", 23 | "description": "Host for execution. Default is 'automatic'", 24 | "enum": [ 25 | "AppVeyor", 26 | "AzurePipelines", 27 | "Bamboo", 28 | "Bitrise", 29 | "GitHubActions", 30 | "GitLab", 31 | "Jenkins", 32 | "Rider", 33 | "SpaceAutomation", 34 | "TeamCity", 35 | "Terminal", 36 | "TravisCI", 37 | "VisualStudio", 38 | "VSCode" 39 | ] 40 | }, 41 | "NoLogo": { 42 | "type": "boolean", 43 | "description": "Disables displaying the NUKE logo" 44 | }, 45 | "Partition": { 46 | "type": "string", 47 | "description": "Partition to use on CI" 48 | }, 49 | "Plan": { 50 | "type": "boolean", 51 | "description": "Shows the execution plan (HTML)" 52 | }, 53 | "Profile": { 54 | "type": "array", 55 | "description": "Defines the profiles to load", 56 | "items": { 57 | "type": "string" 58 | } 59 | }, 60 | "PublishFramework": { 61 | "type": "string", 62 | "description": "publish-framework" 63 | }, 64 | "PublishProject": { 65 | "type": "string", 66 | "description": "publish-project" 67 | }, 68 | "PublishRuntime": { 69 | "type": "string", 70 | "description": "publish-runtime" 71 | }, 72 | "PublishSelfContained": { 73 | "type": "boolean", 74 | "description": "publish-self-contained" 75 | }, 76 | "Root": { 77 | "type": "string", 78 | "description": "Root directory during build execution" 79 | }, 80 | "Skip": { 81 | "type": "array", 82 | "description": "List of targets to be skipped. Empty list skips all dependencies", 83 | "items": { 84 | "type": "string", 85 | "enum": [ 86 | "Clean", 87 | "Compile", 88 | "Pack", 89 | "Publish", 90 | "Restore", 91 | "Test" 92 | ] 93 | } 94 | }, 95 | "Solution": { 96 | "type": "string", 97 | "description": "Path to a solution file that is automatically loaded" 98 | }, 99 | "Target": { 100 | "type": "array", 101 | "description": "List of targets to be invoked. Default is '{default_target}'", 102 | "items": { 103 | "type": "string", 104 | "enum": [ 105 | "Clean", 106 | "Compile", 107 | "Pack", 108 | "Publish", 109 | "Restore", 110 | "Test" 111 | ] 112 | } 113 | }, 114 | "Verbosity": { 115 | "type": "string", 116 | "description": "Logging verbosity during build execution. Default is 'Normal'", 117 | "enum": [ 118 | "Minimal", 119 | "Normal", 120 | "Quiet", 121 | "Verbose" 122 | ] 123 | }, 124 | "VersionSuffix": { 125 | "type": "string", 126 | "description": "version-suffix" 127 | } 128 | } 129 | } 130 | } 131 | } -------------------------------------------------------------------------------- /.nuke/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./build.schema.json", 3 | "Solution": "TemplatedDataGrid.sln" 4 | } -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Wiesław Šoltés 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TemplatedDataGrid 2 | 3 | [![Build Status](https://dev.azure.com/wieslawsoltes/GitHub/_apis/build/status/wieslawsoltes.TemplatedDataGrid?branchName=main)](https://dev.azure.com/wieslawsoltes/GitHub/_build/latest?definitionId=91&branchName=main) 4 | [![CI](https://github.com/wieslawsoltes/TemplatedDataGrid/actions/workflows/build.yml/badge.svg)](https://github.com/wieslawsoltes/TemplatedDataGrid/actions/workflows/build.yml) 5 | 6 | [![NuGet](https://img.shields.io/nuget/v/TemplatedDataGrid.svg)](https://www.nuget.org/packages/TemplatedDataGrid) 7 | [![NuGet](https://img.shields.io/nuget/dt/TemplatedDataGrid.svg)](https://www.nuget.org/packages/TemplatedDataGrid) 8 | [![MyGet](https://img.shields.io/myget/templateddatagrid-nightly/vpre/TemplatedDataGrid.svg?label=myget)](https://www.myget.org/gallery/templateddatagrid-nightly) 9 | 10 | A DataGrid control based on ListBox and Grid panels. 11 | 12 | ![image](https://user-images.githubusercontent.com/2297442/129415635-15da4974-1b12-42a6-a97a-71f6cf48658b.png) 13 | 14 | ## Building TemplatedDataGrid 15 | 16 | First, clone the repository or download the latest zip. 17 | ``` 18 | git clone https://github.com/wieslawsoltes/TemplatedDataGrid.git 19 | ``` 20 | 21 | ### Build on Windows using script 22 | 23 | * [.NET Core](https://www.microsoft.com/net/download?initial-os=windows). 24 | 25 | Open up a command-prompt and execute the commands: 26 | ``` 27 | .\build.ps1 28 | ``` 29 | 30 | ### Build on Linux using script 31 | 32 | * [.NET Core](https://www.microsoft.com/net/download?initial-os=linux). 33 | 34 | Open up a terminal prompt and execute the commands: 35 | ``` 36 | ./build.sh 37 | ``` 38 | 39 | ### Build on OSX using script 40 | 41 | * [.NET Core](https://www.microsoft.com/net/download?initial-os=macos). 42 | 43 | Open up a terminal prompt and execute the commands: 44 | ``` 45 | ./build.sh 46 | ``` 47 | 48 | ## NuGet 49 | 50 | TemplatedDataGrid is delivered as a NuGet package. 51 | 52 | You can find the packages here [NuGet](https://www.nuget.org/packages/TemplatedDataGrid/) and install the package like this: 53 | 54 | `Install-Package TemplatedDataGrid` 55 | 56 | or by using nightly build feed: 57 | * Add `https://www.myget.org/F/templateddatagrid-nightly/api/v3/index.json` to your package sources 58 | * Alternative nightly build feed `https://pkgs.dev.azure.com/wieslawsoltes/GitHub/_packaging/Nightly/nuget/v3/index.json` 59 | * Update your package using `TemplatedDataGrid` feed 60 | 61 | and install the package like this: 62 | 63 | `Install-Package TemplatedDataGrid -Pre` 64 | 65 | ### Package Sources 66 | 67 | * https://api.nuget.org/v3/index.json 68 | * https://www.myget.org/F/avalonia-ci/api/v2 69 | 70 | ## Resources 71 | 72 | * [GitHub source code repository.](https://github.com/wieslawsoltes/TemplatedDataGrid) 73 | 74 | ## License 75 | 76 | TemplatedDataGrid is licensed under the [MIT license](LICENSE.TXT). 77 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Security Commitment 4 | 5 | We value the security of our open-source projects and actively encourage responsible reporting of vulnerabilities. However, due to the nature of open-source software provided under the MIT License, the software is delivered "as is," without warranty or any formal commitment to security or support. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | If you identify a security vulnerability, please report it by opening an issue in this repository. We aim to acknowledge receipt of vulnerability reports within a reasonable time frame, though no guaranteed response time is provided. 10 | 11 | ## Liability Disclaimer 12 | 13 | The maintainers and contributors of this project disclaim all liabilities arising from vulnerabilities or security incidents. Users are solely responsible for evaluating and mitigating risks associated with the use of this software. 14 | 15 | By using this project, you acknowledge and accept these terms. 16 | 17 | -------------------------------------------------------------------------------- /TemplatedDataGrid.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemplatedDataGrid", "src\TemplatedDataGrid\TemplatedDataGrid.csproj", "{941DBB36-F74A-442F-8D4D-F43E6B58F2A9}" 4 | EndProject 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7FDA3505-545B-4392-A3A9-D8F694C3C14F}" 6 | ProjectSection(SolutionItems) = preProject 7 | .editorconfig = .editorconfig 8 | build.ps1 = build.ps1 9 | build.sh = build.sh 10 | global.json = global.json 11 | build\templateddatagrid.public.snk = build\templateddatagrid.public.snk 12 | azure-pipelines.yml = azure-pipelines.yml 13 | EndProjectSection 14 | EndProject 15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "git", "git", "{BFD1765A-82DE-42D3-9359-771EC12D7281}" 16 | ProjectSection(SolutionItems) = preProject 17 | .gitattributes = .gitattributes 18 | .gitignore = .gitignore 19 | EndProjectSection 20 | EndProject 21 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuget", "nuget", "{3603BA2F-4BE5-49EC-B7D7-BEC6EC9AF630}" 22 | ProjectSection(SolutionItems) = preProject 23 | nuget.config = nuget.config 24 | EndProjectSection 25 | EndProject 26 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "props", "props", "{F9FE1661-0D9F-43E3-8861-9A0AA0BC507B}" 27 | ProjectSection(SolutionItems) = preProject 28 | build\Avalonia.Desktop.props = build\Avalonia.Desktop.props 29 | build\Avalonia.Diagnostics.props = build\Avalonia.Diagnostics.props 30 | build\Avalonia.props = build\Avalonia.props 31 | build\Avalonia.ReactiveUI.props = build\Avalonia.ReactiveUI.props 32 | build\Base.props = build\Base.props 33 | build\ReferenceAssemblies.props = build\ReferenceAssemblies.props 34 | build\SignAssembly.props = build\SignAssembly.props 35 | build\SourceLink.props = build\SourceLink.props 36 | build\XUnit.props = build\XUnit.props 37 | build\System.Reactive.props = build\System.Reactive.props 38 | build\Avalonia.Themes.Fluent.props = build\Avalonia.Themes.Fluent.props 39 | build\Avalonia.Fonts.Inter.props = build\Avalonia.Fonts.Inter.props 40 | EndProjectSection 41 | EndProject 42 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_build", "build\build\_build.csproj", "{52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}" 43 | EndProject 44 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F8CF95EB-93C2-4ACE-AEDF-570F68A39601}" 45 | EndProject 46 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{7E493E2E-54BB-4774-8899-205E86AFD281}" 47 | EndProject 48 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D2A68122-27EA-4B4B-AA14-F93E6CFE8B74}" 49 | EndProject 50 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{A28198F3-8C60-4671-B977-8F83E0167359}" 51 | ProjectSection(SolutionItems) = preProject 52 | LICENSE.TXT = LICENSE.TXT 53 | README.md = README.md 54 | EndProjectSection 55 | EndProject 56 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemplatedDataGridDemo", "samples\TemplatedDataGridDemo\TemplatedDataGridDemo.csproj", "{4E69A42B-0199-4B3C-A0CA-D7418517D99F}" 57 | EndProject 58 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemplatedDataGrid.UnitTests", "tests\TemplatedDataGrid.UnitTests\TemplatedDataGrid.UnitTests.csproj", "{F80215A5-0643-4A4A-8B63-AE322094524C}" 59 | EndProject 60 | Global 61 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 62 | Debug|Any CPU = Debug|Any CPU 63 | Debug|x64 = Debug|x64 64 | Release|Any CPU = Release|Any CPU 65 | Release|x64 = Release|x64 66 | EndGlobalSection 67 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 68 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 69 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9}.Debug|Any CPU.Build.0 = Debug|Any CPU 70 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9}.Release|Any CPU.ActiveCfg = Release|Any CPU 71 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9}.Release|Any CPU.Build.0 = Release|Any CPU 72 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9}.Debug|x64.ActiveCfg = Debug|x64 73 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9}.Debug|x64.Build.0 = Debug|x64 74 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9}.Release|x64.ActiveCfg = Release|x64 75 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9}.Release|x64.Build.0 = Release|x64 76 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 77 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}.Debug|Any CPU.Build.0 = Debug|Any CPU 78 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}.Debug|x64.ActiveCfg = Debug|Any CPU 79 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}.Debug|x64.Build.0 = Debug|Any CPU 80 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}.Release|Any CPU.ActiveCfg = Release|Any CPU 81 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}.Release|Any CPU.Build.0 = Release|Any CPU 82 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}.Release|x64.ActiveCfg = Release|Any CPU 83 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A}.Release|x64.Build.0 = Release|Any CPU 84 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 85 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F}.Debug|Any CPU.Build.0 = Debug|Any CPU 86 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F}.Debug|x64.ActiveCfg = Debug|x64 87 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F}.Debug|x64.Build.0 = Debug|x64 88 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F}.Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F}.Release|Any CPU.Build.0 = Release|Any CPU 90 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F}.Release|x64.ActiveCfg = Release|x64 91 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F}.Release|x64.Build.0 = Release|x64 92 | {F80215A5-0643-4A4A-8B63-AE322094524C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 93 | {F80215A5-0643-4A4A-8B63-AE322094524C}.Debug|Any CPU.Build.0 = Debug|Any CPU 94 | {F80215A5-0643-4A4A-8B63-AE322094524C}.Debug|x64.ActiveCfg = Debug|Any CPU 95 | {F80215A5-0643-4A4A-8B63-AE322094524C}.Debug|x64.Build.0 = Debug|Any CPU 96 | {F80215A5-0643-4A4A-8B63-AE322094524C}.Release|Any CPU.ActiveCfg = Release|Any CPU 97 | {F80215A5-0643-4A4A-8B63-AE322094524C}.Release|Any CPU.Build.0 = Release|Any CPU 98 | {F80215A5-0643-4A4A-8B63-AE322094524C}.Release|x64.ActiveCfg = Release|Any CPU 99 | {F80215A5-0643-4A4A-8B63-AE322094524C}.Release|x64.Build.0 = Release|Any CPU 100 | EndGlobalSection 101 | GlobalSection(NestedProjects) = preSolution 102 | {BFD1765A-82DE-42D3-9359-771EC12D7281} = {7FDA3505-545B-4392-A3A9-D8F694C3C14F} 103 | {3603BA2F-4BE5-49EC-B7D7-BEC6EC9AF630} = {7FDA3505-545B-4392-A3A9-D8F694C3C14F} 104 | {F9FE1661-0D9F-43E3-8861-9A0AA0BC507B} = {7FDA3505-545B-4392-A3A9-D8F694C3C14F} 105 | {52F8BE66-BC84-4909-AFD2-AE15AFDFF69A} = {7FDA3505-545B-4392-A3A9-D8F694C3C14F} 106 | {4E69A42B-0199-4B3C-A0CA-D7418517D99F} = {7E493E2E-54BB-4774-8899-205E86AFD281} 107 | {941DBB36-F74A-442F-8D4D-F43E6B58F2A9} = {F8CF95EB-93C2-4ACE-AEDF-570F68A39601} 108 | {F80215A5-0643-4A4A-8B63-AE322094524C} = {D2A68122-27EA-4B4B-AA14-F93E6CFE8B74} 109 | EndGlobalSection 110 | EndGlobal 111 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | name: $(date:yyyyMMdd)$(rev:-rr) 2 | 3 | resources: 4 | repositories: 5 | - repository: templates 6 | endpoint: wieslawsoltes 7 | type: github 8 | name: wieslawsoltes/BuildTemplates 9 | ref: refs/tags/v1.0.0 10 | 11 | variables: 12 | BuildConfiguration: 'Release' 13 | BuildPlatform: 'Any CPU' 14 | PublishFramework: 'net9.0' 15 | PublishProject: 'TemplatedDataGridDemo' 16 | PublishRuntime: '' 17 | 18 | jobs: 19 | - template: Test-PowerShell.yml@templates 20 | parameters: 21 | name: 'Test_Windows' 22 | vmImage: 'windows-2022' 23 | BuildConfiguration: ${{ variables.BuildConfiguration }} 24 | 25 | - template: Test-Bash.yml@templates 26 | parameters: 27 | name: 'Test_Linux' 28 | vmImage: 'ubuntu-22.04' 29 | BuildConfiguration: ${{ variables.BuildConfiguration }} 30 | 31 | - template: Test-Bash.yml@templates 32 | parameters: 33 | name: 'Test_macOS' 34 | vmImage: 'macOS-14' 35 | BuildConfiguration: ${{ variables.BuildConfiguration }} 36 | 37 | - template: Pack-MyGet.yml@templates 38 | parameters: 39 | name: 'Pack_MyGet' 40 | vmImage: 'windows-2022' 41 | BuildConfiguration: ${{ variables.BuildConfiguration }} 42 | 43 | - template: Pack-NuGet.yml@templates 44 | parameters: 45 | name: 'Pack_NuGet' 46 | vmImage: 'windows-2022' 47 | BuildConfiguration: ${{ variables.BuildConfiguration }} 48 | 49 | - template: Publish-PowerShell.yml@templates 50 | parameters: 51 | name: 'Publish_Windows' 52 | vmImage: 'windows-2022' 53 | BuildConfiguration: ${{ variables.BuildConfiguration }} 54 | PublishFramework: ${{ variables.PublishFramework }} 55 | PublishProject: ${{ variables.PublishProject }} 56 | PublishRuntime: 'win-x64' 57 | 58 | - template: Publish-Bash.yml@templates 59 | parameters: 60 | name: 'Publish_Linux' 61 | vmImage: 'ubuntu-22.04' 62 | BuildConfiguration: ${{ variables.BuildConfiguration }} 63 | PublishFramework: ${{ variables.PublishFramework }} 64 | PublishProject: ${{ variables.PublishProject }} 65 | PublishRuntime: 'linux-x64' 66 | 67 | - template: Publish-Bash.yml@templates 68 | parameters: 69 | name: 'Publish_macOS' 70 | vmImage: 'macOS-14' 71 | BuildConfiguration: ${{ variables.BuildConfiguration }} 72 | PublishFramework: ${{ variables.PublishFramework }} 73 | PublishProject: ${{ variables.PublishProject }} 74 | PublishRuntime: 'osx-x64' 75 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | :; set -eo pipefail 2 | :; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) 3 | :; ${SCRIPT_DIR}/build.sh "$@" 4 | :; exit $? 5 | 6 | @ECHO OFF 7 | powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %* 8 | -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | Param( 3 | [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] 4 | [string[]]$BuildArguments 5 | ) 6 | 7 | Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)" 8 | 9 | Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 } 10 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 11 | 12 | ########################################################################### 13 | # CONFIGURATION 14 | ########################################################################### 15 | 16 | $BuildProjectFile = "$PSScriptRoot\build\build\_build.csproj" 17 | $TempDirectory = "$PSScriptRoot\\.nuke\temp" 18 | 19 | $DotNetGlobalFile = "$PSScriptRoot\\global.json" 20 | $DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1" 21 | $DotNetChannel = "Current" 22 | 23 | $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 24 | $env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 25 | $env:DOTNET_MULTILEVEL_LOOKUP = 0 26 | 27 | ########################################################################### 28 | # EXECUTION 29 | ########################################################################### 30 | 31 | function ExecSafe([scriptblock] $cmd) { 32 | & $cmd 33 | if ($LASTEXITCODE) { exit $LASTEXITCODE } 34 | } 35 | 36 | # If dotnet CLI is installed globally and it matches requested version, use for execution 37 | if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` 38 | $(dotnet --version) -and $LASTEXITCODE -eq 0) { 39 | $env:DOTNET_EXE = (Get-Command "dotnet").Path 40 | } 41 | else { 42 | # Download install script 43 | $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" 44 | New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null 45 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 46 | (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) 47 | 48 | # If global.json exists, load expected version 49 | if (Test-Path $DotNetGlobalFile) { 50 | $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) 51 | if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { 52 | $DotNetVersion = $DotNetGlobal.sdk.version 53 | } 54 | } 55 | 56 | # Install by channel or version 57 | $DotNetDirectory = "$TempDirectory\dotnet-win" 58 | if (!(Test-Path variable:DotNetVersion)) { 59 | ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } 60 | } else { 61 | ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } 62 | } 63 | $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" 64 | } 65 | 66 | Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)" 67 | 68 | ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet } 69 | ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } 70 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | bash --version 2>&1 | head -n 1 4 | 5 | set -eo pipefail 6 | SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) 7 | 8 | ########################################################################### 9 | # CONFIGURATION 10 | ########################################################################### 11 | 12 | BUILD_PROJECT_FILE="$SCRIPT_DIR/build/build/_build.csproj" 13 | TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp" 14 | 15 | DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" 16 | DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh" 17 | DOTNET_CHANNEL="Current" 18 | 19 | export DOTNET_CLI_TELEMETRY_OPTOUT=1 20 | export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 21 | export DOTNET_MULTILEVEL_LOOKUP=0 22 | 23 | ########################################################################### 24 | # EXECUTION 25 | ########################################################################### 26 | 27 | function FirstJsonValue { 28 | perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}" 29 | } 30 | 31 | # If dotnet CLI is installed globally and it matches requested version, use for execution 32 | if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then 33 | export DOTNET_EXE="$(command -v dotnet)" 34 | else 35 | # Download install script 36 | DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" 37 | mkdir -p "$TEMP_DIRECTORY" 38 | curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" 39 | chmod +x "$DOTNET_INSTALL_FILE" 40 | 41 | # If global.json exists, load expected version 42 | if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then 43 | DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")") 44 | if [[ "$DOTNET_VERSION" == "" ]]; then 45 | unset DOTNET_VERSION 46 | fi 47 | fi 48 | 49 | # Install by channel or version 50 | DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" 51 | if [[ -z ${DOTNET_VERSION+x} ]]; then 52 | "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path 53 | else 54 | "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path 55 | fi 56 | export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" 57 | fi 58 | 59 | echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)" 60 | 61 | "$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet 62 | "$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" 63 | -------------------------------------------------------------------------------- /build/Avalonia.Desktop.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /build/Avalonia.Diagnostics.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /build/Avalonia.Fonts.Inter.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /build/Avalonia.ReactiveUI.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /build/Avalonia.Themes.Fluent.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /build/Avalonia.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /build/Base.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11.2.0 4 | 5 | Wiesław Šoltés 6 | Wiesław Šoltés 7 | Copyright © Wiesław Šoltés 2024 8 | MIT 9 | https://github.com/wieslawsoltes/TemplatedDataGrid 10 | 11 | 12 | latest 13 | preview 14 | 15 | 16 | -------------------------------------------------------------------------------- /build/ReferenceAssemblies.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /build/SignAssembly.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | True 5 | $(MSBuildThisFileDirectory)\templateddatagrid.public.snk 6 | false 7 | true 8 | 9 | 10 | -------------------------------------------------------------------------------- /build/SourceLink.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | false 5 | true 6 | embedded 7 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 8 | 9 | 10 | true 11 | 12 | 13 | true 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /build/System.Reactive.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /build/XUnit.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /build/build/Build.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Nuke.Common; 3 | using Nuke.Common.Git; 4 | using Nuke.Common.ProjectModel; 5 | using Nuke.Common.Tools.DotNet; 6 | using Nuke.Common.IO; 7 | using static Nuke.Common.IO.FileSystemTasks; 8 | using static Nuke.Common.IO.PathConstruction; 9 | using static Nuke.Common.Tools.DotNet.DotNetTasks; 10 | 11 | class Build : NukeBuild 12 | { 13 | public static int Main() => Execute(x => x.Compile); 14 | 15 | [Solution] 16 | readonly Solution Solution; 17 | 18 | [GitRepository] 19 | readonly GitRepository GitRepository; 20 | 21 | [Parameter("configuration")] 22 | public string Configuration { get; set; } 23 | 24 | [Parameter("version-suffix")] 25 | public string VersionSuffix { get; set; } 26 | 27 | [Parameter("publish-framework")] 28 | public string PublishFramework { get; set; } 29 | 30 | [Parameter("publish-runtime")] 31 | public string PublishRuntime { get; set; } 32 | 33 | [Parameter("publish-project")] 34 | public string PublishProject { get; set; } 35 | 36 | [Parameter("publish-self-contained")] 37 | public bool PublishSelfContained { get; set; } = true; 38 | 39 | AbsolutePath SourceDirectory => RootDirectory / "src"; 40 | 41 | AbsolutePath TestsDirectory => RootDirectory / "tests"; 42 | 43 | AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts"; 44 | 45 | protected override void OnBuildInitialized() 46 | { 47 | Configuration = Configuration ?? "Release"; 48 | VersionSuffix = VersionSuffix ?? ""; 49 | } 50 | 51 | private void DeleteDirectories(IReadOnlyCollection directories) 52 | { 53 | foreach (var directory in directories) 54 | { 55 | DeleteDirectory(directory); 56 | } 57 | } 58 | 59 | Target Clean => _ => _ 60 | .Executes(() => 61 | { 62 | DeleteDirectories(GlobDirectories(SourceDirectory, "**/bin", "**/obj")); 63 | DeleteDirectories(GlobDirectories(TestsDirectory, "**/bin", "**/obj")); 64 | EnsureCleanDirectory(ArtifactsDirectory); 65 | }); 66 | 67 | Target Restore => _ => _ 68 | .DependsOn(Clean) 69 | .Executes(() => 70 | { 71 | DotNetRestore(s => s 72 | .SetProjectFile(Solution)); 73 | }); 74 | 75 | Target Compile => _ => _ 76 | .DependsOn(Restore) 77 | .Executes(() => 78 | { 79 | DotNetBuild(s => s 80 | .SetProjectFile(Solution) 81 | .SetConfiguration(Configuration) 82 | .SetVersionSuffix(VersionSuffix) 83 | .EnableNoRestore()); 84 | }); 85 | 86 | Target Test => _ => _ 87 | .DependsOn(Compile) 88 | .Executes(() => 89 | { 90 | DotNetTest(s => s 91 | .SetProjectFile(Solution) 92 | .SetConfiguration(Configuration) 93 | .SetLoggers("trx") 94 | .SetResultsDirectory(ArtifactsDirectory / "TestResults") 95 | .EnableNoBuild() 96 | .EnableNoRestore()); 97 | }); 98 | 99 | Target Pack => _ => _ 100 | .DependsOn(Test) 101 | .Executes(() => 102 | { 103 | DotNetPack(s => s 104 | .SetProject(Solution) 105 | .SetConfiguration(Configuration) 106 | .SetVersionSuffix(VersionSuffix) 107 | .SetOutputDirectory(ArtifactsDirectory / "NuGet") 108 | .EnableNoBuild() 109 | .EnableNoRestore()); 110 | }); 111 | 112 | Target Publish => _ => _ 113 | .DependsOn(Test) 114 | .Requires(() => PublishRuntime) 115 | .Requires(() => PublishFramework) 116 | .Requires(() => PublishProject) 117 | .Executes(() => 118 | { 119 | DotNetPublish(s => s 120 | .SetProject(Solution.GetProject(PublishProject)) 121 | .SetConfiguration(Configuration) 122 | .SetVersionSuffix(VersionSuffix) 123 | .SetFramework(PublishFramework) 124 | .SetRuntime(PublishRuntime) 125 | .SetSelfContained(PublishSelfContained) 126 | .SetOutput(ArtifactsDirectory / "Publish" / PublishProject + "-" + PublishFramework + "-" + PublishRuntime)); 127 | }); 128 | } 129 | -------------------------------------------------------------------------------- /build/build/_build.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net9.0 6 | false 7 | False 8 | CS0649;CS0169 9 | 1 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /build/templateddatagrid.public.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wieslawsoltes/TemplatedDataGrid/f7723e0f2c6b5ba1d27a52a85351ad7e9b7fdc8e/build/templateddatagrid.public.snk -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "9.0.100", 4 | "rollForward": "latestMinor", 5 | "allowPrerelease": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/App.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Markup.Xaml; 4 | using TemplatedDataGridDemo.ViewModels; 5 | using TemplatedDataGridDemo.Views; 6 | 7 | namespace TemplatedDataGridDemo 8 | { 9 | public class App : Application 10 | { 11 | public override void Initialize() 12 | { 13 | AvaloniaXamlLoader.Load(this); 14 | } 15 | 16 | public override void OnFrameworkInitializationCompleted() 17 | { 18 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 19 | { 20 | desktop.MainWindow = new MainWindow 21 | { 22 | DataContext = new MainWindowViewModel(), 23 | }; 24 | } 25 | 26 | base.OnFrameworkInitializationCompleted(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/Assets/avalonia-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wieslawsoltes/TemplatedDataGrid/f7723e0f2c6b5ba1d27a52a85351ad7e9b7fdc8e/samples/TemplatedDataGridDemo/Assets/avalonia-logo.ico -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia; 3 | using Avalonia.ReactiveUI; 4 | 5 | namespace TemplatedDataGridDemo 6 | { 7 | class Program 8 | { 9 | [STAThread] 10 | public static void Main(string[] args) 11 | { 12 | BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); 13 | } 14 | 15 | public static AppBuilder BuildAvaloniaApp() 16 | { 17 | GC.KeepAlive(typeof(TemplatedDataGrid.TemplatedDataGrid).Assembly); 18 | 19 | return AppBuilder.Configure() 20 | .UsePlatformDetect() 21 | .LogToTrace() 22 | .UseReactiveUI(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/TemplatedDataGridDemo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | 5 | 6 | WinExe 7 | 8 | 9 | net9.0 10 | False 11 | enable 12 | TemplatedDataGridDemo 13 | Debug;Release 14 | AnyCPU;x64 15 | 16 | 17 | 18 | True 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | all 41 | runtime; build; native; contentfiles; analyzers; buildtransitive 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/ViewLocator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia.Controls; 3 | using Avalonia.Controls.Templates; 4 | using TemplatedDataGridDemo.ViewModels; 5 | 6 | namespace TemplatedDataGridDemo 7 | { 8 | public class ViewLocator : IDataTemplate 9 | { 10 | public Control Build(object? data) 11 | { 12 | var name = data?.GetType().FullName?.Replace("ViewModel", "View"); 13 | var type = name is null ? null : Type.GetType(name); 14 | 15 | if (type != null) 16 | { 17 | return (Control)Activator.CreateInstance(type)!; 18 | } 19 | 20 | return new TextBlock { Text = "Not Found: " + name }; 21 | } 22 | 23 | public bool Match(object? data) 24 | { 25 | return data is ViewModelBase; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/ViewModels/ItemViewModel.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | 3 | namespace TemplatedDataGridDemo.ViewModels 4 | { 5 | public partial class ItemViewModel : ViewModelBase 6 | { 7 | [Reactive] 8 | public partial string Column1 { get; set; } 9 | 10 | [Reactive] 11 | public partial string Column2 { get; set; } 12 | 13 | [Reactive] 14 | public partial string Column3 { get; set; } 15 | 16 | [Reactive] 17 | public partial bool Column4 { get; set; } 18 | 19 | [Reactive] 20 | public partial int Column5 { get; set; } 21 | 22 | [Reactive] 23 | public partial Thickness Margin { get; set; } 24 | 25 | public ItemViewModel(string column1, string column2, string column3, bool column4, int column5, Thickness margin) 26 | { 27 | _column1 = column1; 28 | _column2 = column2; 29 | _column3 = column3; 30 | _column4 = column4; 31 | _column5 = column5; 32 | _margin = margin; 33 | } 34 | 35 | public override string ToString() 36 | { 37 | return $"{_column5}"; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/ViewModels/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Reactive.Linq; 7 | using System.Reactive.Subjects; 8 | using System.Threading.Tasks; 9 | using System.Windows.Input; 10 | using Avalonia; 11 | using DynamicData; 12 | using DynamicData.Binding; 13 | using ReactiveUI; 14 | 15 | namespace TemplatedDataGridDemo.ViewModels 16 | { 17 | public partial class MainWindowViewModel : ViewModelBase 18 | { 19 | private ReadOnlyObservableCollection? _items; 20 | 21 | public ReadOnlyObservableCollection? Items => _items; 22 | 23 | [Reactive] 24 | public partial ItemViewModel? SelectedItem { get; set; } 25 | 26 | [Reactive] 27 | public partial ListSortDirection? SortingStateColumn1 { get; set; } 28 | 29 | [Reactive] 30 | public partial ListSortDirection? SortingStateColumn2 { get; set; } 31 | 32 | [Reactive] 33 | public partial ListSortDirection? SortingStateColumn3 { get; set; } 34 | 35 | [Reactive] 36 | public partial ListSortDirection? SortingStateColumn4 { get; set; } 37 | 38 | [Reactive] 39 | public partial ListSortDirection? SortingStateColumn5 { get; set; } 40 | 41 | public ICommand SortCommand { get; } 42 | 43 | public ICommand AddItemCommand { get; } 44 | 45 | public ICommand InsertItemCommand { get; } 46 | 47 | public ICommand RemoveItemCommand { get; } 48 | 49 | public ICommand SelectFirstItemCommand { get; } 50 | 51 | public MainWindowViewModel() 52 | { 53 | var itemsSourceList = new SourceList(); 54 | var comparerSubject = new Subject>(); 55 | var isSortingEnabled = false; 56 | var totalItems = 1_000; 57 | var enableRandom = false; 58 | var randomSize = 100; 59 | var rand = new Random(); 60 | var items = new List(); 61 | 62 | for (var i = 0; i < totalItems; i++) 63 | { 64 | items.Add(CreateItem(i)); 65 | } 66 | itemsSourceList.AddRange(items); 67 | 68 | IDisposable? subscription = null; 69 | SortingStateColumn5 = ListSortDirection.Ascending; 70 | EnableSort(x => x.Column5, SortingStateColumn5); 71 | 72 | ItemViewModel CreateItem(int index) 73 | { 74 | return new ItemViewModel( 75 | $"Template1 {index}-1", 76 | $"Template2 {index}-2", 77 | $"Template3 {index}-3", 78 | rand.NextDouble() > 0.5, 79 | index, 80 | enableRandom 81 | ? new Thickness(0, rand.NextDouble() * randomSize, 0, rand.NextDouble() * randomSize) 82 | : new Thickness(0)); 83 | } 84 | 85 | IObservable> GetSortObservable(IComparer comparer) 86 | { 87 | return itemsSourceList! 88 | .Connect() 89 | .ObserveOn(RxApp.MainThreadScheduler) 90 | .Sort(comparer, comparerChanged: comparerSubject) 91 | .Bind(out _items); 92 | } 93 | 94 | IObservable> GetDefaultObservable() 95 | { 96 | return itemsSourceList! 97 | .Connect() 98 | .ObserveOn(RxApp.MainThreadScheduler) 99 | .Bind(out _items); 100 | } 101 | 102 | void EnableSort(Func expression, ListSortDirection? listSortDirection) 103 | { 104 | var sortExpressionComparer = listSortDirection == ListSortDirection.Ascending 105 | ? SortExpressionComparer.Ascending(expression) 106 | : SortExpressionComparer.Descending(expression); 107 | 108 | if (!isSortingEnabled) 109 | { 110 | subscription?.Dispose(); 111 | subscription = GetSortObservable(sortExpressionComparer).Subscribe(); 112 | isSortingEnabled = true; 113 | this.RaisePropertyChanged(nameof(Items)); 114 | } 115 | else 116 | { 117 | comparerSubject.OnNext(sortExpressionComparer); 118 | } 119 | } 120 | 121 | void DisableSort() 122 | { 123 | if (isSortingEnabled) 124 | { 125 | subscription?.Dispose(); 126 | subscription = GetDefaultObservable().Subscribe(); 127 | isSortingEnabled = false; 128 | this.RaisePropertyChanged(nameof(Items)); 129 | } 130 | } 131 | 132 | void Sort(string? sortMemberPath) 133 | { 134 | switch (sortMemberPath) 135 | { 136 | case null: 137 | DisableSort(); 138 | break; 139 | case "Column1": 140 | EnableSort(x => x.Column1, SortingStateColumn1); 141 | break; 142 | case "Column2": 143 | EnableSort(x => x.Column2, SortingStateColumn2); 144 | break; 145 | case "Column3": 146 | EnableSort(x => x.Column3, SortingStateColumn3); 147 | break; 148 | case "Column4": 149 | EnableSort(x => x.Column4, SortingStateColumn4); 150 | break; 151 | case "Column5": 152 | EnableSort(x => x.Column5, SortingStateColumn5); 153 | break; 154 | } 155 | } 156 | 157 | SortCommand = ReactiveCommand.CreateFromTask(async sortMemberPath => 158 | { 159 | await Task.Run(() => 160 | { 161 | Sort(sortMemberPath); 162 | }); 163 | }); 164 | 165 | InsertItemCommand = ReactiveCommand.Create(() => 166 | { 167 | if (_items is null) 168 | { 169 | return; 170 | } 171 | var index = _items.Count; 172 | var item = CreateItem(index); 173 | itemsSourceList.Insert(0, item); 174 | }); 175 | 176 | AddItemCommand = ReactiveCommand.Create(() => 177 | { 178 | if (_items is null) 179 | { 180 | return; 181 | } 182 | var index = _items.Count; 183 | var item = CreateItem(index); 184 | itemsSourceList.Add(item); 185 | }); 186 | 187 | RemoveItemCommand = ReactiveCommand.Create((item) => 188 | { 189 | if (item is not null) 190 | { 191 | itemsSourceList.Remove(item); 192 | } 193 | }); 194 | 195 | SelectFirstItemCommand = ReactiveCommand.Create(() => 196 | { 197 | if (_items is null) 198 | { 199 | return; 200 | } 201 | SelectedItem = _items.FirstOrDefault(); 202 | }); 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace TemplatedDataGridDemo.ViewModels 4 | { 5 | public class ViewModelBase : ReactiveObject 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/TemplatedDataGridDemo/Views/MainWindow.axaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 28 | 31 | 32 | 33 | 34 | 35 |