├── .github └── workflows │ └── build_and_publish.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── resources └── images │ ├── BasicSample.gif │ ├── ColoredBandHeaderSample.png │ ├── FlexGridMergedHeader.png │ ├── FlexGridTemplateStructure.png │ ├── FrozenHeaderSample.gif │ ├── MergedHeaderSample.gif │ ├── VirtualBandSample.gif │ └── VirtualBandSample_ItemsSource_Image.png └── src ├── KevinComponent.Demo.App ├── App.xaml ├── App.xaml.cs ├── AssemblyInfo.cs ├── BindingProxy.cs ├── KevinComponent.Demo.App.csproj ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Models │ ├── Person.cs │ ├── Sample.cs │ ├── Score.cs │ └── Subject.cs └── Views │ ├── BasicSampleView.xaml │ ├── BasicSampleView.xaml.cs │ ├── ColoredBandHeaderSampleView.xaml │ ├── ColoredBandHeaderSampleView.xaml.cs │ ├── FrozenHeaderView.xaml │ ├── FrozenHeaderView.xaml.cs │ ├── MergedHeaderSampleView.xaml │ ├── MergedHeaderSampleView.xaml.cs │ ├── VirtualBandSampleView.xaml │ └── VirtualBandSampleView.xaml.cs ├── KevinComponent.sln └── KevinComponent ├── AssemblyInfo.cs ├── Assist ├── FlexGridAssist.cs └── TextBoxAssist.cs ├── Band.cs ├── BandCollection.cs ├── BandHeader.cs ├── BandHeaderGripper.cs ├── BandHeadersPresenter.cs ├── CheckBoxBand.cs ├── ComboBoxBand.cs ├── FlexGrid.cs ├── FlexGridColumn.cs ├── FlexGridCommittedArgs.cs ├── IVirtualBandBindable.cs ├── KevinComponent.csproj ├── TemplateBand.cs ├── TextBand.cs ├── Themes ├── Generic.xaml ├── Theme.Colors.xaml └── Theme.FlexGrid.xaml ├── Utils.cs ├── VirtualBand.cs ├── VirtualBandBinding.cs ├── VirtualBandMultiBinding.cs ├── VirtualBandPriorityBinding.cs ├── VirtualCheckBoxBand.cs ├── VirtualComboBoxBand.cs ├── VirtualTemplateBand.cs └── VirtualTextBand.cs /.github/workflows/build_and_publish.yml: -------------------------------------------------------------------------------- 1 | name : Build And Publish to Nuget 2 | on: 3 | push: 4 | branches: [ master ] 5 | # workflow_dispatch: 6 | # inputs: 7 | # tags: 8 | # description: 'Description' 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | env: 14 | SOLUTION_FILE: src/KevinComponent.sln 15 | NUGET_FILE: src/KevinComponent/bin/GitHub Release/*.nupkg 16 | 17 | steps: 18 | - name: Load Repository Files 19 | uses: actions/checkout@v3 20 | 21 | - name: Setup .NET 22 | uses: actions/setup-dotnet@v3 23 | 24 | - name: Build Solution 25 | run: dotnet build $SOLUTION_FILE -c "GitHub Release" 26 | 27 | - name: Publish to nuget.org 28 | run: dotnet nuget push "$NUGET_FILE" --api-key ${{secrets.NUGET_API_KEY}} --source "https://api.nuget.org/v3/index.json" --skip-duplicate 29 | 30 | - name: Publish to GitHub Repository 31 | run: | 32 | dotnet nuget add source --username "soomin-kevin-sung" --password ${{secrets.ACCESS_TOKEN}} --store-password-in-clear-text --name "github" "https://nuget.pkg.github.com/soomin-kevin-sung/index.json" 33 | dotnet nuget push "$NUGET_FILE" --api-key ${{secrets.ACCESS_TOKEN}} --source "github" --skip-duplicate 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/.vs/ 2 | src/KevinComponent/Build/ 3 | src/KevinComponent/bin/ 4 | src/KevinComponent/obj/ 5 | src/KevinComponent.Demo.App/Build/ 6 | src/KevinComponent.Demo.App/bin/ 7 | src/KevinComponent.Demo.App/obj/ 8 | *.csproj.user 9 | 10 | # Ignore NuGet Packages 11 | *.nupkg 12 | 13 | # The packages folder can be ignored because of Package Restore 14 | **/[Pp]ackages/* 15 | 16 | # except build/, which is used as an MSBuild target. 17 | !**/[Pp]ackages/build/ 18 | 19 | # Uncomment if necessary however generally it will be regenerated when needed 20 | #!**/[Pp]ackages/repositories.config 21 | 22 | # NuGet v3's project.json files produces more ignorable files 23 | *.nuget.props 24 | *.nuget.targets 25 | 26 | # Ignore other intermediate files that NuGet might create. project.lock.json is used in conjunction 27 | # with project.json (NuGet v3); project.assets.json is used in conjunction with the PackageReference 28 | # format (NuGet v4 and .NET Core). 29 | project.lock.json 30 | project.assets.json -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 soomin-kevin-sung 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 | # FlexGrid 2 | 3 | [![Build And Publish to Nuget](https://github.com/soomin-kevin-sung/dotnet-flexgrid/actions/workflows/build_and_publish.yml/badge.svg?branch=master)](https://github.com/soomin-kevin-sung/dotnet-flexgrid/actions/workflows/build_and_publish.yml) 4 | ![Nuget](https://img.shields.io/nuget/v/flexgrid?label=NuGet&logo=NuGet) 5 |
6 | ![.NET](https://img.shields.io/badge/.NET-6.0-512BD4?style=flat)  7 | ![.NET](https://img.shields.io/badge/.NET-Framework%204.8-512BD4?style=flat)  8 | ![.NET](https://img.shields.io/badge/.NET-CoreApp%203.1-512BD4?style=flat)  9 |
10 | [![CodeFactor](https://www.codefactor.io/repository/github/soomin-kevin-sung/dotnet-flexgrid/badge/master)](https://www.codefactor.io/repository/github/soomin-kevin-sung/dotnet-flexgrid/overview/master)  11 | [![License](https://img.shields.io/github/license/soomin-kevin-sung/dotnet-flexgrid)](LICENSE.md)  12 | ![C#](https://img.shields.io/badge/.NET-C%23-007396?style=flat)  13 | ![WPF](https://img.shields.io/badge/WPF-DataGrid-FF9900?style=flat)  14 | 15 | FlexGrid is a custom WPF DataGrid with convenient and useful features. When developing code using WPF, the Microsoft-supported DataGrid has limited functionality, such as nested and merged column headers and variable columns. However, with FlexGrid, your DataGrid development environment becomes significantly more convenient! 16 | 17 |
18 | 19 | I'm proud to say that FlexGrid was fully built by me, and I'm excited to share it on GitHub :) 20 | 21 |
22 | 23 | ## Goal 24 | 25 | - Create Customized DataGrid with convenient and useful features. 26 | - Use FlexGrid to develop other WPF Programs 27 | 28 |
29 | 30 | ## Available Features 31 | 32 | - [FlexGrid Template Structure](#flexgrid-template-structure) 33 | - [Using Bands Instead Of Columns](#using-bands-instead-of-columns) 34 | - [Bands and Frozen Bands](#bands-and-frozen-bands) 35 | - [Mergable Column Header (Band.Bands)](#mergable-column-header-bandbands) 36 | - [Variable Columns (VirtualBand)](#variable-columns-virtualband--virtualbandbinding) 37 | 38 |
39 | 40 | ## FlexGrid Template Structure 41 | 42 | FlexGrid is a Component that modified the Template of the default DataGrid. 43 | 44 |

45 | FlexGridTemplateStructure.png 46 |
47 | <FlexGrid Template Structure> 48 |

49 | 50 | ## Using Bands Instead Of Columns 51 | 52 | FlexGrid uses BandHeadersPresenters to represent the columns. The BandHeaderPresenter represents the Bands in FlexGrid.FrozenBands and FlexGrid.Bands as Columns in the FlexGrid. 53 | 54 | ### Band Types 55 | 56 | - TextBand 57 | - CheckBoxBand 58 | - ComboBoxBand 59 | - TemplateBand 60 | - VirtualBand 61 | - VirtualTextBand 62 | - VirtualCheckBoxBand 63 | - VirtualComboBoxBand 64 | - VirtualTemplateBand 65 | 66 | This is Example how to use Bands. 67 | 68 | ```xml 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | ``` 106 | 107 |
108 | 109 | ## Bands and Frozen Bands 110 | 111 | For represent Frozen Columns (Always showed Columns) in FlexGrid. You should use FlexGrid.FrozenBands. 112 | The FlexGrid shows to Bands in FlexGrid.FrozenBands as Frozen Columns. 113 | 114 | This is Example Code how to use Frozen Bands. 115 | 116 | ```xml 117 | 118 | 119 | 120 | 121 | 122 | 123 | 128 | 129 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 144 | 145 | 146 | 147 | ``` 148 | 149 |
150 | 151 | ## Mergable Column Header (Band.Bands) 152 | 153 | The **`Bands`** Property in Band can be used to represent Merged Column Headers. 154 | 155 |

156 | FlexGridMergedHeader.png 157 |
158 | <Merged Column Headers> 159 |

160 | 161 | Related StackOverflow questions: 162 | * [Multilevel column header for datagrid in wpf](https://stackoverflow.com/questions/17652039/multilevel-column-header-for-datagrid-in-wpf)
163 | * [Wpf datagrid header above header](https://stackoverflow.com/questions/51440426/wpf-datagrid-header-above-header)
164 | * [Merge header columns datagrid wpf](https://stackoverflow.com/questions/6446684/merge-header-columns-datagrid-wpf) 165 |

166 | 167 | This is Example Code how to use Band.Bands Object. 168 | 169 | ```xml 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 186 | 187 | 188 | 193 | 194 | 195 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | ``` 225 | 226 |
227 | 228 | ## Variable Columns (VirtualBand & VirtualBandBinding) 229 | 230 | FlexGrid can represent varaible columns by **`VirtualBand`** class. 231 |
232 | 233 | List of All kind of **`VirtualBand`**. 234 | - **`VirtualTextBand`** 235 | - **`VirtualCheckBoxBand`** 236 | - **`VirtualComboBoxBand`** 237 | - **`VirtualTemplateBand`** 238 |
239 | 240 | Related StackOverflow questions: 241 | * [How do i bind a wpf datagrid to a variable number of columns](https://stackoverflow.com/questions/320089/how-do-i-bind-a-wpf-datagrid-to-a-variable-number-of-columns)
242 | * [How do i dynamically generate columns in a wpf datagrid](https://stackoverflow.com/questions/1983033/how-do-i-dynamically-generate-columns-in-a-wpf-datagrid)
243 | 244 | Related CodeProject Articles: 245 | * [Dynamic Columns in a WPF DataGrid Control](https://www.codeproject.com/Articles/891995/Dynamic-Columns-in-a-WPF-DataGrid-Control-Part-2)
246 | 247 |
248 | 249 | This is Example Code how to use VirtualBands. 250 | 251 | ```xml 252 | 253 | 254 | 255 | 256 | 261 | 262 | 267 | 268 | 272 | 273 | 274 | 275 | 276 | 277 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | ``` 306 | 307 |
308 | 309 | The **`VirtualBandBinding`** is the class to binding property to generated bands by **`VirtualBand`**. FlexGrid converts the Items in the VirtualBand to Columns, while mapping the VirtualBandBinding to each property appropriately so that the data appears in the Cell. 310 | 311 | Refer to the code below. 312 | https://github.com/soomin-kevin-sung/dotnet-flexgrid/blob/c4e05c1f2c0517c263fdca6026c2e74f2cda1fe9/src/KevinComponent/Band.cs#L469-L496 313 | 314 |
315 | 316 | ## Samples 317 | 318 | ### Basic Sample 319 | 320 |

321 | BasicSample.gif 322 |
323 | <BasicSample ScreenShot> 324 |

325 | 326 | - **`BasicSample`** shows the basic usage of FlexGrid.
327 | - You can know how to use **`FlexGrid`** the basically in this sample. 328 | 329 |
330 | 331 | ### Frozen Header Sample 332 | 333 |

334 | BasicSample.gif 335 |
336 | <FrozenHedaerSample ScreenShot> 337 |

338 | 339 | - FrozenHedaerSample shows how to using the frozen columns.
340 | - You can use **`FlexGrid.FrozenBands`** to add frozen columns. 341 | - In this sample, the Name, BirthDate bands are Frozen Bands. 342 | 343 |
344 | 345 | ### Merged Header Sample 346 | 347 |

348 | BasicSample.gif 349 |
350 | <MergedHedaerSample ScreenShot> 351 |

352 | 353 | - MergedHedaerSample shows how to merge column headers.
354 | - You can use **`Band.Bands`**(ex. TextBand.Bands, CheckBoxBand.Bands, etc.) to merge column headers. 355 | - In this sample, you can see the Name, BirthDate, Address, and WebSite bands merged into the information band. 356 | 357 |
358 | 359 | ### VirtualBand Sample 360 | 361 |

362 | VirtualBandSample.gif 363 |
364 | <VirtualBandSample ScreenShot> 365 |

366 | 367 | - VirtualBandSample shows how variable columns are implemented in FlexGrid.
368 | - You can use **`VirtualBand`**(ex. VirtualTextBand, VirtualComboBoxBand, VirtualCheckBoxBand, etc.) to show variable columns. 369 | - In this Sample, you can see that the list of subject scores synchronizes with the subject list when you edit the subject list. 370 | 371 |

372 | VirtualBandSample.gif 373 |
374 | <ItemsSource Description> 375 |

376 | 377 |
378 | 379 | ### Colored BandHeader Sample 380 | 381 |

382 | ColoredBandHeaderSample.png 383 |
384 | <ColoredBandHeaderSample ScreenShot> 385 |

386 | 387 | - ColoredBandHeaderSample shows how to set header and cell style. 388 | - You can use **`Band.HeaderStyle`** and **`Band.CellStyle`** to set header style and cell style. 389 | 390 |
391 | 392 | ## Support 393 | 394 | If you have any good ideas (such as new featrue, refactoring, improvement feature quality, etc), do not hesitate to let me know!
395 | You also can "Pull request" or request adding New Feature to the email below. 396 | Thank you. 397 | 398 | - E-mail : ssm0725@gmail.com 399 | -------------------------------------------------------------------------------- /resources/images/BasicSample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soomin-kevin-sung/dotnet-flexgrid/9ae4e3da92df84145aa3ed73009820608a3a1d93/resources/images/BasicSample.gif -------------------------------------------------------------------------------- /resources/images/ColoredBandHeaderSample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soomin-kevin-sung/dotnet-flexgrid/9ae4e3da92df84145aa3ed73009820608a3a1d93/resources/images/ColoredBandHeaderSample.png -------------------------------------------------------------------------------- /resources/images/FlexGridMergedHeader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soomin-kevin-sung/dotnet-flexgrid/9ae4e3da92df84145aa3ed73009820608a3a1d93/resources/images/FlexGridMergedHeader.png -------------------------------------------------------------------------------- /resources/images/FlexGridTemplateStructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soomin-kevin-sung/dotnet-flexgrid/9ae4e3da92df84145aa3ed73009820608a3a1d93/resources/images/FlexGridTemplateStructure.png -------------------------------------------------------------------------------- /resources/images/FrozenHeaderSample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soomin-kevin-sung/dotnet-flexgrid/9ae4e3da92df84145aa3ed73009820608a3a1d93/resources/images/FrozenHeaderSample.gif -------------------------------------------------------------------------------- /resources/images/MergedHeaderSample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soomin-kevin-sung/dotnet-flexgrid/9ae4e3da92df84145aa3ed73009820608a3a1d93/resources/images/MergedHeaderSample.gif -------------------------------------------------------------------------------- /resources/images/VirtualBandSample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soomin-kevin-sung/dotnet-flexgrid/9ae4e3da92df84145aa3ed73009820608a3a1d93/resources/images/VirtualBandSample.gif -------------------------------------------------------------------------------- /resources/images/VirtualBandSample_ItemsSource_Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soomin-kevin-sung/dotnet-flexgrid/9ae4e3da92df84145aa3ed73009820608a3a1d93/resources/images/VirtualBandSample_ItemsSource_Image.png -------------------------------------------------------------------------------- /src/KevinComponent.Demo.App/App.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | -------------------------------------------------------------------------------- /src/KevinComponent.Demo.App/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace KevinComponent.Demo.App 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/KevinComponent.Demo.App/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /src/KevinComponent.Demo.App/BindingProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace KevinComponent.Demo.App 9 | { 10 | public class BindingProxy : Freezable 11 | { 12 | #region Dependency Properties 13 | 14 | public static readonly DependencyProperty DataProperty = 15 | DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy)); 16 | 17 | #endregion 18 | 19 | #region Public Properties 20 | 21 | public object Data 22 | { 23 | get => GetValue(DataProperty); 24 | set => SetValue(DataProperty, value); 25 | } 26 | 27 | #endregion 28 | 29 | #region Protected Override Methods 30 | 31 | protected override Freezable CreateInstanceCore() 32 | { 33 | return new BindingProxy(); 34 | } 35 | 36 | #endregion 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/KevinComponent.Demo.App/KevinComponent.Demo.App.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net6.0-windows 6 | enable 7 | true 8 | Build 9 | Debug;Release;GitHub Release 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/KevinComponent.Demo.App/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | 18 | 22 | 23 | 28 | 29 | 30 | 31 |