Repository: MaterialDesignInXAML/MaterialDesignInXamlToolkit Branch: master Commit: bde437426e8a Files: 1176 Total size: 9.6 MB Directory structure: gitextract_uy4cad4e/ ├── .config/ │ └── dotnet-tools.json ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── CONTRIBUTING.md │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yaml │ │ ├── config.yml │ │ └── feature_request.md │ ├── copilot-instructions.md │ ├── dependabot.yml │ ├── release.yml │ └── workflows/ │ ├── build_artifacts.yml │ ├── control_styles.yml │ ├── copilot-setup-steps.yml │ ├── generate_contributors.yml │ ├── get_versions.yml │ ├── icon_update.yml │ ├── nightly_release.yml │ ├── pr_verification.yml │ ├── release.yml │ └── stale_issues_and_prs.yml ├── .gitignore ├── Directory.Build.props ├── Directory.packages.props ├── LICENSE ├── MaterialDesignToolkit.Full.slnx ├── README.md ├── Settings.XamlStyler ├── build/ │ ├── ApplyXamlStyler.ps1 │ ├── BuildNugets.ps1 │ ├── GenerateThemesWikiMarkdown.ps1 │ ├── MigrateBrushes.ps1 │ ├── MigrateStyles.ps1 │ ├── UpdateNugets.ps1 │ └── key.snk ├── docs/ │ ├── Freezable_Object_for_Enhanced_Performance.md │ ├── Optimize_UI_Thread_Performance.md │ ├── Optimizing-WPF-Rendering-Performance.md │ ├── Reducing_Layout_Complexity.md │ └── rendering-performance.md ├── global.json ├── nuget.config ├── src/ │ ├── MahMaterialDragablzMashUp/ │ │ ├── AnotherCommandImplementation.cs │ │ ├── App.config │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Dialogs.xaml │ │ ├── Dialogs.xaml.cs │ │ ├── DialogsViewModel.cs │ │ ├── FlyoutContent.xaml │ │ ├── FlyoutContent.xaml.cs │ │ ├── Mah.xaml │ │ ├── Mah.xaml.cs │ │ ├── MahAppsDragablzDemo.csproj │ │ ├── MahViewModel.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── NotEmptyValidationRule.cs │ │ ├── PaletteSelector.xaml │ │ ├── PaletteSelector.xaml.cs │ │ ├── PaletteSelectorViewModel.cs │ │ ├── Properties/ │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ └── Settings.settings │ │ └── XamlDisplayEx.cs │ ├── MainDemo.Wpf/ │ │ ├── App.config │ │ ├── App.manifest │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── ButtonAssist.cs │ │ ├── Buttons.xaml │ │ ├── Buttons.xaml.cs │ │ ├── Cards.xaml │ │ ├── Cards.xaml.cs │ │ ├── Chips.xaml │ │ ├── Chips.xaml.cs │ │ ├── ColorTool.xaml │ │ ├── ColorTool.xaml.cs │ │ ├── ColorZones.xaml │ │ ├── ColorZones.xaml.cs │ │ ├── ComboBoxes.xaml │ │ ├── ComboBoxes.xaml.cs │ │ ├── CommandLineOptions.cs │ │ ├── DataGrids.xaml │ │ ├── DataGrids.xaml.cs │ │ ├── Dialogs.xaml │ │ ├── Dialogs.xaml.cs │ │ ├── Domain/ │ │ │ ├── DemoItem.cs │ │ │ ├── DialogsViewModel.cs │ │ │ ├── DocumentationLink.cs │ │ │ ├── DocumentationLinkType.cs │ │ │ ├── DocumentationLinks.xaml │ │ │ ├── DocumentationLinks.xaml.cs │ │ │ ├── FieldsViewModel.cs │ │ │ ├── FutureDateValidationRule.cs │ │ │ ├── IconPackViewModel.cs │ │ │ ├── IsCheckedValidationRule.cs │ │ │ ├── Link.cs │ │ │ ├── ListsAndGridsViewModel.cs │ │ │ ├── MainWindowViewModel.cs │ │ │ ├── NotEmptyValidationRule.cs │ │ │ ├── PaletteSelectorViewModel.cs │ │ │ ├── PickersViewModel.cs │ │ │ ├── Sample4Dialog.xaml │ │ │ ├── Sample4Dialog.xaml.cs │ │ │ ├── SampleDialog.xaml │ │ │ ├── SampleDialog.xaml.cs │ │ │ ├── SampleDialogViewModel.cs │ │ │ ├── SampleMessageDialog.xaml │ │ │ ├── SampleMessageDialog.xaml.cs │ │ │ ├── SampleProgressDialog.xaml │ │ │ ├── SampleProgressDialog.xaml.cs │ │ │ ├── SelectableViewModel.cs │ │ │ ├── SimpleDataTemplateSelector.cs │ │ │ ├── SimpleDateValidationRule.cs │ │ │ ├── SlidersViewModel.cs │ │ │ ├── SmartHintViewModel.cs │ │ │ ├── TabsViewModel.cs │ │ │ ├── ThemeSettingsViewModel.cs │ │ │ └── TreesViewModel.cs │ │ ├── Drawers.xaml │ │ ├── Drawers.xaml.cs │ │ ├── Elevation.xaml │ │ ├── Elevation.xaml.cs │ │ ├── Expander.xaml │ │ ├── Expander.xaml.cs │ │ ├── Fields.xaml │ │ ├── Fields.xaml.cs │ │ ├── FieldsLineUp.xaml │ │ ├── FieldsLineUp.xaml.cs │ │ ├── GroupBoxes.xaml │ │ ├── GroupBoxes.xaml.cs │ │ ├── Home.xaml │ │ ├── Home.xaml.cs │ │ ├── IconPack.xaml │ │ ├── IconPack.xaml.cs │ │ ├── InputElementContentControl.cs │ │ ├── Lists.xaml │ │ ├── Lists.xaml.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── MaterialDesignDemo.csproj │ │ ├── MenusAndToolBars.xaml │ │ ├── MenusAndToolBars.xaml.cs │ │ ├── NavigationRail.xaml │ │ ├── NavigationRail.xaml.cs │ │ ├── NumericUpDown.xaml │ │ ├── NumericUpDown.xaml.cs │ │ ├── PackIconKindGroup.cs │ │ ├── Palette.xaml │ │ ├── Palette.xaml.cs │ │ ├── PaletteSelector.xaml │ │ ├── PaletteSelector.xaml.cs │ │ ├── Pickers.xaml │ │ ├── Pickers.xaml.cs │ │ ├── PopupBox.xaml │ │ ├── PopupBox.xaml.cs │ │ ├── Progress.xaml │ │ ├── Progress.xaml.cs │ │ ├── Properties/ │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ ├── Settings.settings │ │ │ └── launchSettings.json │ │ ├── RatingBar.xaml │ │ ├── RatingBar.xaml.cs │ │ ├── Sliders.xaml │ │ ├── Sliders.xaml.cs │ │ ├── SmartHint.xaml │ │ ├── SmartHint.xaml.cs │ │ ├── Snackbars.xaml │ │ ├── Snackbars.xaml.cs │ │ ├── StatusBars.xaml │ │ ├── StatusBars.xaml.cs │ │ ├── Tabs.xaml │ │ ├── Tabs.xaml.cs │ │ ├── ThemeSettings.xaml │ │ ├── ThemeSettings.xaml.cs │ │ ├── Toggles.xaml │ │ ├── Toggles.xaml.cs │ │ ├── ToolTips.xaml │ │ ├── ToolTips.xaml.cs │ │ ├── Transitions.xaml │ │ ├── Transitions.xaml.cs │ │ ├── TransitionsDemo/ │ │ │ ├── Slide1_Intro.xaml │ │ │ ├── Slide1_Intro.xaml.cs │ │ │ ├── Slide2_Intro.xaml │ │ │ ├── Slide2_Intro.xaml.cs │ │ │ ├── Slide3_Intro.xaml │ │ │ ├── Slide3_Intro.xaml.cs │ │ │ ├── Slide4_CombineTransitions.xaml │ │ │ ├── Slide4_CombineTransitions.xaml.cs │ │ │ ├── Slide5_TransitioningContent.xaml │ │ │ ├── Slide5_TransitioningContent.xaml.cs │ │ │ ├── Slide6_Origins.xaml │ │ │ ├── Slide6_Origins.xaml.cs │ │ │ ├── Slide7_MVVM.xaml │ │ │ ├── Slide7_MVVM.xaml.cs │ │ │ ├── Slide7_MasterModel.cs │ │ │ ├── Slide8_Details.xaml │ │ │ ├── Slide8_Details.xaml.cs │ │ │ ├── TransitionsDemoHome.xaml │ │ │ └── TransitionsDemoHome.xaml.cs │ │ ├── Trees.xaml │ │ ├── Trees.xaml.cs │ │ ├── Typography.xaml │ │ ├── Typography.xaml.cs │ │ ├── VisualTreeUtil.cs │ │ └── XamlDisplayEx.cs │ ├── MaterialDesign3.Demo.Wpf/ │ │ ├── App.config │ │ ├── App.manifest │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── ButtonAssist.cs │ │ ├── Buttons.xaml │ │ ├── Buttons.xaml.cs │ │ ├── Cards.xaml │ │ ├── Cards.xaml.cs │ │ ├── Chips.xaml │ │ ├── Chips.xaml.cs │ │ ├── ColorScheme.cs │ │ ├── ColorTool.xaml │ │ ├── ColorTool.xaml.cs │ │ ├── ColorZones.xaml │ │ ├── ColorZones.xaml.cs │ │ ├── ComboBoxes.xaml │ │ ├── ComboBoxes.xaml.cs │ │ ├── DataGrids.xaml │ │ ├── DataGrids.xaml.cs │ │ ├── Dialogs.xaml │ │ ├── Dialogs.xaml.cs │ │ ├── Domain/ │ │ │ ├── AnotherCommandImplementation.cs │ │ │ ├── DemoItem.cs │ │ │ ├── DialogsViewModel.cs │ │ │ ├── DocumentationLink.cs │ │ │ ├── DocumentationLinkType.cs │ │ │ ├── DocumentationLinks.xaml │ │ │ ├── DocumentationLinks.xaml.cs │ │ │ ├── FieldsViewModel.cs │ │ │ ├── FutureDateValidationRule.cs │ │ │ ├── IconPackViewModel.cs │ │ │ ├── IsCheckedValidationRule.cs │ │ │ ├── Link.cs │ │ │ ├── ListsAndGridsViewModel.cs │ │ │ ├── MainWindowViewModel.cs │ │ │ ├── NotEmptyValidationRule.cs │ │ │ ├── PaletteSelectorViewModel.cs │ │ │ ├── PickersViewModel.cs │ │ │ ├── Sample4Dialog.xaml │ │ │ ├── Sample4Dialog.xaml.cs │ │ │ ├── SampleDialog.xaml │ │ │ ├── SampleDialog.xaml.cs │ │ │ ├── SampleDialogViewModel.cs │ │ │ ├── SampleItem.cs │ │ │ ├── SampleMessageDialog.xaml │ │ │ ├── SampleMessageDialog.xaml.cs │ │ │ ├── SampleProgressDialog.xaml │ │ │ ├── SampleProgressDialog.xaml.cs │ │ │ ├── SelectableViewModel.cs │ │ │ ├── SimpleDataTemplateSelector.cs │ │ │ ├── SimpleDateValidationRule.cs │ │ │ ├── SlidersViewModel.cs │ │ │ ├── ThemeSettingsViewModel.cs │ │ │ └── TreesViewModel.cs │ │ ├── Drawers.xaml │ │ ├── Drawers.xaml.cs │ │ ├── Elevation.xaml │ │ ├── Elevation.xaml.cs │ │ ├── Expander.xaml │ │ ├── Expander.xaml.cs │ │ ├── Fields.xaml │ │ ├── Fields.xaml.cs │ │ ├── FieldsLineUp.xaml │ │ ├── FieldsLineUp.xaml.cs │ │ ├── GroupBoxes.xaml │ │ ├── GroupBoxes.xaml.cs │ │ ├── Home.xaml │ │ ├── Home.xaml.cs │ │ ├── IconPack.xaml │ │ ├── IconPack.xaml.cs │ │ ├── Lists.xaml │ │ ├── Lists.xaml.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── MaterialDesign3Demo.csproj │ │ ├── MenusAndToolBars.xaml │ │ ├── MenusAndToolBars.xaml.cs │ │ ├── NavigationBar.xaml │ │ ├── NavigationBar.xaml.cs │ │ ├── NavigationRail.xaml │ │ ├── NavigationRail.xaml.cs │ │ ├── PackIconKindGroup.cs │ │ ├── Palette.xaml │ │ ├── Palette.xaml.cs │ │ ├── PaletteHelperExtensions.cs │ │ ├── PaletteSelector.xaml │ │ ├── PaletteSelector.xaml.cs │ │ ├── Pickers.xaml │ │ ├── Pickers.xaml.cs │ │ ├── Progress.xaml │ │ ├── Progress.xaml.cs │ │ ├── Properties/ │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ ├── Settings.settings │ │ │ └── launchSettings.json │ │ ├── RatingBar.xaml │ │ ├── RatingBar.xaml.cs │ │ ├── Sliders.xaml │ │ ├── Sliders.xaml.cs │ │ ├── Snackbars.xaml │ │ ├── Snackbars.xaml.cs │ │ ├── ThemeSettings.xaml │ │ ├── ThemeSettings.xaml.cs │ │ ├── Toggles.xaml │ │ ├── Toggles.xaml.cs │ │ ├── ToolTips.xaml │ │ ├── ToolTips.xaml.cs │ │ ├── Transitions.xaml │ │ ├── Transitions.xaml.cs │ │ ├── TransitionsDemo/ │ │ │ ├── Slide1_Intro.xaml │ │ │ ├── Slide1_Intro.xaml.cs │ │ │ ├── Slide2_Intro.xaml │ │ │ ├── Slide2_Intro.xaml.cs │ │ │ ├── Slide3_Intro.xaml │ │ │ ├── Slide3_Intro.xaml.cs │ │ │ ├── Slide4_CombineTransitions.xaml │ │ │ ├── Slide4_CombineTransitions.xaml.cs │ │ │ ├── Slide5_TransitioningContent.xaml │ │ │ ├── Slide5_TransitioningContent.xaml.cs │ │ │ ├── Slide6_Origins.xaml │ │ │ ├── Slide6_Origins.xaml.cs │ │ │ ├── Slide7_MVVM.xaml │ │ │ ├── Slide7_MVVM.xaml.cs │ │ │ ├── Slide7_MasterModel.cs │ │ │ ├── Slide8_Details.xaml │ │ │ ├── Slide8_Details.xaml.cs │ │ │ ├── TransitionsDemoHome.xaml │ │ │ └── TransitionsDemoHome.xaml.cs │ │ ├── Trees.xaml │ │ ├── Trees.xaml.cs │ │ ├── Typography.xaml │ │ ├── Typography.xaml.cs │ │ └── XamlDisplayEx.cs │ ├── MaterialDesign3.MaterialColorUtilities/ │ │ ├── Blend/ │ │ │ └── Blend.cs │ │ ├── Contrast/ │ │ │ └── Contrast.cs │ │ ├── Dislike/ │ │ │ └── DislikeAnalyzer.cs │ │ ├── DynamicColor/ │ │ │ ├── ColorSpec.cs │ │ │ ├── ColorSpec2021.cs │ │ │ ├── ColorSpec2025.cs │ │ │ ├── ColorSpecs.cs │ │ │ ├── ContrastCurve.cs │ │ │ ├── DeltaConstraint.cs │ │ │ ├── DynamicColor.cs │ │ │ ├── DynamicScheme.cs │ │ │ ├── MaterialDynamicColors.cs │ │ │ ├── Platform.cs │ │ │ ├── SpecVersion.cs │ │ │ ├── ToneDeltaPair.cs │ │ │ ├── TonePolarity.cs │ │ │ └── Variant.cs │ │ ├── Hct/ │ │ │ ├── Cam16.cs │ │ │ ├── Hct.cs │ │ │ ├── HctSolver.cs │ │ │ └── ViewingConditions.cs │ │ ├── MaterialColorUtilities.csproj │ │ ├── Palettes/ │ │ │ ├── CorePalette.cs │ │ │ ├── CorePalettes.cs │ │ │ └── TonalPalette.cs │ │ ├── Quantize/ │ │ │ ├── PointProvider.cs │ │ │ ├── PointProviderLab.cs │ │ │ ├── Quantizer.cs │ │ │ ├── QuantizerCelebi.cs │ │ │ ├── QuantizerMap.cs │ │ │ ├── QuantizerResult.cs │ │ │ ├── QuantizerWsmeans.cs │ │ │ └── QuantizerWu.cs │ │ ├── Scheme/ │ │ │ ├── DynamicSchemeFactory.cs │ │ │ ├── Scheme.cs │ │ │ ├── SchemeContent.cs │ │ │ ├── SchemeExpressive.cs │ │ │ ├── SchemeFidelity.cs │ │ │ ├── SchemeFruitSalad.cs │ │ │ ├── SchemeMonochrome.cs │ │ │ ├── SchemeNeutral.cs │ │ │ ├── SchemeRainbow.cs │ │ │ ├── SchemeTonalSpot.cs │ │ │ └── SchemeVibrant.cs │ │ ├── Score/ │ │ │ └── Score.cs │ │ ├── Temperature/ │ │ │ └── TemperatureCache.cs │ │ └── Utils/ │ │ ├── ColorUtils.cs │ │ ├── MathUtils.cs │ │ └── StringUtils.cs │ ├── MaterialDesign3.Motion/ │ │ ├── AnimationEndReason.cs │ │ ├── AnimationParameters.cs │ │ ├── AnimationSpec.cs │ │ ├── AnimationVector.cs │ │ ├── AnimationVector1D.cs │ │ ├── AnimationVector2D.cs │ │ ├── AnimationVector3D.cs │ │ ├── AnimationVector4D.cs │ │ ├── AnimationVectorExtensions.cs │ │ ├── AnimationVectorFactory.cs │ │ ├── ArcSpline.cs │ │ ├── CubicBezierEasing.cs │ │ ├── Easing.cs │ │ ├── Hermite.cs │ │ ├── IMotionScheme.cs │ │ ├── ITwoWayConverter.cs │ │ ├── MonoSpline.cs │ │ ├── Motion.cs │ │ ├── Motion.csproj │ │ ├── Motion.md │ │ ├── MotionSchemeContext.cs │ │ ├── MotionSchemeExtensions.cs │ │ ├── MotionSchemeKeyTokenExtensions.cs │ │ ├── MotionSchemeKeyTokens.cs │ │ ├── MotionSchemes.cs │ │ ├── MotionTokens.cs │ │ ├── Preconditions.cs │ │ ├── RepeatMode.cs │ │ ├── Repeatable.cs │ │ ├── SpringConstants.cs │ │ ├── SpringEstimation.cs │ │ ├── SpringMotionSpec.cs │ │ ├── SpringSimulation.cs │ │ ├── TwoWayConverter.cs │ │ └── VectorConverters.cs │ ├── MaterialDesignColors.Wpf/ │ │ ├── ColorManipulation/ │ │ │ ├── ColorAssist.cs │ │ │ ├── Hsb.cs │ │ │ ├── HsbExtensions.cs │ │ │ ├── Hsl.cs │ │ │ ├── HslExtensions.cs │ │ │ ├── Lab.cs │ │ │ ├── LabExtensions.cs │ │ │ ├── Xyz.cs │ │ │ └── XyzExtensions.cs │ │ ├── ColorPair.cs │ │ ├── Hue.cs │ │ ├── ISwatch.cs │ │ ├── MaterialDesignColor.cs │ │ ├── MaterialDesignColors.Wpf.csproj │ │ ├── MaterialDesignColors.nuspec │ │ ├── Properties/ │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ └── Settings.settings │ │ ├── Recommended/ │ │ │ ├── AmberSwatch.cs │ │ │ ├── BlueGreySwatch.cs │ │ │ ├── BlueSwatch.cs │ │ │ ├── BrownSwatch.cs │ │ │ ├── CyanSwatch.cs │ │ │ ├── DeepOrangeSwatch.cs │ │ │ ├── DeepPurpleSwatch.cs │ │ │ ├── GreenSwatch.cs │ │ │ ├── GreySwatch.cs │ │ │ ├── IndigoSwatch.cs │ │ │ ├── LightBlueSwatch.cs │ │ │ ├── LightGreenSwatch.cs │ │ │ ├── LimeSwatch.cs │ │ │ ├── OrangeSwatch.cs │ │ │ ├── PinkSwatch.cs │ │ │ ├── PurpleSwatch.cs │ │ │ ├── RedSwatch.cs │ │ │ ├── TealSwatch.cs │ │ │ └── YellowSwatch.cs │ │ ├── StaticResourceExtension.cs │ │ ├── Swatch.cs │ │ ├── SwatchHelper.cs │ │ ├── SwatchesProvider.cs │ │ └── Themes/ │ │ ├── MaterialDesignColor.Amber.Named.Primary.xaml │ │ ├── MaterialDesignColor.Amber.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Amber.Named.xaml │ │ ├── MaterialDesignColor.Amber.Primary.xaml │ │ ├── MaterialDesignColor.Amber.Secondary.xaml │ │ ├── MaterialDesignColor.Amber.xaml │ │ ├── MaterialDesignColor.Blue.Named.Primary.xaml │ │ ├── MaterialDesignColor.Blue.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Blue.Named.xaml │ │ ├── MaterialDesignColor.Blue.Primary.xaml │ │ ├── MaterialDesignColor.Blue.Secondary.xaml │ │ ├── MaterialDesignColor.Blue.xaml │ │ ├── MaterialDesignColor.BlueGrey.Named.Primary.xaml │ │ ├── MaterialDesignColor.BlueGrey.Named.xaml │ │ ├── MaterialDesignColor.BlueGrey.Primary.xaml │ │ ├── MaterialDesignColor.BlueGrey.xaml │ │ ├── MaterialDesignColor.Brown.Named.Primary.xaml │ │ ├── MaterialDesignColor.Brown.Named.xaml │ │ ├── MaterialDesignColor.Brown.Primary.xaml │ │ ├── MaterialDesignColor.Brown.xaml │ │ ├── MaterialDesignColor.Cyan.Named.Primary.xaml │ │ ├── MaterialDesignColor.Cyan.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Cyan.Named.xaml │ │ ├── MaterialDesignColor.Cyan.Primary.xaml │ │ ├── MaterialDesignColor.Cyan.Secondary.xaml │ │ ├── MaterialDesignColor.Cyan.xaml │ │ ├── MaterialDesignColor.DeepOrange.Named.Primary.xaml │ │ ├── MaterialDesignColor.DeepOrange.Named.Secondary.xaml │ │ ├── MaterialDesignColor.DeepOrange.Named.xaml │ │ ├── MaterialDesignColor.DeepOrange.Primary.xaml │ │ ├── MaterialDesignColor.DeepOrange.Secondary.xaml │ │ ├── MaterialDesignColor.DeepOrange.xaml │ │ ├── MaterialDesignColor.DeepPurple.Named.Primary.xaml │ │ ├── MaterialDesignColor.DeepPurple.Named.Secondary.xaml │ │ ├── MaterialDesignColor.DeepPurple.Named.xaml │ │ ├── MaterialDesignColor.DeepPurple.Primary.xaml │ │ ├── MaterialDesignColor.DeepPurple.Secondary.xaml │ │ ├── MaterialDesignColor.DeepPurple.xaml │ │ ├── MaterialDesignColor.Green.Named.Primary.xaml │ │ ├── MaterialDesignColor.Green.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Green.Named.xaml │ │ ├── MaterialDesignColor.Green.Primary.xaml │ │ ├── MaterialDesignColor.Green.Secondary.xaml │ │ ├── MaterialDesignColor.Green.xaml │ │ ├── MaterialDesignColor.Grey.Named.Primary.xaml │ │ ├── MaterialDesignColor.Grey.Named.xaml │ │ ├── MaterialDesignColor.Grey.Primary.xaml │ │ ├── MaterialDesignColor.Grey.xaml │ │ ├── MaterialDesignColor.Indigo.Named.Primary.xaml │ │ ├── MaterialDesignColor.Indigo.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Indigo.Named.xaml │ │ ├── MaterialDesignColor.Indigo.Primary.xaml │ │ ├── MaterialDesignColor.Indigo.Secondary.xaml │ │ ├── MaterialDesignColor.Indigo.xaml │ │ ├── MaterialDesignColor.LightBlue.Named.Primary.xaml │ │ ├── MaterialDesignColor.LightBlue.Named.Secondary.xaml │ │ ├── MaterialDesignColor.LightBlue.Named.xaml │ │ ├── MaterialDesignColor.LightBlue.Primary.xaml │ │ ├── MaterialDesignColor.LightBlue.Secondary.xaml │ │ ├── MaterialDesignColor.LightBlue.xaml │ │ ├── MaterialDesignColor.LightGreen.Named.Primary.xaml │ │ ├── MaterialDesignColor.LightGreen.Named.Secondary.xaml │ │ ├── MaterialDesignColor.LightGreen.Named.xaml │ │ ├── MaterialDesignColor.LightGreen.Primary.xaml │ │ ├── MaterialDesignColor.LightGreen.Secondary.xaml │ │ ├── MaterialDesignColor.LightGreen.xaml │ │ ├── MaterialDesignColor.Lime.Named.Primary.xaml │ │ ├── MaterialDesignColor.Lime.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Lime.Named.xaml │ │ ├── MaterialDesignColor.Lime.Primary.xaml │ │ ├── MaterialDesignColor.Lime.Secondary.xaml │ │ ├── MaterialDesignColor.Lime.xaml │ │ ├── MaterialDesignColor.Orange.Named.Primary.xaml │ │ ├── MaterialDesignColor.Orange.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Orange.Named.xaml │ │ ├── MaterialDesignColor.Orange.Primary.xaml │ │ ├── MaterialDesignColor.Orange.Secondary.xaml │ │ ├── MaterialDesignColor.Orange.xaml │ │ ├── MaterialDesignColor.Pink.Named.Primary.xaml │ │ ├── MaterialDesignColor.Pink.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Pink.Named.xaml │ │ ├── MaterialDesignColor.Pink.Primary.xaml │ │ ├── MaterialDesignColor.Pink.Secondary.xaml │ │ ├── MaterialDesignColor.Pink.xaml │ │ ├── MaterialDesignColor.Purple.Named.Primary.xaml │ │ ├── MaterialDesignColor.Purple.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Purple.Named.xaml │ │ ├── MaterialDesignColor.Purple.Primary.xaml │ │ ├── MaterialDesignColor.Purple.Secondary.xaml │ │ ├── MaterialDesignColor.Purple.xaml │ │ ├── MaterialDesignColor.Red.Named.Primary.xaml │ │ ├── MaterialDesignColor.Red.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Red.Named.xaml │ │ ├── MaterialDesignColor.Red.Primary.xaml │ │ ├── MaterialDesignColor.Red.Secondary.xaml │ │ ├── MaterialDesignColor.Red.xaml │ │ ├── MaterialDesignColor.Teal.Named.Primary.xaml │ │ ├── MaterialDesignColor.Teal.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Teal.Named.xaml │ │ ├── MaterialDesignColor.Teal.Primary.xaml │ │ ├── MaterialDesignColor.Teal.Secondary.xaml │ │ ├── MaterialDesignColor.Teal.xaml │ │ ├── MaterialDesignColor.Yellow.Named.Primary.xaml │ │ ├── MaterialDesignColor.Yellow.Named.Secondary.xaml │ │ ├── MaterialDesignColor.Yellow.Named.xaml │ │ ├── MaterialDesignColor.Yellow.Primary.xaml │ │ ├── MaterialDesignColor.Yellow.Secondary.xaml │ │ ├── MaterialDesignColor.Yellow.xaml │ │ └── Recommended/ │ │ ├── Primary/ │ │ │ ├── MaterialDesignColor.Amber.xaml │ │ │ ├── MaterialDesignColor.Blue.xaml │ │ │ ├── MaterialDesignColor.BlueGrey.xaml │ │ │ ├── MaterialDesignColor.Brown.xaml │ │ │ ├── MaterialDesignColor.Cyan.xaml │ │ │ ├── MaterialDesignColor.DeepOrange.xaml │ │ │ ├── MaterialDesignColor.DeepPurple.xaml │ │ │ ├── MaterialDesignColor.Green.xaml │ │ │ ├── MaterialDesignColor.Grey.xaml │ │ │ ├── MaterialDesignColor.Indigo.xaml │ │ │ ├── MaterialDesignColor.LightBlue.xaml │ │ │ ├── MaterialDesignColor.LightGreen.xaml │ │ │ ├── MaterialDesignColor.Lime.xaml │ │ │ ├── MaterialDesignColor.Orange.xaml │ │ │ ├── MaterialDesignColor.Pink.xaml │ │ │ ├── MaterialDesignColor.Purple.xaml │ │ │ ├── MaterialDesignColor.Red.xaml │ │ │ ├── MaterialDesignColor.Teal.xaml │ │ │ └── MaterialDesignColor.Yellow.xaml │ │ └── Secondary/ │ │ ├── MaterialDesignColor.Amber.xaml │ │ ├── MaterialDesignColor.Blue.xaml │ │ ├── MaterialDesignColor.Cyan.xaml │ │ ├── MaterialDesignColor.DeepOrange.xaml │ │ ├── MaterialDesignColor.DeepPurple.xaml │ │ ├── MaterialDesignColor.Green.xaml │ │ ├── MaterialDesignColor.Indigo.xaml │ │ ├── MaterialDesignColor.LightBlue.xaml │ │ ├── MaterialDesignColor.LightGreen.xaml │ │ ├── MaterialDesignColor.Lime.xaml │ │ ├── MaterialDesignColor.Orange.xaml │ │ ├── MaterialDesignColor.Pink.xaml │ │ ├── MaterialDesignColor.Purple.xaml │ │ ├── MaterialDesignColor.Red.xaml │ │ ├── MaterialDesignColor.Teal.xaml │ │ └── MaterialDesignColor.Yellow.xaml │ ├── MaterialDesignDemo.Shared/ │ │ ├── ColorScheme.cs │ │ ├── Converters/ │ │ │ ├── BoolToTextWrappingConverter.cs │ │ │ ├── BooleanToDoubleConverter.cs │ │ │ ├── BrushToHexConverter.cs │ │ │ ├── ColorToBrushConverter.cs │ │ │ ├── IsTransparentConverter.cs │ │ │ ├── MultiValueEqualityConverter.cs │ │ │ └── StringJoinConverter.cs │ │ ├── Domain/ │ │ │ ├── AnotherCommandImplementation.cs │ │ │ ├── ButtonsViewModel.cs │ │ │ ├── ColorToolViewModel.cs │ │ │ ├── ComboBoxesViewModel.cs │ │ │ ├── ToolTipsViewModel.cs │ │ │ └── ViewModelBase.cs │ │ ├── MaterialDesignDemo.Shared.csproj │ │ └── PaletteHelperExtensions.cs │ ├── MaterialDesignThemes.MahApps/ │ │ ├── BaseThemeExtensions.cs │ │ ├── FlyoutAssist.cs │ │ ├── MahAppsBundledTheme.cs │ │ ├── MahAppsCustomColorTheme.cs │ │ ├── MaterialDesignAssist.cs │ │ ├── MaterialDesignThemes.MahApps.csproj │ │ ├── MaterialDesignThemes.MahApps.nuspec │ │ ├── Properties/ │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ └── Settings.settings │ │ └── Themes/ │ │ ├── MaterialDesignTheme.MahApps.Defaults.xaml │ │ ├── MaterialDesignTheme.MahApps.Dialogs.xaml │ │ ├── MaterialDesignTheme.MahApps.Flyout.xaml │ │ ├── MaterialDesignTheme.MahApps.Fonts.xaml │ │ ├── MaterialDesignTheme.MahApps.NumericUpDown.xaml │ │ ├── MaterialDesignTheme.MahApps.PasswordBox.xaml │ │ ├── MaterialDesignTheme.MahApps.RangeSlider.xaml │ │ ├── MaterialDesignTheme.MahApps.TextBox.xaml │ │ └── MaterialDesignTheme.MahApps.WindowCommands.xaml │ ├── MaterialDesignThemes.Wpf/ │ │ ├── AdornerExtensions.cs │ │ ├── AutoSuggestBox.cs │ │ ├── Automation/ │ │ │ └── Peers/ │ │ │ └── TreeListViewItemAutomationPeer.cs │ │ ├── Badged.cs │ │ ├── BadgedAssist.cs │ │ ├── BaseTheme.cs │ │ ├── BehaviorCollection.cs │ │ ├── Behaviors/ │ │ │ ├── Internal/ │ │ │ │ ├── TabControlHeaderScrollBehavior.cs │ │ │ │ └── TextBoxHorizontalScrollBarBehavior.cs │ │ │ ├── PasswordBoxBehavior.cs │ │ │ ├── PasswordBoxRevealTextBoxBehavior.cs │ │ │ ├── SmartHintBehavior.cs │ │ │ └── TextBoxLineCountBehavior.cs │ │ ├── BehaviorsAssist.cs │ │ ├── BottomDashedLineAdorner.cs │ │ ├── BundledTheme.cs │ │ ├── ButtonAssist.cs │ │ ├── ButtonProgressAssist.cs │ │ ├── CalendarAssist.cs │ │ ├── CalendarFormatInfo.cs │ │ ├── Card.cs │ │ ├── CheckBoxAssist.cs │ │ ├── Chip.cs │ │ ├── Clock.cs │ │ ├── ClockChoiceMadeEventArgs.cs │ │ ├── ClockItemButton.cs │ │ ├── ColorAdjustment.cs │ │ ├── ColorPicker.cs │ │ ├── ColorReference.cs │ │ ├── ColorSelection.cs │ │ ├── ColorZone.cs │ │ ├── ColorZoneAssist.cs │ │ ├── ColorZoneMode.cs │ │ ├── ComboBoxAssist.cs │ │ ├── ComboBoxPopup.cs │ │ ├── Constants.cs │ │ ├── Contrast.cs │ │ ├── Converters/ │ │ │ ├── BooleanAllConverter.cs │ │ │ ├── BooleanConverter.cs │ │ │ ├── BooleanToDashStyleConverter.cs │ │ │ ├── BooleanToVisibilityConverter.cs │ │ │ ├── BorderClipConverter.cs │ │ │ ├── BrushOpacityConverter.cs │ │ │ ├── BrushRoundConverter.cs │ │ │ ├── BrushToRadialGradientBrushConverter.cs │ │ │ ├── CalendarDateCoalesceConverter.cs │ │ │ ├── CalendarYearMonthConverter.cs │ │ │ ├── CircularProgressBar/ │ │ │ │ ├── ArcEndPointConverter.cs │ │ │ │ ├── ArcSizeConverter.cs │ │ │ │ ├── LocalEx.cs │ │ │ │ ├── RotateTransformCentreConverter.cs │ │ │ │ └── StartPointConverter.cs │ │ │ ├── ClockItemIsCheckedConverter.cs │ │ │ ├── ClockLineConverter.cs │ │ │ ├── CornerRadiusCloneConverter.cs │ │ │ ├── CursorConverter.cs │ │ │ ├── DrawerOffsetConverter.cs │ │ │ ├── ElevationMarginConverter.cs │ │ │ ├── ElevationRadiusConverter.cs │ │ │ ├── EllipseClipConverter.cs │ │ │ ├── EqualityToVisibilityConverter.cs │ │ │ ├── FallbackBrushConverter.cs │ │ │ ├── FirstNonNullConverter.cs │ │ │ ├── FloatingHintClippingGridConverter.cs │ │ │ ├── FloatingHintContainerMarginConverter.cs │ │ │ ├── FloatingHintInitialHorizontalOffsetConverter.cs │ │ │ ├── FloatingHintInitialVerticalOffsetConverter.cs │ │ │ ├── FloatingHintMarginConverter.cs │ │ │ ├── FloatingHintScaleTransformConverter.cs │ │ │ ├── FloatingHintTranslateTransformConverter.cs │ │ │ ├── GridLinesVisibilityBorderToThicknessConverter.cs │ │ │ ├── HintProxyFabricConverter.cs │ │ │ ├── HorizontalThicknessConverter.cs │ │ │ ├── HsbLinearGradientConverter.cs │ │ │ ├── HsbToColorConverter.cs │ │ │ ├── Internal/ │ │ │ │ ├── AutomationPropertiesNameConverter.cs │ │ │ │ ├── DialogBackgroundBlurConverter.cs │ │ │ │ ├── DoubleToCornerRadiusConverter.cs │ │ │ │ ├── ExpanderRotateAngleConverter.cs │ │ │ │ ├── FloatingHintTextBlockMarginConverter.cs │ │ │ │ ├── GridViewHasColumnsConverter.cs │ │ │ │ ├── SliderToolTipConverter.cs │ │ │ │ ├── SliderValueLabelPositionConverter.cs │ │ │ │ ├── TextBoxHorizontalScrollBarMarginConverter.cs │ │ │ │ ├── TextBoxHorizontalScrollBarWidthConverter.cs │ │ │ │ ├── TextFieldClearButtonVisibilityConverter.cs │ │ │ │ └── ViewIsGridViewConverter.cs │ │ │ ├── InvertBooleanConverter.cs │ │ │ ├── IsDarkConverter.cs │ │ │ ├── IsTransparentBrushConverter.cs │ │ │ ├── ListViewItemContainerStyleConverter.cs │ │ │ ├── MathConverter.cs │ │ │ ├── MathMultipleConverter.cs │ │ │ ├── MathOperation.cs │ │ │ ├── NonDefaultThicknessConverter.cs │ │ │ ├── NotConverter.cs │ │ │ ├── NotZeroConverter.cs │ │ │ ├── NotZeroToVisibilityConverter.cs │ │ │ ├── NullableDateTimeToCurrentDateConverter.cs │ │ │ ├── NullableToVisibilityConverter.cs │ │ │ ├── OutlinedDateTimePickerActiveBorderThicknessConverter.cs │ │ │ ├── OutlinedStyleActiveBorderMarginCompensationConverter.cs │ │ │ ├── OutlinedStyleFloatingHintBackgroundConverter.cs │ │ │ ├── PointValueConverter.cs │ │ │ ├── RangeLengthConverter.cs │ │ │ ├── RemoveAlphaBrushConverter.cs │ │ │ ├── ShadowConverter.cs │ │ │ ├── ShadowOpacityMaskConverter.cs │ │ │ ├── SnackbarActionButtonPlacementModeConverter.cs │ │ │ ├── SnackbarMessageTypeConverter.cs │ │ │ ├── StringLengthValueConverter.cs │ │ │ ├── TextFieldHintVisibilityConverter.cs │ │ │ ├── TextFieldPrefixTextVisibilityConverter.cs │ │ │ ├── ThicknessCloneConverter.cs │ │ │ ├── TimeToVisibilityConverter.cs │ │ │ ├── ToolBarOverflowButtonVisibilityConverter.cs │ │ │ ├── TopThicknessConverter.cs │ │ │ ├── TreeListViewIndentConverter.cs │ │ │ └── VerticalAlignmentConverter.cs │ │ ├── CustomColorTheme.cs │ │ ├── CustomPopupPlacementCallbackHelper.cs │ │ ├── DataGridAssist.cs │ │ ├── DataGridComboBoxColumn.cs │ │ ├── DataGridTextColumn.cs │ │ ├── DatePickerAssist.cs │ │ ├── DateTimeEx.cs │ │ ├── DecimalUpDown.cs │ │ ├── DialogClosedEventArgs.cs │ │ ├── DialogClosedEventHandler.cs │ │ ├── DialogClosingEventArgs.cs │ │ ├── DialogClosingEventHandler.cs │ │ ├── DialogHost.cs │ │ ├── DialogHostEx.cs │ │ ├── DialogOpenedEventArgs.cs │ │ ├── DialogOpenedEventHandler.cs │ │ ├── DialogSession.cs │ │ ├── DpiHelper.cs │ │ ├── DrawerClosingEventArgs.cs │ │ ├── DrawerHost.cs │ │ ├── DrawerHostOpenMode.cs │ │ ├── DrawerOpenedEventArgs.cs │ │ ├── ElevationAssist.cs │ │ ├── ExpanderAssist.cs │ │ ├── Flipper.cs │ │ ├── FlipperAssist.cs │ │ ├── FlipperClassic.cs │ │ ├── FloatingHintHorizontalAlignment.cs │ │ ├── GridViewColumnThumb.cs │ │ ├── GroupBoxAssist.cs │ │ ├── HintAssist.cs │ │ ├── HintProxyFabric.ComboBox.cs │ │ ├── HintProxyFabric.PasswordBox.cs │ │ ├── HintProxyFabric.RichTextBox.cs │ │ ├── HintProxyFabric.TextBox.cs │ │ ├── HintProxyFabric.cs │ │ ├── IHintProxy.cs │ │ ├── IMaterialDesignThemeDictionary.cs │ │ ├── ISnackbarMessageQueue.cs │ │ ├── IThemeManager.cs │ │ ├── InheritSystemColorTypeConverter.cs │ │ ├── Internal/ │ │ │ ├── ClearText.cs │ │ │ ├── InternalTextFieldAssist.cs │ │ │ ├── PaddedBringIntoViewStackPanel.cs │ │ │ ├── Shims/ │ │ │ │ ├── Index.cs │ │ │ │ └── NotNullWhen.cs │ │ │ ├── TreeListViewContentPresenter.cs │ │ │ └── TreeListViewItemsCollection.cs │ │ ├── ListBoxAssist.cs │ │ ├── ListBoxItemAssist.cs │ │ ├── ListSortDirectionIndicator.cs │ │ ├── ListViewAssist.cs │ │ ├── MaterialDateDisplay.cs │ │ ├── MaterialDesignFont.cs │ │ ├── MaterialDesignThemes.Wpf.csproj │ │ ├── MaterialDesignThemes.nuspec │ │ ├── MaterialDesignThemes.targets │ │ ├── MenuAssist.cs │ │ ├── MenuItemAssist.cs │ │ ├── MessageQueueExtension.cs │ │ ├── NavigationBarAssist.cs │ │ ├── NavigationDrawerAssist.cs │ │ ├── NavigationRailAssist.cs │ │ ├── NotoFontExtension.cs │ │ ├── NumericUpDown.cs │ │ ├── PackIcon.cs │ │ ├── PackIconDataFactory.cs │ │ ├── PackIconExtension.cs │ │ ├── PackIconKind.cs │ │ ├── PaddingMode.cs │ │ ├── Palette.cs │ │ ├── PaletteHelper.cs │ │ ├── PasswordBoxAssist.cs │ │ ├── Plane3D.cs │ │ ├── PopupBox.cs │ │ ├── PopupEx.cs │ │ ├── PrefixSuffixHintBehavior.cs │ │ ├── PrefixSuffixVisibility.cs │ │ ├── Properties/ │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ └── Settings.settings │ │ ├── RadioButtonAssist.cs │ │ ├── RatingBar.cs │ │ ├── RatingBarButton.cs │ │ ├── ResourceDictionaryExtensions.cs │ │ ├── ResourceDictionaryExtensions.g.cs │ │ ├── Resources/ │ │ │ └── Noto/ │ │ │ └── OFL.txt │ │ ├── Ripple.cs │ │ ├── RippleAssist.cs │ │ ├── RobotoFontExtension.cs │ │ ├── ScaleHelper.cs │ │ ├── ScaleHost.cs │ │ ├── Screen.cs │ │ ├── ScrollViewerAssist.cs │ │ ├── ScrollbarAssist.cs │ │ ├── ShadowAssist.cs │ │ ├── SliderAssist.cs │ │ ├── SmartHint.cs │ │ ├── Snackbar.cs │ │ ├── SnackbarMessage.cs │ │ ├── SnackbarMessageEventArgs.cs │ │ ├── SnackbarMessageQueue.cs │ │ ├── SnackbarMessageQueueItem.cs │ │ ├── Spelling.cs │ │ ├── SplitButton.cs │ │ ├── StringExtensions.cs │ │ ├── TabAssist.cs │ │ ├── TextBlockAssist.cs │ │ ├── TextFieldAssist.cs │ │ ├── Theme.cs │ │ ├── Theme.g.cs │ │ ├── ThemeAssist.cs │ │ ├── ThemeChangedEventArgs.cs │ │ ├── ThemeColorReference.cs │ │ ├── ThemeExtensions.cs │ │ ├── ThemeExtensions.g.cs │ │ ├── Themes/ │ │ │ ├── Generic.xaml │ │ │ ├── Internal/ │ │ │ │ ├── BaseThemeColors.cs │ │ │ │ └── MaterialDesignTheme.BaseThemeColors.xaml │ │ │ ├── MaterialDesign2.Defaults.xaml │ │ │ ├── MaterialDesign3.Defaults.xaml │ │ │ ├── MaterialDesign3.Font.xaml │ │ │ ├── MaterialDesign3.NavigationBar.xaml │ │ │ ├── MaterialDesign3.NavigationDrawer.xaml │ │ │ ├── MaterialDesign3.NavigationRail.xaml │ │ │ ├── MaterialDesign3.Slider.xaml │ │ │ ├── MaterialDesign3.TextBlock.xaml │ │ │ ├── MaterialDesign3.ToggleButton.xaml │ │ │ ├── MaterialDesign3.Window.xaml │ │ │ ├── MaterialDesignTheme.AutoSuggestBox.xaml │ │ │ ├── MaterialDesignTheme.Badged.xaml │ │ │ ├── MaterialDesignTheme.Button.xaml │ │ │ ├── MaterialDesignTheme.Calendar.xaml │ │ │ ├── MaterialDesignTheme.Card.xaml │ │ │ ├── MaterialDesignTheme.CheckBox.xaml │ │ │ ├── MaterialDesignTheme.Chip.xaml │ │ │ ├── MaterialDesignTheme.Clock.xaml │ │ │ ├── MaterialDesignTheme.ColorPicker.xaml │ │ │ ├── MaterialDesignTheme.ComboBox.xaml │ │ │ ├── MaterialDesignTheme.Dark.xaml │ │ │ ├── MaterialDesignTheme.DataGrid.ComboBox.xaml │ │ │ ├── MaterialDesignTheme.DataGrid.xaml │ │ │ ├── MaterialDesignTheme.DatePicker.xaml │ │ │ ├── MaterialDesignTheme.DialogHost.xaml │ │ │ ├── MaterialDesignTheme.Expander.xaml │ │ │ ├── MaterialDesignTheme.Flipper.xaml │ │ │ ├── MaterialDesignTheme.FlipperClassic.xaml │ │ │ ├── MaterialDesignTheme.Font.xaml │ │ │ ├── MaterialDesignTheme.GridSplitter.xaml │ │ │ ├── MaterialDesignTheme.GroupBox.xaml │ │ │ ├── MaterialDesignTheme.Hyperlink.xaml │ │ │ ├── MaterialDesignTheme.Label.xaml │ │ │ ├── MaterialDesignTheme.Light.xaml │ │ │ ├── MaterialDesignTheme.ListBox.xaml │ │ │ ├── MaterialDesignTheme.ListView.xaml │ │ │ ├── MaterialDesignTheme.Menu.xaml │ │ │ ├── MaterialDesignTheme.NumericUpDown.xaml │ │ │ ├── MaterialDesignTheme.ObsoleteBrushes.xaml │ │ │ ├── MaterialDesignTheme.ObsoleteStyles.xaml │ │ │ ├── MaterialDesignTheme.PasswordBox.xaml │ │ │ ├── MaterialDesignTheme.PopupBox.xaml │ │ │ ├── MaterialDesignTheme.ProgressBar.xaml │ │ │ ├── MaterialDesignTheme.RadioButton.xaml │ │ │ ├── MaterialDesignTheme.RatingBar.xaml │ │ │ ├── MaterialDesignTheme.RichTextBox.xaml │ │ │ ├── MaterialDesignTheme.ScrollBar.xaml │ │ │ ├── MaterialDesignTheme.ScrollViewer.xaml │ │ │ ├── MaterialDesignTheme.Separator.xaml │ │ │ ├── MaterialDesignTheme.Shadows.xaml │ │ │ ├── MaterialDesignTheme.Slider.xaml │ │ │ ├── MaterialDesignTheme.SmartHint.xaml │ │ │ ├── MaterialDesignTheme.Snackbar.xaml │ │ │ ├── MaterialDesignTheme.SplitButton.xaml │ │ │ ├── MaterialDesignTheme.StatusBar.xaml │ │ │ ├── MaterialDesignTheme.TabControl.xaml │ │ │ ├── MaterialDesignTheme.TextBlock.xaml │ │ │ ├── MaterialDesignTheme.TextBox.xaml │ │ │ ├── MaterialDesignTheme.Thumb.xaml │ │ │ ├── MaterialDesignTheme.TimePicker.xaml │ │ │ ├── MaterialDesignTheme.ToggleButton.xaml │ │ │ ├── MaterialDesignTheme.ToolBar.xaml │ │ │ ├── MaterialDesignTheme.ToolBarTray.xaml │ │ │ ├── MaterialDesignTheme.ToolTip.xaml │ │ │ ├── MaterialDesignTheme.TreeListView.xaml │ │ │ ├── MaterialDesignTheme.TreeView.xaml │ │ │ ├── MaterialDesignTheme.ValidationErrorTemplate.xaml │ │ │ ├── MaterialDesignTheme.Window.xaml │ │ │ └── ObsoleteConverters.xaml │ │ ├── TimeChangedEventArgs.cs │ │ ├── TimePicker.cs │ │ ├── TimePickerAssist.cs │ │ ├── TimePickerTextBox.cs │ │ ├── ToggleButtonAssist.cs │ │ ├── ToolTipAssist.cs │ │ ├── TransitionAssist.cs │ │ ├── Transitions/ │ │ │ ├── CircleWipe.cs │ │ │ ├── FadeWipe.cs │ │ │ ├── ITransitionEffect.cs │ │ │ ├── ITransitionEffectSubject.cs │ │ │ ├── ITransitionWipe.cs │ │ │ ├── IZIndexController.cs │ │ │ ├── IndexedItemOffsetMultiplierExtension.cs │ │ │ ├── SlideDirection.cs │ │ │ ├── SlideOutWipe.cs │ │ │ ├── SlideWipe.cs │ │ │ ├── TransitionEffect.cs │ │ │ ├── TransitionEffectBase.cs │ │ │ ├── TransitionEffectExtension.cs │ │ │ ├── TransitionEffectKind.cs │ │ │ ├── TransitionEffectTypeConverter.cs │ │ │ ├── Transitioner.cs │ │ │ ├── TransitionerSlide.cs │ │ │ ├── TransitionerSlideState.cs │ │ │ ├── TransitioningContent.cs │ │ │ └── TransitioningContentBase.cs │ │ ├── TreeHelper.cs │ │ ├── TreeListView.cs │ │ ├── TreeListViewItem.cs │ │ ├── TreeViewAssist.cs │ │ ├── Underline.cs │ │ ├── UpDownBase.cs │ │ ├── ValidationAssist.cs │ │ ├── VisualStudioToolsManifest.xml │ │ └── VisualTreeExtensions.cs │ ├── MaterialDesignToolkit.ResourceGeneration/ │ │ ├── Brushes.cs │ │ ├── Icon.cs │ │ ├── IconDataFactorySyntaxRewriter.cs │ │ ├── IconDiff.cs │ │ ├── IconThing.cs │ │ ├── MaterialColourSwatchesSnippet.xml │ │ ├── MaterialDesignTheme.ObsoleteBrushes.xaml │ │ ├── MaterialDesignToolkit.ResourceGeneration.csproj │ │ ├── MdPalette.cs │ │ ├── PackIconDataFactory.template.cs │ │ ├── PackIconKind.template.cs │ │ ├── Palette.json │ │ ├── PathHelper.cs │ │ ├── Program.cs │ │ ├── Properties/ │ │ │ └── launchSettings.json │ │ ├── RecommendedPrimaryTemplate.xaml │ │ ├── RecommendedSecondaryTemplate.xaml │ │ ├── ThemeColors.json │ │ └── TreeItem.cs │ ├── Shims/ │ │ ├── IsExternalInit.cs │ │ └── MathCompat.cs │ └── web/ │ ├── PaletteBuilder.html │ ├── images/ │ │ ├── MD4XAML.psd │ │ ├── MD4XAML.xcf │ │ ├── MaterialDesign.MahApps.xcf │ │ └── modern-wpf.xcf │ ├── jsx/ │ │ └── PaletteBuilder.js │ ├── scripts/ │ │ ├── PaletteBuilder.js │ │ ├── Swatches.js │ │ └── react.js │ └── styles/ │ └── style.css └── tests/ ├── MaterialColorUtilities.Tests/ │ ├── BlendTests.cs │ ├── ColorUtilsTests.cs │ ├── ContrastConstraintTests.cs │ ├── ContrastTests.cs │ ├── DislikeAnalyzerTests.cs │ ├── DynamicSchemeTests.cs │ ├── HctTests.cs │ ├── MaterialColorUtilities.Tests.csproj │ ├── MaterialDynamicColorsTests.cs │ ├── MathUtilsTests.cs │ ├── QuantizerCelebiTests.cs │ ├── QuantizerWsMeansTests.cs │ ├── QuantizerWuTests.cs │ ├── SchemeMonochromeTests.cs │ ├── ScoreTests.cs │ ├── TemperatureCacheTests.cs │ └── TonalPaletteTests.cs ├── MaterialDesignColors.Wpf.Tests/ │ ├── ColorAssistTests.cs │ ├── MaterialDesignColors.Wpf.Tests.csproj │ ├── Properties/ │ │ └── AssemblyInfo.cs │ └── ResourceProviderFixture.cs ├── MaterialDesignThemes.UITests/ │ ├── AllStyles.cs │ ├── MaterialDesignSpec.cs │ ├── MaterialDesignThemes.UITests.csproj │ ├── Samples/ │ │ ├── AutoSuggestBoxes/ │ │ │ ├── AutoSuggestTextBoxWithCollectionView.xaml │ │ │ ├── AutoSuggestTextBoxWithCollectionView.xaml.cs │ │ │ ├── AutoSuggestTextBoxWithInteractiveTemplate.xaml │ │ │ ├── AutoSuggestTextBoxWithInteractiveTemplate.xaml.cs │ │ │ ├── AutoSuggestTextBoxWithTemplate.xaml │ │ │ └── AutoSuggestTextBoxWithTemplate.xaml.cs │ │ ├── DialogHost/ │ │ │ ├── ClosingEventCounter.xaml │ │ │ ├── ClosingEventCounter.xaml.cs │ │ │ ├── ClosingEventViewModel.cs │ │ │ ├── LoadAndUnloadControl.xaml │ │ │ ├── LoadAndUnloadControl.xaml.cs │ │ │ ├── RestoreFocus.xaml │ │ │ ├── RestoreFocus.xaml.cs │ │ │ ├── RestoreFocusDisabled.xaml │ │ │ ├── RestoreFocusDisabled.xaml.cs │ │ │ ├── WithComboBox.xaml │ │ │ ├── WithComboBox.xaml.cs │ │ │ ├── WithCounter.xaml │ │ │ └── WithCounter.xaml.cs │ │ ├── DrawerHost/ │ │ │ ├── CancellingDrawerHost.xaml │ │ │ └── CancellingDrawerHost.xaml.cs │ │ ├── PasswordBox/ │ │ │ ├── BoundPasswordBox.xaml │ │ │ ├── BoundPasswordBox.xaml.cs │ │ │ ├── BoundPasswordBoxViewModel.cs │ │ │ ├── BoundPasswordBoxWindow.xaml │ │ │ └── BoundPasswordBoxWindow.xaml.cs │ │ ├── PopupBox/ │ │ │ ├── PopupBoxWithTemplateSelector.xaml │ │ │ └── PopupBoxWithTemplateSelector.xaml.cs │ │ ├── SplitButton/ │ │ │ ├── SplitButtonWithCommandBinding.xaml │ │ │ ├── SplitButtonWithCommandBinding.xaml.cs │ │ │ ├── SplitButtonWithCommandBindingWindow.xaml │ │ │ └── SplitButtonWithCommandBindingWindow.xaml.cs │ │ ├── Theme/ │ │ │ ├── ColorAdjustWindow.xaml │ │ │ └── ColorAdjustWindow.xaml.cs │ │ ├── UpDownControls/ │ │ │ ├── BoundNumericUpDown.xaml │ │ │ ├── BoundNumericUpDown.xaml.cs │ │ │ └── BoundNumericUpDownViewModel.cs │ │ └── Validation/ │ │ ├── ValidationUpdates.xaml │ │ └── ValidationUpdates.xaml.cs │ ├── TUnit/ │ │ └── IsCloseToExtensions.cs │ ├── TestBase.cs │ ├── WPF/ │ │ ├── AutoSuggestBoxes/ │ │ │ └── AutoSuggestTextBoxTests.cs │ │ ├── Buttons/ │ │ │ ├── OutlineButtonTests.cs │ │ │ └── RaisedButtonTests.cs │ │ ├── Cards/ │ │ │ ├── ElevatedCardTests.cs │ │ │ └── OutlinedCardTests.cs │ │ ├── ColorPickerTests.cs │ │ ├── ColorZones/ │ │ │ └── ColorZoneTests.cs │ │ ├── ComboBoxes/ │ │ │ └── ComboBoxTests.cs │ │ ├── ContentControls/ │ │ │ └── ContentControlTests.cs │ │ ├── DatePickers/ │ │ │ └── DatePickerTests.cs │ │ ├── DialogHosts/ │ │ │ └── DialogHostTests.cs │ │ ├── DrawerHosts/ │ │ │ └── DrawerHostTests.cs │ │ ├── Flippers/ │ │ │ └── ClassicFlipperTests.cs │ │ ├── ListBoxes/ │ │ │ └── ListBoxTests.cs │ │ ├── PasswordBoxes/ │ │ │ └── PasswordBoxTests.cs │ │ ├── PopupBoxes/ │ │ │ └── PopupBoxTests.cs │ │ ├── SnackBars/ │ │ │ └── SnackBarTests.cs │ │ ├── SplitButtons/ │ │ │ └── SplitButtonTests.cs │ │ ├── TabControls/ │ │ │ └── TabControlTests.cs │ │ ├── TextBoxes/ │ │ │ ├── MaterialDesignTextBox.cs │ │ │ └── TextBoxTests.cs │ │ ├── TextFieldDefaultHeightTests.cs │ │ ├── Theme/ │ │ │ ├── ColorAdjustTests.cs │ │ │ ├── ThemeTests.cs │ │ │ └── ThemeTests.g.cs │ │ ├── TimePickers/ │ │ │ ├── MaterialDesignTimePicker.cs │ │ │ └── TimePickerTests.cs │ │ ├── ToolBars/ │ │ │ └── ToolBarTests.cs │ │ ├── TreeListViews/ │ │ │ ├── TestableCollection.cs │ │ │ ├── TreeItem.cs │ │ │ ├── TreeListViewDataBinding.xaml │ │ │ ├── TreeListViewDataBinding.xaml.cs │ │ │ ├── TreeListViewExtensions.cs │ │ │ ├── TreeListViewImplicitTemplate.xaml │ │ │ ├── TreeListViewImplicitTemplate.xaml.cs │ │ │ ├── TreeListViewTemplateSelector.xaml │ │ │ ├── TreeListViewTemplateSelector.xaml.cs │ │ │ ├── TreeListViewTests.cs │ │ │ ├── TreeListViewWithCollectionView.xaml │ │ │ └── TreeListViewWithCollectionView.xaml.cs │ │ ├── TreeViews/ │ │ │ └── TreeViewTests.cs │ │ └── UpDownControls/ │ │ ├── DecimalUpDownTests.cs │ │ └── NumericUpDownTests.cs │ └── XamlTestExtensions.cs └── MaterialDesignThemes.Wpf.Tests/ ├── AdornerExtensionsTests.cs ├── AllStyles.cs ├── BundledThemeTests.cs ├── ButtonProgressAssistTests.cs ├── CalendarFormatInfoTests.cs ├── CheckBoxAssistTests.cs ├── ClockTests.cs ├── ColorPickerTests.cs ├── Converters/ │ ├── AutomationPropertiesNameConverterTests.cs │ ├── BrushOpacityConverterTests.cs │ ├── DoubleToCornerRadiusConverterTests.cs │ ├── MathConverterTests.cs │ ├── MathMultipleConverterTests.cs │ └── SliderToolTipConverterTests.cs ├── CustomColorThemeTests.cs ├── DataGridAssistTests.cs ├── DialogHostTests.cs ├── DrawerHostTests.cs ├── EnumDataAttribute.cs ├── FlipperAssistTests.cs ├── Internal/ │ └── TreeListViewItemsCollectionTests.cs ├── LabelTests.cs ├── MaterialDesignThemes.Wpf.Tests.csproj ├── MdixHelper.cs ├── PackIconTests.cs ├── PopupBoxTests.cs ├── Properties/ │ └── AssemblyInfo.cs ├── RatingBarTests.cs ├── SnackbarMessageQueueItemTests.cs ├── SnackbarMessageQueueTests.cs ├── TextBlockTests.cs ├── TextBoxTests.cs ├── ThemeTests.cs ├── TimePickerUnitTests.cs ├── TransitionerTests.cs ├── TreeViewTests.cs └── VisualTreeHelper.cs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .config/dotnet-tools.json ================================================ { "version": 1, "isRoot": true, "tools": { "xamlstyler.console": { "version": "3.2311.2", "commands": [ "xstyler" ] } } } ================================================ FILE: .editorconfig ================================================ # Remove the line below if you want to inherit .editorconfig settings from higher directories root = true ##### All files ##### [*] #### Core EditorConfig Options #### # Indentation and spacing indent_size = 4 indent_style = space tab_width = 4 # New line preferences insert_final_newline = true trim_trailing_whitespace = true ##### XAML/XML files ##### [*.{xaml,xml,csproj,targets,props,nuspec}] # Indentation and spacing indent_size = 2 indent_style = space tab_width = 2 # The following rules were initially inferred by Visual Studio IntelliCode from the C:\Users\bushc\Source\Repos\MaterialDesignInXamlToolkit codebase based on best match to current usage at 8/14/2018 # You can modify the rules from these initially generated values to suit your own policies # You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference [*.cs] #Core editorconfig formatting - indentation #use soft tabs (spaces) for indentation indent_style = space #Formatting - indentation options #indent switch case contents. csharp_indent_case_contents = true #indent switch labels csharp_indent_switch_labels = true #Formatting - new line options #place catch statements on a new line csharp_new_line_before_catch = true #place else statements on a new line csharp_new_line_before_else = true #require braces to be on a new line for methods, accessors, anonymous_methods, types, properties, control_blocks, and lambdas (also known as "Allman" style) csharp_new_line_before_open_brace = all #Formatting - organize using options #sort System.* using directives alphabetically, and place them before other usings dotnet_sort_system_directives_first = true #Formatting - spacing options #require a space before the colon for bases or interfaces in a type declaration csharp_space_after_colon_in_inheritance_clause = true #require a space after a keyword in a control flow statement such as a for loop csharp_space_after_keywords_in_control_flow_statements = true #require a space before the colon for bases or interfaces in a type declaration csharp_space_before_colon_in_inheritance_clause = true #remove space within empty argument list parentheses csharp_space_between_method_call_empty_parameter_list_parentheses = false #remove space between method call name and opening parenthesis csharp_space_between_method_call_name_and_opening_parenthesis = false #do not place space characters after the opening parenthesis and before the closing parenthesis of a method call csharp_space_between_method_call_parameter_list_parentheses = false #remove space within empty parameter list parentheses for a method declaration csharp_space_between_method_declaration_empty_parameter_list_parentheses = false #place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. csharp_space_between_method_declaration_parameter_list_parentheses = false #Formatting - wrapping options #leave code block on single line csharp_preserve_single_line_blocks = true #leave statements and member declarations on the same line csharp_preserve_single_line_statements = true #Style - expression bodied member options #prefer block bodies for accessors csharp_style_expression_bodied_accessors = when_on_single_line:suggestion #prefer block bodies for constructors csharp_style_expression_bodied_constructors = when_on_single_line:suggestion #prefer block bodies for methods csharp_style_expression_bodied_methods = when_on_single_line:suggestion #prefer block bodies for properties csharp_style_expression_bodied_properties = when_on_single_line:suggestion #Style - expression level options #prefer out variables to be declared before the method call csharp_style_inlined_variable_declaration = false:suggestion #prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them dotnet_style_predefined_type_for_member_access = true:suggestion #Style - implicit and explicit types #prefer var is used to declare variables with built-in system types such as int csharp_style_var_for_built_in_types = false:suggestion #prefer var when the type is already mentioned on the right-hand side of a declaration expression csharp_style_var_when_type_is_apparent = true:suggestion #Style - language keyword and framework type options #prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion #Style - qualification options #prefer events not to be prefaced with this. or Me. in Visual Basic dotnet_style_qualification_for_event = false:suggestion #prefer fields not to be prefaced with this. or Me. in Visual Basic dotnet_style_qualification_for_field = false:suggestion #prefer methods not to be prefaced with this. or Me. in Visual Basic dotnet_style_qualification_for_method = false:suggestion #prefer properties not to be prefaced with this. or Me. in Visual Basic dotnet_style_qualification_for_property = false:suggestion csharp_indent_labels = one_less_than_current csharp_using_directive_placement = outside_namespace:silent csharp_prefer_simple_using_statement = true:suggestion csharp_prefer_braces = true:silent csharp_style_namespace_declarations = block_scoped:silent csharp_style_prefer_method_group_conversion = true:silent csharp_style_prefer_top_level_statements = true:silent csharp_style_expression_bodied_operators = false:silent csharp_style_expression_bodied_indexers = true:silent csharp_style_expression_bodied_lambdas = true:silent csharp_style_expression_bodied_local_functions = false:silent [*.{cs,vb}] #### Naming styles #### # Naming rules dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion dotnet_naming_rule.types_should_be_pascal_case.symbols = types dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case # Symbol specifications dotnet_naming_symbols.interface.applicable_kinds = interface dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.interface.required_modifiers = dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.types.required_modifiers = dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.non_field_members.required_modifiers = # Naming styles dotnet_naming_style.begins_with_i.required_prefix = I dotnet_naming_style.begins_with_i.required_suffix = dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case dotnet_naming_style.pascal_case.required_prefix = dotnet_naming_style.pascal_case.required_suffix = dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_naming_style.pascal_case.required_prefix = dotnet_naming_style.pascal_case.required_suffix = dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_style_operator_placement_when_wrapping = beginning_of_line end_of_line = crlf dotnet_style_coalesce_expression = true:suggestion dotnet_style_null_propagation = true:suggestion dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion dotnet_style_prefer_auto_properties = true:silent dotnet_style_object_initializer = true:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_prefer_simplified_boolean_expressions = true:suggestion ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization * text=auto # Custom for Visual Studio *.cs diff=csharp # Standard to msysgit *.doc diff=astextplain *.DOC diff=astextplain *.docx diff=astextplain *.DOCX diff=astextplain *.dot diff=astextplain *.DOT diff=astextplain *.pdf diff=astextplain *.PDF diff=astextplain *.rtf diff=astextplain *.RTF diff=astextplain ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Contribution Guidelines PRs to this project are welcome, but before contributing please bear in mind my thoughts below. Where possible, please include unit tests. If you want to get involved but are unsure, please ask (say hello in the [Gitter chat room](http://gitter.im/ButchersBoy/MaterialDesignInXamlToolkit)). Also note that I wrote these guidelines several months after the library was first made available, with the benefit of hindsight. Apologies if there are inconsistencies with what you read below and what's already in the library. ## The purposes of this library: This is a theme library, **not** a control library. There is a subtle difference. Yes, there are some new custom controls, but their role is to specifically support either styling of existing WPF controls, or to Material Design components, as per the "Components" section in [Google's guidelines](https://www.google.com/design/spec/material-design/introduction.html). The role of this library is to give users Material Design themes for standard WPF controls, and custom controls for Google specified components where no parallel exists in WPF, or where existing WPF controls cannot be sufficiently styled to meet the Google specification. Anything else is outside the scope of this library. WPF is very powerful and flexible when it comes to creating custom controls, but that doesn't mean that I want to fill up this library with random controls. I want to provide the base tools and controls for Material Design, giving people a springboard to create their own controls where required. In no way is this library a home for any sort of application or business logic. ## Coding standards: I code using standard Visual Studio settings, using Resharper, and adopt (most of the) ReSharper's suggestions. I'd like the code to look pretty similar. The API is king. If adding anything to the public interface of this library (controls, helpers etc) be mindful of the naming and usage. Don't be offended if I accept your PR but rename things slightly. ## UWP: This whole project is a personal hobby, and this is even more true of the UWP section. I'm not accepting any PRs to UWP as I will be coding on this in my spare time, and using it as a way to learn and explore UWP for my own enlightenment. If and when the UWP solution becomes more mature I will relax this stance. ## Submitting a PR: Probably the smaller the better (within sensible bounds for the nature of your change); at least keep a single feature to a single branch/PR. ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yaml ================================================ name: Bug report description: File a bug report labels: ["bug", "evaluation required"] body: - type: markdown attributes: value: | Thanks for taking the time to fill out this bug report! Seriously consider creating and linking to a test repo which takes absolutely minimal setup to illustrate how reproduce the problem. - type: textarea id: bug-explanation attributes: label: Bug explanation description: | - Tell us what is the problem and what did you expect to happen. - Explain the different steps to reproduce the bug. - Provide a minimal and reproducible example either with code snippets or ideally an example repository. You can attach some screenshots or/and videos to better illustrate the problem. placeholder: Explain the problem... validations: required: true - type: input id: version attributes: label: Version description: What version of our package are you running? placeholder: "Example: 4.5.0" validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: GitHub discussion tab url: https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/discussions about: Please ask and answer questions here ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for this project title: '' labels: enhancement, evaluation required assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. ================================================ FILE: .github/copilot-instructions.md ================================================ # Copilot Instructions for MaterialDesignInXamlToolkit ## Repository Overview The MaterialDesignInXamlToolkit is a **theme library** for WPF applications that provides Material Design themes and styling. This is NOT a control library - the focus is on theming existing WPF controls and providing custom controls only when necessary to support Google's Material Design specifications. ### Key Principles - Theme library, not control library - Styling existing WPF controls to match Material Design - Custom controls only for Google-specified components that don't exist in WPF - No application or business logic belongs in this library - Provide base tools and springboard for developers to create their own controls ## Architecture and Structure ### Core Projects - **`MaterialDesignThemes.Wpf`** - Main theming library with styles, templates, and controls - **`MaterialDesignColors.Wpf`** - Color palette and theme management - **`MaterialDesignThemes.MahApps`** - Integration with MahApps.Metro - **`MainDemo.Wpf`** - Primary demonstration application - **`MaterialDesign3.Demo.Wpf`** - Material Design 3 demonstration - **`MaterialDesignToolkit.ResourceGeneration`** - Build-time resource generation tools ### Key Technologies - **WPF (Windows Presentation Foundation)** - UI framework - **XAML** - Markup for UI definitions and styles - **Material Design** - Google's design system implementation - **.NET 8** and **.NET Framework 4.7.2** - Target frameworks for the library - **.NET 9 SDK** - Required for building (as specified in `global.json`) - **C# 12.0** - Programming language - **PowerShell** - Build automation scripts ## Development Environment ### Requirements - **Windows** - Required for WPF development and compilation - **.NET 9 SDK** - As specified in `global.json` (note: projects target .NET 8 and .NET Framework 4.7.2) - **Visual Studio 2022** or **Visual Studio Code** with C# extension - **PowerShell** - For build scripts ### Build and Test ```powershell # Restore dependencies dotnet restore MaterialDesignToolkit.Full.slnx # Build (requires Windows) dotnet build MaterialDesignToolkit.Full.slnx --configuration Release --no-restore -p:Platform="Any CPU" -p:TreatWarningsAsErrors=True # Run tests dotnet test MaterialDesignToolkit.Full.slnx --configuration Release --no-build # Build NuGet packages .\build\BuildNugets.ps1 -MDIXVersion "x.x.x" -MDIXColorsVersion "x.x.x" -MDIXMahAppsVersion "x.x.x" ``` ## Code Style and Conventions ### General Guidelines - Follow standard Visual Studio settings with ReSharper suggestions - Use .editorconfig settings (4-space indents for C#, 2-space for XAML/XML) - Allman brace style (`csharp_new_line_before_open_brace = all`) - No `this.` qualification unless necessary - Prefer explicit types over `var` for built-in types - Use PascalCase for public members, interfaces start with `I` ### C# Conventions ```csharp // Preferred dependency property pattern public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyProperty", typeof(string), typeof(MyControl), new UIPropertyMetadata("DefaultValue", OnMyPropertyChanged)); public string MyProperty { get => (string)GetValue(MyPropertyProperty); set => SetValue(MyPropertyProperty, value); } private static void OnMyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (MyControl)d; // Handle property change } ``` ### XAML Style Guidelines - Use XamlStyler settings from `Settings.XamlStyler` - 2-space indentation for XAML - Keep first attribute on same line as element - Order attributes according to defined groups - Use `{StaticResource}` over `{DynamicResource}` where possible - Follow resource naming: `MaterialDesign.Brush.Primary.Light` ## WPF and Material Design Context ### Theme Architecture - **Base Themes**: Light and Dark variants - **Color System**: Primary, Secondary, Surface, Background colors with variants - **Elevation**: Shadow and overlay systems for depth - **Typography**: Material Design text styles - **Motion**: Transitions and animations ### Common Patterns ```csharp // Theme modification pattern private static void ModifyTheme(Action modificationAction) { var paletteHelper = new PaletteHelper(); Theme theme = paletteHelper.GetTheme(); modificationAction?.Invoke(theme); paletteHelper.SetTheme(theme); } // Color adjustment usage theme.ColorAdjustment = new ColorAdjustment { DesiredContrastRatio = desiredRatio, Contrast = contrastValue, Colors = colorSelection }; ``` ### Resource Dictionary Patterns ```xml ``` ## Testing Approach ### Test Structure - **Unit Tests**: `MaterialDesignThemes.Wpf.Tests`, `MaterialDesignColors.Wpf.Tests` - **UI Tests**: `MaterialDesignThemes.UITests` - Visual/integration testing - **Demo Applications**: Manual testing and showcasing functionality ### Test Patterns ```csharp [Test] public async Task ThemeTest_Example() { await App.InitializeWithMaterialDesign( baseTheme: BaseTheme.Light, primary: PrimaryColor.Blue, secondary: SecondaryColor.Orange); // Test implementation } ``` ## Build Pipeline and Automation ### GitHub Actions Workflows - **PR Verification**: `pr_verification.yml` - Build and test on PRs - **Build Artifacts**: `build_artifacts.yml` - Main build pipeline - **Release**: `release.yml` - Create releases and publish NuGets ### PowerShell Build Scripts - **`BuildNugets.ps1`** - Package creation - **`ApplyXamlStyler.ps1`** - Code formatting - **`MigrateBrushes.ps1`** - Resource migration utilities - **`UpdateNugets.ps1`** - Package management ## Domain-Specific Knowledge ### Material Design Implementation - Follow Google Material Design guidelines strictly - Implement elevation through shadows and overlays - Use consistent color theming system - Support both Material Design 2 and 3 specifications - Ensure accessibility compliance (contrast ratios, touch targets) ### WPF Theming Best Practices - Use `TemplateBinding` for connecting to parent properties - Implement proper focus visuals and keyboard navigation - Support high contrast mode and accessibility features - Use appropriate triggers for state changes (hover, pressed, disabled) - Leverage WPF's dependency property system effectively ### Resource Organization - Brush resources: `MaterialDesign.Brush.*` - Style resources: Clear, descriptive names matching WPF conventions - Template resources: Match control types and variants - Color resources: Follow Material Design naming (Primary, Secondary, Surface, etc.) ## API Design Guidelines - **Maintain backward compatibility** - This is a widely-used library - **Minimal public API surface** - Only expose what's necessary - **Consistent naming** - Follow WPF and Material Design conventions - **Proper documentation** - XML docs for all public APIs - **Designer support** - Ensure controls work well in Visual Studio designer ## Common Tasks and Patterns ### Adding a New Style 1. Define in appropriate XAML resource dictionary 2. Follow existing naming conventions 3. Test in demo applications 4. Ensure accessibility compliance 5. Add to migration scripts if replacing existing styles ### Theme Modifications 1. Use `PaletteHelper` for runtime theme changes 2. Support both static and dynamic resource binding 3. Test with both Light and Dark themes 4. Verify color adjustments work properly ### Custom Control Development 1. Only when no WPF equivalent exists 2. Follow Material Design specifications exactly 3. Implement proper template parts and visual states 4. Support theming and color adjustments 5. Include comprehensive tests and demo usage Remember: This library's primary goal is to provide a complete, high-quality Material Design theming solution for WPF applications while maintaining excellent performance and broad compatibility. ================================================ FILE: .github/dependabot.yml ================================================ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "nuget" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "weekly" - package-ecosystem: "github-actions" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "weekly" ================================================ FILE: .github/release.yml ================================================ # .github/release.yml changelog: exclude: labels: - ignore-for-release authors: - MDIX-SA - github-actions[bot] categories: - title: Key Changes labels: - release notes - title: Breaking Changes labels: - breaking change - visual breaking change ================================================ FILE: .github/workflows/build_artifacts.yml ================================================ name: Build Artifacts on: workflow_call: inputs: build-configuration: default: "Release" required: false type: string mdix-version: required: true type: string mdix-colors-version: required: true type: string mdix-mahapps-version: required: true type: string jobs: build: name: Build and Test runs-on: windows-latest env: solution: MaterialDesignToolkit.Full.slnx steps: - uses: actions/checkout@v6 - name: Setup .NET uses: actions/setup-dotnet@v5 with: dotnet-version: | 8.x 9.x 10.x - name: Restore dependencies run: dotnet restore ${{ env.solution }} - name: Build run: dotnet build ${{ env.solution }} --configuration ${{ inputs.build-configuration }} --no-restore -p:Platform="Any CPU" -p:TreatWarningsAsErrors=True env: MDIXVersion: ${{ inputs.mdix-version }} MDIXColorsVersion: ${{ inputs.mdix-colors-version }} MDIXMahAppsVersion: ${{ inputs.mdix-mahapps-version }} - name: Test timeout-minutes: 20 run: dotnet test ${{ env.solution }} --configuration ${{ inputs.build-configuration }} --no-build --blame-crash --logger GitHubActions - name: Upload Screenshots if: ${{ always() }} uses: actions/upload-artifact@v7 with: name: Screenshots-${{ github.run_number }} path: ${{ github.workspace }}\tests\MaterialDesignThemes.UITests\bin\${{ inputs.build-configuration }}\net9.0-windows\Screenshots if-no-files-found: ignore - name: Build NuGets run: .\build\BuildNugets.ps1 -MDIXVersion ${{ inputs.mdix-version }} -MDIXColorsVersion ${{ inputs.mdix-colors-version }} -MDIXMahAppsVersion ${{ inputs.mdix-mahapps-version }} - name: Upload NuGets uses: actions/upload-artifact@v7 with: name: NuGets path: "*.nupkg" - name: Upload Demo App uses: actions/upload-artifact@v7 with: name: DemoApp path: "src/MainDemo.Wpf/bin/${{ env.buildConfiguration }}" ================================================ FILE: .github/workflows/control_styles.yml ================================================ name: Wiki - Update Control Styles on: # push: # branches: [ master ] workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Generate Control Styles Markdown run: build/GenerateThemesWikiMarkdown.ps1 shell: pwsh - name: Upload Control Styles to Wiki uses: docker://decathlon/wiki-page-creator-action:latest env: GH_PAT: ${{ secrets.SA_TOKEN }} ACTION_MAIL: mdixsa@outlook.com ACTION_NAME: Material Design Service Account OWNER: MaterialDesignInXAML REPO_NAME: MaterialDesignInXamlToolkit MD_FOLDER: build WIKI_PUSH_MESSAGE: Automatic update of ControlStyleList.md from GitHub Action ================================================ FILE: .github/workflows/copilot-setup-steps.yml ================================================ name: "Copilot Setup Steps" # Automatically run the setup steps when they are changed to allow for easy validation, and # allow manual testing through the repository's "Actions" tab on: workflow_dispatch: push: paths: - .github/workflows/copilot-setup-steps.yml pull_request: paths: - .github/workflows/copilot-setup-steps.yml defaults: run: shell: pwsh jobs: # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. copilot-setup-steps: runs-on: windows-latest permissions: contents: read steps: - name: Checkout code uses: actions/checkout@v6 - name: Setup .NET uses: actions/setup-dotnet@v5 with: dotnet-version: | 8.x 9.x 10.x - name: Restore dependencies run: dotnet restore MaterialDesignToolkit.Full.slnx ================================================ FILE: .github/workflows/generate_contributors.yml ================================================ # This is a basic workflow to help you get started with Actions name: Generate Milestone Contributors # Controls when the workflow will run on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: inputs: milestone: description: 'The milestone to generate contributors' required: true type: string jobs: show_contributors: runs-on: ubuntu-latest name: A job to get contributors steps: - name: GetContribs id: get-contribs uses: Keboo/GitHubHelper@master with: milestone: '${{ inputs.milestone }}' repository: 'MaterialDesignInXamlToolkit' repository-owner: 'MaterialDesignInXAML' token: ${{ github.token }} - name: Get the output run: echo "${{ steps.get-contribs.outputs.contributors }}" ================================================ FILE: .github/workflows/get_versions.yml ================================================ name: Setup Versions on: workflow_call: inputs: is-full-release: required: false type: boolean default: false outputs: mdix-version: description: "The version for the MaterialDesignThemes library" value: ${{ jobs.getting_versions.outputs.mdix-version }} mdix-colors-version: description: "The version for the MaterialDesignColors library" value: ${{ jobs.getting_versions.outputs.mdix-colors-version }} mdix-mahapps-version: description: "The version for the MaterialDesignThemes.MahApps library" value: ${{ jobs.getting_versions.outputs.mdix-mahapps-version }} jobs: getting_versions: env: #Update these base version numbers mdix-version: "5.3.1" mdix-colors-version: "5.3.1" mdix-mahapps-version: "5.3.1" name: Set version numbers runs-on: ubuntu-latest defaults: run: shell: pwsh # Map the job outputs to step outputs outputs: mdix-version: ${{ steps.output_versions.outputs.mdix-version }} mdix-colors-version: ${{ steps.output_versions.outputs.mdix-colors-version }} mdix-mahapps-version: ${{ steps.output_versions.outputs.mdix-mahapps-version }} steps: - name: Set preview version numbers if: ${{ !inputs.is-full-release }} run: | "mdix-version=${{ env.mdix-version }}-ci${{ github.run_number }}" >> $env:GITHUB_ENV "mdix-colors-version=${{ env.mdix-colors-version }}-ci${{ github.run_number }}" >> $env:GITHUB_ENV "mdix-mahapps-version=${{ env.mdix-mahapps-version }}-ci${{ github.run_number }}" >> $env:GITHUB_ENV - name: Output Versions id: output_versions run: | echo ${{ env.mdix-version }} "mdix-version=${{ env.mdix-version }}" >> $env:GITHUB_OUTPUT echo ${{ env.mdix-colors-version }} "mdix-colors-version=${{ env.mdix-colors-version }}" >> $env:GITHUB_OUTPUT echo ${{ env.mdix-mahapps-version }} "mdix-mahapps-version=${{ env.mdix-mahapps-version }}" >> $env:GITHUB_OUTPUT ================================================ FILE: .github/workflows/icon_update.yml ================================================ name: Icon Update on: workflow_dispatch: schedule: - cron: "0 3 * * *" env: GH_TOKEN: ${{ secrets.SA_PAT }} defaults: run: shell: pwsh jobs: build: #This check prevents this from running on forks if: ${{ github.repository == 'MaterialDesignInXAML/MaterialDesignInXamlToolkit' }} runs-on: windows-latest steps: - uses: actions/checkout@v6 - name: Run Icon Generation run: dotnet run -c Release -- icons working-directory: ./src/MaterialDesignToolkit.ResourceGeneration - name: Check for changes id: check_for_changes run: | $hasChanges = $((git status --porcelain).Length -gt 0).ToString().ToLower() "has_changes=$hasChanges" >> $env:GITHUB_OUTPUT - name: Open Pull Request if: ${{ steps.check_for_changes.outputs.has_changes == 'true' }} run: | git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" git checkout -b "automated/icon_update" git commit -m "[bot] Pack Icon update" --all git push -f --set-upstream origin automated/icon_update gh pr create --fill gh pr merge automated/icon_update --delete-branch --auto --squash ================================================ FILE: .github/workflows/nightly_release.yml ================================================ name: Nightly Release on: workflow_dispatch: schedule: - cron: '0 9 * * *' env: GH_TOKEN: ${{ github.token }} defaults: run: shell: pwsh jobs: check_for_changes: #This check prevents this from running on forks if: ${{ github.repository == 'MaterialDesignInXAML/MaterialDesignInXamlToolkit' }} runs-on: ubuntu-latest outputs: should_run: ${{ steps.check_for_changes.outputs.has_changed }} steps: - id: check_for_changes name: Check for changes run: | # Grab the last two run, since the latest run will be the current one executing $workflowList = gh run list --workflow "${{ github.workflow }}" --branch "${{ github.ref_name }}" --json databaseId --limit 2 --repo "${{ github.repository }}" $runId = ($workflowList | ConvertFrom-Json)[1].databaseId $lastRunHash = ((gh run view $runId --json headSha --repo "${{ github.repository }}") | ConvertFrom-Json).headSha echo "Last hash $lastRunHash" echo "Current hash ${{ github.sha }}" $hasChanged = ($lastRunHash -ne "${{ github.sha }}").ToString().ToLower() echo "Has updates $hasChanged" "has_changed=$hasChanged" >> $env:GITHUB_OUTPUT get_versions: needs: [check_for_changes] if: ${{ needs.check_for_changes.outputs.should_run == 'true' }} name: Get Versions uses: ./.github/workflows/get_versions.yml build_artifacts: name: Build artifacts needs: [get_versions, check_for_changes] if: ${{ needs.check_for_changes.outputs.should_run == 'true' }} uses: ./.github/workflows/build_artifacts.yml with: mdix-version: ${{ needs.get_versions.outputs.mdix-version }} mdix-colors-version: ${{ needs.get_versions.outputs.mdix-colors-version }} mdix-mahapps-version: ${{ needs.get_versions.outputs.mdix-mahapps-version }} push_nugets: needs: [build_artifacts] runs-on: ubuntu-latest name: Push NuGets steps: - name: Download NuGet Artifacts uses: actions/download-artifact@v8 with: name: NuGets path: nugets - name: Push NuGets run: | dotnet nuget push nugets/*.nupkg --api-key ${{ secrets.PAT }} --source https://api.nuget.org/v3/index.json --skip-duplicate ================================================ FILE: .github/workflows/pr_verification.yml ================================================ name: Pull Request Verification on: push: branches: [ master ] pull_request: branches: [ master ] workflow_dispatch: defaults: run: shell: pwsh jobs: build: name: Build artifacts uses: ./.github/workflows/build_artifacts.yml with: mdix-version: "0.0.0" mdix-colors-version: "0.0.0" mdix-mahapps-version: "0.0.0" automerge: needs: build runs-on: ubuntu-latest permissions: pull-requests: write contents: write steps: - uses: fastify/github-action-merge-dependabot@v3.11.2 ================================================ FILE: .github/workflows/release.yml ================================================ name: Production Release on: workflow_dispatch: inputs: milestone: description: "The milestone to generate a release for" required: true type: string env: solution: MaterialDesignToolkit.Full.slnx GITHUB_TOKEN: ${{ secrets.SA_PAT }} defaults: run: shell: pwsh jobs: get_versions: name: Get Versions uses: ./.github/workflows/get_versions.yml with: is-full-release: true version_number_check: needs: [get_versions] runs-on: ubuntu-latest name: Version matches milestone steps: - name: Check versions run: | if ('${{ inputs.milestone }}' -ne '${{ needs.get_versions.outputs.mdix-version }}') { Write-Error "Milestone ${{ inputs.milestone }} does not match MDIX ${{ needs.get_versions.outputs.mdix-version }}" exit 1 } else { Write-Host "Versions match" } build_release_notes: runs-on: ubuntu-latest name: Generate Release Notes steps: - name: Get Contributors id: get-contribs uses: Keboo/GitHubHelper@master with: milestone: "${{ inputs.milestone }}" repository: "MaterialDesignInXamlToolkit" repository-owner: "MaterialDesignInXAML" token: ${{ github.token }} - name: Generate Release Notes run: | $response = gh api --method POST -H "Accept: application/vnd.github+json" /repos/${{ github.repository }}/releases/generate-notes -f tag_name='v${{ inputs.milestone }}' $json = $response | ConvertFrom-Json $releaseNotes = $json.body $contributors = "${{ steps.get-contribs.outputs.contributors }}" $releaseNotes | Out-File -Append "ReleaseNotes.md" "`n" | Out-File -Append "ReleaseNotes.md" $contributors | Out-File -Append "ReleaseNotes.md" cat "ReleaseNotes.md" - name: Upload Release Notes uses: actions/upload-artifact@v7 with: name: ReleaseNotes path: "ReleaseNotes.md" build_artifacts: name: Build artifacts needs: get_versions uses: ./.github/workflows/build_artifacts.yml with: mdix-version: ${{ needs.get_versions.outputs.mdix-version }} mdix-colors-version: ${{ needs.get_versions.outputs.mdix-colors-version }} mdix-mahapps-version: ${{ needs.get_versions.outputs.mdix-mahapps-version }} build_icon_changes: needs: [build_artifacts] runs-on: windows-latest name: Get Icon Changes steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Download NuGet Artifacts uses: actions/download-artifact@v8 with: name: NuGets path: nugets - name: Get Previous NuGet release run: | $release = (gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository }}/releases/latest) | ConvertFrom-Json gh release download "$($release.tag_name)" --repo "${{ github.repository }}" --pattern *.nupkg working-directory: nugets - name: Create Icon Diff File run: | dotnet run --project ./src/MaterialDesignToolkit.ResourceGeneration/MaterialDesignToolkit.ResourceGeneration.csproj -c Release -- icon-diff - name: Upload Icon Changes uses: actions/upload-artifact@v7 with: name: IconChanges path: "IconChanges*.md" create_release: needs: [ build_release_notes, build_artifacts, build_icon_changes, version_number_check, ] runs-on: ubuntu-latest name: Create Draft Release steps: - name: Download NuGet Artifacts uses: actions/download-artifact@v8 with: name: NuGets path: nugets - name: Download Demo App Artifacts uses: actions/download-artifact@v8 with: name: DemoApp path: demo-app - name: Zip Demo App run: zip -r DemoApp.zip demo-app/* - name: Download Release Notes uses: actions/download-artifact@v8 with: name: ReleaseNotes - name: Create Release run: | # We can't use glob pattern because of this bug https://github.com/cli/cli/issues/5099 gh release create v${{ inputs.milestone }} --repo '${{ github.repository }}' --draft --latest --title "${{ inputs.milestone }}" --notes-file ReleaseNotes.md (Get-Item '${{ github.workspace }}/nugets/*.nupkg') '${{ github.workspace }}/DemoApp.zip' update_wiki: needs: [create_release] runs-on: ubuntu-latest environment: production name: Update Wiki steps: - name: Checkout Wiki Repo uses: actions/checkout@v6 with: repository: ${{ github.repository }}.wiki - name: Download Icon Changes uses: actions/download-artifact@v8 with: name: IconChanges path: icon-changes - name: Update Wiki run: | $iconUpdates = Get-ChildItem -Path "icon-changes/*.md" foreach($update in $iconUpdates){ Write-Host "Updating from $update" if ($update.Name -match '-(?\d+\.\d+\.\d+)--(?\d+\.\d+\.\d+).md$') { $previousVersion = $Matches.PreviousVersion $targetVersion = $Matches.TargetVersion $majorVersion = $targetVersion.Split(".") | Select-Object -First 1 # Update the changes $changesFileName = "$majorVersion-x-icon-changes" $changesFile = "$changesFileName.md" if (!(Test-Path $changesFile)) { New-Item -ItemType File $changesFile | Out-Null } @( (Get-Content $update), "", (Get-Content $changesFile) ) | Set-Content $changesFile # Update the PackIcon Release notes [string[]] $releaseNotes = Get-Content "PackIcon-ReleaseNotes.md" $firstLine = $releaseNotes | Where-Object { $_.StartsWith("[Pack Icon Changes") } | Select-Object -First 1 $index = $releaseNotes.IndexOf($firstLine) @( ($releaseNotes | Select-Object -First $index), "[Pack Icon Changes $previousVersion => $targetVersion]($changesFileName#pack-icon-changes-$($previousVersion -replace '\.', '')--$($targetVersion -replace '\.', ''))", "", ($releaseNotes | Select-Object -Skip $index) ) | Set-Content "PackIcon-ReleaseNotes.md" Remove-Item $update } else { Write-Warning "Did not parse version from $($update.Name)" } } - name: Push Wiki run: | git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" git add . git commit -m "[automated] Update Wiki with icon changes for ${{ inputs.milestone }}" --all git push push_nugets: needs: [create_release] runs-on: ubuntu-latest name: Push NuGets environment: production steps: - name: Download NuGet Artifacts uses: actions/download-artifact@v8 with: name: NuGets path: nugets - name: Push NuGets run: | dotnet nuget push nugets/*.nupkg --api-key ${{ secrets.PAT }} --source https://api.nuget.org/v3/index.json --skip-duplicate publish_release: needs: [create_release] runs-on: ubuntu-latest name: Publish Release environment: production steps: - name: Publish Release run: | gh release edit v${{ inputs.milestone }} --repo '${{ github.repository }}' --draft=false close_milestone: needs: [create_release] runs-on: ubuntu-latest name: Close Milestone environment: production steps: # Doing a checkout, until this issue is resolved. # https://github.com/valeriobelli/gh-milestone/issues/15 # As of version 2.1.0 the -R doesn't appear to output valid json when filtering. So still using the checkout. - uses: actions/checkout@v6 - name: Close Milestone run: | gh extension install valeriobelli/gh-milestone Write-Host "Using extension version $(gh milestone --version)" $milestones = $(gh milestone list --json number,title) | ConvertFrom-Json $milestoneNumber = ($milestones | Where-Object { $_.title -eq "${{ inputs.milestone }}" }).number gh milestone edit $milestoneNumber --state closed env: GITHUB_TOKEN: ${{ secrets.SA_PAT }} update_version_numbers: needs: [create_release] runs-on: ubuntu-latest name: Update Version Numbers environment: production steps: # Checkout is needed so that we can update the get_versions.yml file - uses: actions/checkout@v6 with: token: ${{ secrets.SA_PAT }} - name: Increment Version Numbers run: | function Update-Version { param ( [string]$Prefix ) $workflowPath = "./.github/workflows/get_versions.yml" $workflowContent = Get-Content -Path $workflowPath $versionPattern = '"(\d+\.\d+\.)(\d+)"' $pattern = "$Prefix`: $versionPattern" $match = $workflowContent -match $pattern if ($match[0] -match $versionPattern) { $newVersion = $Matches[1] + ([int]$Matches[2] + 1) $workflowContent = $workflowContent -replace $pattern,"$Prefix`: `"$newVersion`"" Write-Host "$Prefix updated to $newVersion" } else { Write-Error "Failed to update $Prefix version" } Set-Content -Path $workflowPath -Value $workflowContent } Update-Version -Prefix "mdix-version" Update-Version -Prefix "mdix-colors-version" Update-Version -Prefix "mdix-mahapps-version" - name: Open Pull Request env: GH_TOKEN: ${{ secrets.SA_PAT }} run: | git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" git checkout -b "automated/version_update" git commit -m "[bot] Release version update" --all git push -f --set-upstream origin automated/version_update gh pr create --fill gh pr merge automated/version_update --delete-branch --auto --squash ================================================ FILE: .github/workflows/stale_issues_and_prs.yml ================================================ name: 'Close stale issues and PRs' on: schedule: - cron: '30 1 * * *' workflow_dispatch: jobs: stale: runs-on: ubuntu-latest steps: - uses: actions/stale@v10 with: stale-issue-message: 'This issue is marked stale because it has been open 30 days with no activity. Remove stale label or update the issue, otherwise it will be closed in 14 days.' stale-pr-message: 'This PR is marked stale because it has been open 60 days with no activity. Remove stale label or update the PR, otherwise it will be closed in 14 days.' close-issue-message: 'This issue was closed because it has been stalled for 14 days with no activity.' close-pr-message: 'This PR was closed because it has been stalled for 14 days with no activity.' only-issue-labels: Waiting on feedback # Only consider issues with 'Waiting on feedback' labels exempt-draft-pr: true # Do not consider a draft PR stale exempt-all-pr-milestones: true # Do not consider a PR associated with a Milestone stale days-before-stale: 30 days-before-pr-stale: 60 days-before-close: 14 ascending: true # Start with the oldest issues/PRs first debug-only: false # Currently only doing "dry runs" until we're satisfied with the configuration operations-per-run: 30 # GitHub API calls are rate limited. When debug-only is "false", this value should be approx. 30 (default) or less ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.suo *.user *.userosscache *.sln.docstates # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ # Visual Studio 2015/2017 cache/options directory .vs/ # JetBrains Rider .idea # Roslyn cache directories *.ide/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* #NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *_wpftmp.csproj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opensdf *.sdf *.cachefile # Visual Studio profiler *.psess *.vsp *.vspx # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding addin-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch _NCrunch_* .*crunch*.local.xml # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # TODO: Comment the next line if you want to checkin your web deploy settings # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ # If using the old MSBuild-Integrated Package Restore, uncomment this: #!**/packages/repositories.config # Windows Azure Build Output csx/ *.build.csdef # Windows Store app package directory AppPackages/ # Others sql/ *.Cache ClientBin/ [Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview *.pfx *.publishsettings node_modules/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files *.mdf *.ldf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings # Microsoft Fakes FakesAssemblies/ # ========================= # Operating System Files # ========================= # OSX # ========================= .DS_Store .AppleDouble .LSOverride # Thumbnails ._* # Files that might appear on external disk .Spotlight-V100 .Trashes # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk # Windows # ========================= # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp # Windows shortcuts *.lnk #React.JS .module-cache *.lutconfig ================================================ FILE: Directory.Build.props ================================================ Copyright © 2022 Mulholland Software/James Willock 14.0 prompt true ..\..\build\key.snk false enable true true false James Willock James Willock MIT https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit MaterialDesign.Icon.png false README.md https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/releases ================================================ FILE: Directory.packages.props ================================================ true true ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) James Willock, Mulholland Software and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MaterialDesignToolkit.Full.slnx ================================================ ================================================ FILE: README.md ================================================ # Material Design In XAML Toolkit ![Logo of Material Design in XAML](src/web/images/MD4XAML32.png) [![NuGet-Themes](https://img.shields.io/nuget/v/MaterialDesignThemes.svg?label=nuget:%20MaterialDesignThemes)](https://www.nuget.org/packages/MaterialDesignThemes/) [![NuGet-Colors](https://img.shields.io/nuget/v/MaterialDesignColors.svg?label=nuget:%20MaterialDesignColors)](https://www.nuget.org/packages/MaterialDesignColors/) [![NuGet-Themes-CI](https://img.shields.io/nuget/vpre/MaterialDesignThemes.svg?label=nuget:%20MaterialDesignThemes%20(CI))](https://www.nuget.org/packages/MaterialDesignThemes/) [![NuGet-Colors-CI](https://img.shields.io/nuget/vpre/MaterialDesignColors.svg?label=nuget:%20MaterialDesignColors%20(CI))](https://www.nuget.org/packages/MaterialDesignColors/) [![Backers on Open Collective](https://opencollective.com/materialdesigninxaml/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/materialdesigninxaml/sponsors/badge.svg)](#sponsors) [![Chat](https://img.shields.io/badge/chat-grey?logo=discord)][discord-server-url] [![Issues](https://img.shields.io/github/issues/MaterialDesignInXAML/MaterialDesignInXamlToolkit.svg)](https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/issues) Comprehensive and easy to use Material Design theme and control library for the Windows desktop (WPF). - Material Design styles for all major WPF Framework controls - Additional controls to support the theme, including Multi Action Button, Cards, Dialogs, Clock - Easy configuration of palette (at design _and_ runtime), according to [Google's guidelines](https://material.io/design/) - Full [Material Design Icons](https://materialdesignicons.com/) icon pack - Easy transition effects - Compatible with [Dragablz](https://github.com/ButchersBoy/Dragablz), [MahApps](https://github.com/MahApps/MahApps.Metro) - Demo applications included in the source project [See screenshots](#screenshots)
Table of contents - [Getting started](#getting-started) - [Building the source](#building-the-source) - [Screenshots](#screenshots) - [More examples](#more-examples) - [FAQ](#faq) - [Contributing](#contributing) - [Mentions](#mentions) - [Backers](#backers) - [Sponsors](#sponsors)
--- ## Getting started > [!NOTE] > See the [full starting guide](https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/wiki/Getting-Started) for more in-depth information. This quick guide assumes you have already created a WPF project and are using Microsoft Visual Studio 2022. * Install the toolkit through the visual NuGet package manager in Visual Studio or use the following command: ``` Install-Package MaterialDesignThemes ``` * Alter your `App.xaml` ```xml ``` * If you want to target Material Design 3, alter the `ResourceDictionary` line in the snippet above to use `MaterialDesign3.Defaults.xaml`. * Alter your `MainWindow.xaml` ```xml ``` ## Building the source To build the project, following is required: * Microsoft Visual Studio 2022 * .NET desktop development workload This repository also contains 3 different demo applications: * `MaterialDesignDemo` - Reference WPF app with Material Design 2 styling, this contains all controls and is a recommended tool when developing apps with this library * `MaterialDesign3Demo` - Reference WPF app with Material Design 3 styling, under development * `MahAppsDragablzDemo` - Demo app for combining with Dragablz and MahApps ## Screenshots
Material Design 3 demo app screenshots ![Buttons](src/web/images/screen-md3/buttons.png) ![Cards](src/web/images/screen-md3/cards.png) ![Chips](src/web/images/screen-md3/chips.png) ![Colortool](src/web/images/screen-md3/colortool.png) ![Colorzones](src/web/images/screen-md3/colorzones.png) ![Comboboxes](src/web/images/screen-md3/comboboxes.png) ![Datagrids](src/web/images/screen-md3/datagrids.png) ![Dialogs](src/web/images/screen-md3/dialogs.png) ![Drawer](src/web/images/screen-md3/drawer.png) ![Elevation](src/web/images/screen-md3/elevation.png) ![Expander](src/web/images/screen-md3/expander.png) ![Fields](src/web/images/screen-md3/fields.png) ![Fieldslineup](src/web/images/screen-md3/fieldslineup.png) ![Groupboxes](src/web/images/screen-md3/groupboxes.png) ![Home](src/web/images/screen-md3/home.png) ![Iconpack](src/web/images/screen-md3/iconpack.png) ![Lists](src/web/images/screen-md3/lists.png) ![Menustoolbars](src/web/images/screen-md3/menustoolbars.png) ![Navigationbar](src/web/images/screen-md3/navigationbar.png) ![Navigationrail](src/web/images/screen-md3/navigationrail.png) ![Pallete](src/web/images/screen-md3/pallete.png) ![Pickers](src/web/images/screen-md3/pickers.png) ![Progressindicators](src/web/images/screen-md3/progressindicators.png) ![Ratingbar](src/web/images/screen-md3/ratingbar.png) ![Slider](src/web/images/screen-md3/slider.png) ![Snackbar](src/web/images/screen-md3/snackbar.png) ![Toggles](src/web/images/screen-md3/toggles.png) ![Tooltips](src/web/images/screen-md3/tooltips.png) ![Transitions](src/web/images/screen-md3/transitions.png) ![Trees](src/web/images/screen-md3/trees.png) ![Typography](src/web/images/screen-md3/typography.png)
Material Design 2 demo app screenshots > [!WARNING] > The screenshots below are taken from the Material Design 2 demo app. > Material Design 3 is the latest version, so the UI shown here may differ from the latest design. ![Screenshot of WPF Material Design 2 demo application home page](src/web/images/screen-md2/home.png) ![Buttons](src/web/images/screen-md2/buttons.png) ![Toggles](src/web/images/screen-md2/toggles.png) ![Fields](src/web/images/screen-md2/fields.png) ![ComboBoxes](src/web/images/screen-md2/comboboxes.png) ![Palette](src/web/images/screen-md2/palette.png) ![Color Tools](src/web/images/screen-md2/colortools.png) ![Pickers](src/web/images/screen-md2/pickers.png) ![Icons](src/web/images/screen-md2/iconpack.png) ![Cards](src/web/images/screen-md2/cards.png) ![Menus and Toolbars](src/web/images/screen-md2/menutoolbar.png) ![Progress Bars](src/web/images/screen-md2/progress.png) ![Dialogs](src/web/images/screen-md2/dialogs.png) ![Lists](src/web/images/screen-md2/lists.png) ![Tree View](src/web/images/screen-md2/treeview.png) ![Sliders](src/web/images/screen-md2/sliders.png) ![Chips](src/web/images/screen-md2/chips.png) ![Typography](src/web/images/screen-md2/typography.png) ![Group Box](src/web/images/screen-md2/groupbox.png) ![Snackbars](src/web/images/screen-md2/snackbars.png) ![Elevation](src/web/images/screen-md2/elevation.png) ![Colorzones](src/web/images/screen-md2/colorzones.png) ![Datagrids](src/web/images/screen-md2/datagrids.png) ![Drawer](src/web/images/screen-md2/drawer.png) ![Expander](src/web/images/screen-md2/expander.png) ![Fieldslineup](src/web/images/screen-md2/fieldslineup.png) ![Navigationrail](src/web/images/screen-md2/navigationrail.png) ![NumericUpDown](src/web/images/screen-md2/numericupdown.png) ![Ratingbar](src/web/images/screen-md2/ratingbar.png) ![Tabs](src/web/images/screen-md2/tabs.png) ![Tooltips](src/web/images/screen-md2/tooltips.png) ![Transitions](src/web/images/screen-md2/transitions.png)
## More examples * [Keboo/MaterialDesign.Examples](https://github.com/Keboo/MaterialDesignInXaml.Examples) * [Motion List](https://github.com/MaterialDesignInXAML/MotionList) ## FAQ * [How to increase rendering performance?](docs/rendering-performance.md) ## Contributing Before contributing code read the [Contribution Guidelines](.github/CONTRIBUTING.md) * GitHub issues are for bugs and feature requests. * For questions, help and chat in general, please use the [GitHub discussion tab](https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/discussions) or the [Discord server][discord-server-url]. * Stack Overflow tag: [`material-design-in-xaml`](http://stackoverflow.com/questions/tagged/material-design-in-xaml) Want to say thanks? 🙏🏻 * Hit the :star: star :star: button * If you'd like to make a very much appreciated financial donation please visit open collective This project exists thanks to all the people who contribute. ## Mentions - **[James Willock](https://github.com/ButchersBoy) [![Twitter](https://img.shields.io/badge/twitter-%40james__willock-55acee.svg?style=flat-square)](https://twitter.com/James_Willock)** - Founder of the project - **[Kevin Bost](https://github.com/Keboo) [![Twitter](https://img.shields.io/badge/twitter-%40kitokeboo-55acee.svg?style=flat-square)](https://twitter.com/kitokeboo)** - Maintainer of the repository - [Snalty](https://github.com/snalty) [![Twitter](https://img.shields.io/badge/twitter-%40snalty-55acee.svg?style=flat-square)](https://twitter.com/snalty) - Designer of the logo - Icon pack sourced from [Material Design Icons](https://materialdesignicons.com/) - [ControlzEx](https://github.com/ControlzEx/ControlzEx) - Library used in MaterialDesignInXAML - [Ignace Maes](https://github.com/IgnaceMaes) - Whose [Material Skin](https://github.com/IgnaceMaes/MaterialSkin) project inspired the original material design theme for [Dragablz](https://github.com/ButchersBoy/Dragablz), which in turn led James Willock start this project - [Material Design Extensions](https://github.com/spiegelp/MaterialDesignExtensions) - A community repository based on this library that provides additional controls and features. - **[Contributors](https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/graphs/contributors)** - A big thank you to all the contributors of the project! ## Backers Thank you to all our backers! 🙏 [Become a backer.](https://opencollective.com/materialdesigninxaml#backer) ## Sponsors Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor.](https://opencollective.com/materialdesigninxaml#sponsor) [discord-server-url]: https://discord.keboo.dev ================================================ FILE: Settings.XamlStyler ================================================ { "IndentSize": 2, "AttributesTolerance": 2, "KeepFirstAttributeOnSameLine": true, "MaxAttributeCharactersPerLine": 0, "MaxAttributesPerLine": 1, "NewlineExemptionElements": "RadialGradientBrush, GradientStop, LinearGradientBrush, ScaleTransform, SkewTransform, RotateTransform, TranslateTransform, Trigger, MultiTrigger, DataTrigger, MultiDataTrigger, Condition, Setter, SolidColorBrush, Pen", "SeparateByGroups": false, "AttributeIndentation": 0, "AttributeIndentationStyle": "Spaces", "RemoveDesignTimeReferences": false, "EnableAttributeReordering": true, "AttributeOrderingRuleGroups": [ "x:Class", "xmlns, xmlns:x", "xmlns:*", "x:Key, Key, x:Name, Name, x:Uid, Uid, Title", "Grid.Row, Grid.RowSpan, Grid.Column, Grid.ColumnSpan, Canvas.Left, Canvas.Top, Canvas.Right, Canvas.Bottom", "Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight", "Margin, Padding, HorizontalAlignment, VerticalAlignment, HorizontalContentAlignment, VerticalContentAlignment, Panel.ZIndex", "*:*, *", "PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint", "*:Freeze, mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText", "Storyboard.*, From, To, Duration", "TargetType", "BasedOn" ], "FirstLineAttributes": "", "OrderAttributesByName": true, "PutEndingBracketOnNewLine": false, "RemoveEndingTagOfEmptyElement": true, "SpaceBeforeClosingSlash": true, "RootElementLineBreakRule": "Always", "ReorderVSM": "First", "ReorderGridChildren": false, "ReorderCanvasChildren": false, "ReorderSetters": "TargetNameThenProperty", "FormatMarkupExtension": true, "NoNewLineMarkupExtensions": "x:Bind, Binding, TemplateBinding, x:Static, DynamicResource, ComponentResourceKey, iconPacks:Modern, iconPacks:Material", "ThicknessSeparator": "Comma", "ThicknessAttributes": "Margin, Padding, BorderThickness, ThumbnailClipMargin", "FormatOnSave": false, "CommentPadding": 1 } ================================================ FILE: build/ApplyXamlStyler.ps1 ================================================ # Reset to repo root Push-Location $(Join-Path $PSScriptRoot "..") # Restore local tool dotnet tool restore #Run XAML Styler xstyler --directory . --config .\Settings.XamlStyler --recursive # Reset location Pop-Location ================================================ FILE: build/BuildNugets.ps1 ================================================ param( [string]$MDIXVersion = "1.0.0", [string]$MDIXColorsVersion = "1.0.0", [string]$MDIXMahAppsVersion = "1.0.0" ) $year = [System.DateTime]::Now.ToString("yyyy") $copyright = "Copyright $year James Willock/Mulholland Software Ltd" $configuration = "Release" function New-DotNetPackage { param ( [string]$ProjectPath, [string]$Version ) $ProjectPath = Resolve-Path $ProjectPath Write-Host "Packing $ProjectPath with version $Version" dotnet pack "$ProjectPath" -c $configuration -p:PackageVersion="$Version" -p:Copyright="$copyright" --no-build -o "." } Push-Location "$(Join-Path $PSScriptRoot "..")" # Pack the projects New-DotNetPackage .\src\MaterialDesignColors.Wpf\MaterialDesignColors.Wpf.csproj $MDIXColorsVersion New-DotNetPackage .\src\MaterialDesignThemes.Wpf\MaterialDesignThemes.Wpf.csproj $MDIXVersion New-DotNetPackage .\src\MaterialDesignThemes.MahApps\MaterialDesignThemes.MahApps.csproj $MDIXMahAppsVersion Pop-Location ================================================ FILE: build/GenerateThemesWikiMarkdown.ps1 ================================================ $defaultStyleText = "(default style)" $headerMarkdown = "##" $listMarkdown = "-" $themesDirectory = "..\src\MaterialDesignThemes.Wpf\Themes\" $latestHash = git log -1 --pretty=format:"%H" $baseURL = "https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/blob" $filePathURL = "src/MaterialDesignThemes.Wpf/Themes" $outputFileName = "ControlStyleList.md" $themesFullDir = Join-Path $PSScriptRoot $themesDirectory $outputFullDir = Join-Path $PSScriptRoot $outputFileName $DebugPreference = 'Continue' # Log debug messages to terminal. $discoverdStyles = New-Object System.Collections.ArrayList $defaults = New-Object System.Collections.ArrayList Function Main { # Get xaml files and loop through. Get-ChildItem $themesFullDir -Filter *.xaml | Foreach-Object { $xamlLines = Get-Content -Path $_.FullName $file = Select-ControlNameFromFile($_.Name) Read-XamlStyles -xamlLines $xamlLines -file $file } Set-Defaults Format-Output } Function Format-Output { Write-OutputFile "[//]: <> (AUTO GENERATED FILE; DO NOT EDIT)" foreach($style in $discoverdStyles | Sort-Object -Property File,@{Expression = {$_.IsDefault}; Ascending = $false}) { if ($previousFile -ne $style.File) { Write-OutputFile "`n$headerMarkdown $($style.File)" } $previousFile = $style.File; $styleLink = "$($baseURL)/$($latestHash)/$($filePathURL)/MaterialDesignTheme.$($style.File).xaml" if ($style.LineNumber) { $styleLink += "#L$($style.LineNumber)" } $linkAndStyleName = "[$($style.Style)]($styleLink)"; if ($style.IsDefault) { Write-OutputFile ("$listMarkdown $($linkAndStyleName) $defaultStyleText" -replace '\s+', ' ') } else { Write-OutputFile "$listMarkdown $($linkAndStyleName)" } } } Function Write-OutputFile{ Param ($output) Add-content $outputFullDir -value $output Write-Debug $output #debug } Function Set-Defaults{ ForEach ($default in $defaults) { $style = $discoverdStyles.Where({$_.style -match $default.style -and $_.Control -match $default.Type}) if ($null -ne $style[0]) { $style[0].IsDefault = $true } else { $temp = Get-Style -targetType $default.Type -styleName $default.Style -fileName $default.Type $discoverdStyles.Add($temp) | Out-Null } } $discoverdStyles | Format-Table #debug } Function Select-ControlNameFromFile { Param ($fileName) return $fileName -replace ".xaml" -replace "MaterialDesignTheme." } Function Read-XamlStyles { Param ($xamlLines, $file) [xml]$xaml = $xamlLines $lineNum = 1 $xaml.ResourceDictionary.Style | Foreach-Object { Write-Output $_ # Get line number by Key or TargetType $styleLineNumber = $null $searchKey = if ($_.Key) { $_.Key } else { $_.TargetType } for ($i = 0; $i -lt $xamlLines.Length; $i++) { if ($xamlLines[$i] -match [regex]::Escape($searchKey)) { $styleLineNumber = $i + 1 break } } if ($file -eq "Defaults") { New-Default -style $_ -file $file -lineNumber $styleLineNumber } elseif ($file -eq "Generic") { New-GenericDefault -style $_ -file $file -lineNumber $styleLineNumber } else { New-Style -style $_ -file $file -lineNumber $styleLineNumber } $lineNum++ } } Function New-GenericDefault { Param ($style, $file, $lineNumber) $targetType = Read-TargetType($style | Select-Object TargetType) $basedOn = Read-BasedOn($style | Select-Object BasedOn) $styleNameValue = ($style | Select-Object Key).Key $defaultStyleName = if ($null -eq $styleNameValue) { $basedOn } else { $styleNameValue } Write-Debug "[$file] [Type: $targetType] [StyleNameValue: $styleNameValue] [BasedOn: $basedOn] [DefaultStyleName: $defaultStyleName]" Add-DefaultStyle -file $file -targetType $targetType -styleName $defaultStyleName -lineNumber $lineNumber } Function New-Default { Param ($style, $file, $lineNumber) $targetType = Read-TargetType($style | Select-Object TargetType) $basedOn = Read-BasedOn($style | Select-Object BasedOn) $styleNameValue = ($style | Select-Object Key).Key $defaultStyleName = if ($null -eq $styleNameValue) { $basedOn } else { $styleNameValue } Write-Debug "[$file] [Type: $targetType] [StyleNameValue: $styleNameValue] [BasedOn: $basedOn] [DefaultStyleName: $defaultStyleName]" Add-DefaultStyle -file $file -targetType $targetType -styleName $defaultStyleName -lineNumber $lineNumber } Function New-Style { Param ($style, $file, $lineNumber) $targetType = Read-TargetType($style | Select-Object TargetType) $styleName = ($style | Select-Object Key).Key $splittedFile = $file.split('.') # Support for "nested" file names like DataGrid.ComboBox if ($targetType -eq $splittedFile[-1]) { Write-Debug "[Match ] [File: $file] [Type: $targetType] [Style: $styleName]" Add-Style -targetType $targetType -styleName $styleName -fileName $file -lineNumber $lineNumber } else { Write-Debug "[Skipped] [File: $file] [Type: $targetType] [Style: $styleName]" } } Function Add-Style { Param ($targetType, $styleName, $fileName, $lineNumber) $temp = Get-Style -targetType $targetType -styleName $styleName -fileName $file -lineNumber $lineNumber $discoverdStyles.Add($temp) | Out-Null } Function Get-Style { Param ($targetType, $styleName, $fileName, $lineNumber) $temp = "" | Select-Object "Control", "Style", "IsDefault", "File", "LineNumber" $temp.Control = $targetType $temp.Style = $styleName $temp.IsDefault = !$styleName $temp.File = $fileName $temp.LineNumber = $lineNumber return $temp } Function Add-DefaultStyle { Param ($file, $targetType, $styleName, $lineNumber) $temp = "" | Select-Object "File", "Type", "Style", "LineNumber" $temp.File = $file $temp.Type = $targetType $temp.Style = $styleName $temp.LineNumber = $lineNumber $defaults.Add($temp) | Out-Null } Function Read-TargetType { Param ($targetTypeText) return ($targetTypeText.TargetType -replace "{x:Type" -replace "{x:Type" -replace ".*:" -replace "}*" -replace "Base").Trim() } Function Read-BasedOn { Param ($targetTypeText) return ($targetTypeText.BasedOn -replace "{StaticResource" -replace ".*:" -replace "}*").Trim() } Main ================================================ FILE: build/MigrateBrushes.ps1 ================================================ param( [System.IO.DirectoryInfo]$RootDirectory ) #NB: This script requires PowerShell 7.1 or later $files = Get-ChildItem -Recurse -Path $RootDirectory -Include "*.xaml" foreach ($file in $files) { $fileContents = Get-Content $file -Encoding utf8BOM -Raw $fileLength = $fileContents.Length $fileContents = $fileContents -replace "\{StaticResource\ PrimaryHueLightBrush}", "{StaticResource MaterialDesign.Brush.Primary.Light}" $fileContents = $fileContents -replace "\{StaticResource\ PrimaryHueLightForegroundBrush}", "{StaticResource MaterialDesign.Brush.Primary.Light.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ PrimaryHueMidBrush}", "{StaticResource MaterialDesign.Brush.Primary}" $fileContents = $fileContents -replace "\{StaticResource\ PrimaryHueMidForegroundBrush}", "{StaticResource MaterialDesign.Brush.Primary.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ PrimaryHueDarkBrush}", "{StaticResource MaterialDesign.Brush.Primary.Dark}" $fileContents = $fileContents -replace "\{StaticResource\ PrimaryHueDarkForegroundBrush}", "{StaticResource MaterialDesign.Brush.Primary.Dark.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ SecondaryHueLightBrush}", "{StaticResource MaterialDesign.Brush.Secondary.Light}" $fileContents = $fileContents -replace "\{StaticResource\ SecondaryHueLightForegroundBrush}", "{StaticResource MaterialDesign.Brush.Secondary.Light.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ SecondaryHueMidBrush}", "{StaticResource MaterialDesign.Brush.Secondary}" $fileContents = $fileContents -replace "\{StaticResource\ SecondaryHueMidForegroundBrush}", "{StaticResource MaterialDesign.Brush.Secondary.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ SecondaryHueDarkBrush}", "{StaticResource MaterialDesign.Brush.Secondary.Dark}" $fileContents = $fileContents -replace "\{StaticResource\ SecondaryHueDarkForegroundBrush}", "{StaticResource MaterialDesign.Brush.Secondary.Dark.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignPaper}", "{StaticResource MaterialDesign.Brush.Background}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignFlatButtonClick}", "{StaticResource MaterialDesign.Brush.Button.FlatClick}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignFlatButtonRipple}", "{StaticResource MaterialDesign.Brush.Button.Ripple}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignSnackbarRipple}", "{StaticResource MaterialDesign.Brush.Button.Ripple}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignBackground}", "{StaticResource MaterialDesign.Brush.Card.Background}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignCardBackground}", "{StaticResource MaterialDesign.Brush.Card.Background}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignCheckBoxDisabled}", "{StaticResource MaterialDesign.Brush.CheckBox.Disabled}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignChipBackground}", "{StaticResource MaterialDesign.Brush.Chip.Background}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignDataGridRowHoverBackground}", "{StaticResource MaterialDesign.Brush.DataGrid.RowHoverBackground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignBody}", "{StaticResource MaterialDesign.Brush.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignBodyLight}", "{StaticResource MaterialDesign.Brush.ForegroundLight}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignCheckBoxOff}", "{StaticResource MaterialDesign.Brush.ForegroundLight}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignTextBoxBorder}", "{StaticResource MaterialDesign.Brush.ForegroundLight}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignColumnHeader}", "{StaticResource MaterialDesign.Brush.Header.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignTextAreaBorder}", "{StaticResource MaterialDesign.Brush.Header.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignSnackbarBackground}", "{StaticResource MaterialDesign.Brush.SnackBar.Background}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignSnackbarMouseOver}", "{StaticResource MaterialDesign.Brush.SnackBar.MouseOver}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignTextFieldBoxDisabledBackground}", "{StaticResource MaterialDesign.Brush.TextBox.DisabledBackground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignTextFieldBoxBackground}", "{StaticResource MaterialDesign.Brush.TextBox.FilledBackground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignTextFieldBoxHoverBackground}", "{StaticResource MaterialDesign.Brush.TextBox.HoverBackground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignDivider}", "{StaticResource MaterialDesign.Brush.TextBox.HoverBackground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignTextAreaInactiveBorder}", "{StaticResource MaterialDesign.Brush.TextBox.OutlineInactiveBorder}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignToolBarBackground}", "{StaticResource MaterialDesign.Brush.ToolBar.Background}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignToolBackground}", "{StaticResource MaterialDesign.Brush.ToolBar.Item.Background}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignToolForeground}", "{StaticResource MaterialDesign.Brush.ToolBar.Item.Foreground}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignToolTipBackground}", "{StaticResource MaterialDesign.Brush.ToolTip.Background}" $fileContents = $fileContents -replace "\{StaticResource\ MaterialDesignValidationErrorBrush}", "{StaticResource MaterialDesign.Brush.ValidationError}" if ($fileContents.Length -ne $fileLength) { Set-Content -Path $file -Value $fileContents -Encoding utf8BOM -NoNewline } } ================================================ FILE: build/MigrateStyles.ps1 ================================================ param( [System.IO.DirectoryInfo]$RootDirectory ) #NB: This script requires PowerShell 7.1 or later $files = Get-ChildItem -Recurse -Path $RootDirectory -File -Filter "*.xaml" $resourceTypes = ('StaticResource', 'DynamicResource') foreach ($file in $files) { $fileContents = Get-Content $file -Encoding utf8BOM -Raw $fileLength = $fileContents.Length foreach($resourceType in $resourceTypes) { $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignActionAccentCheckBox}", "{$resourceType MaterialDesignActionSecondaryCheckBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignAccentCheckBox}", "{$resourceType MaterialDesignSecondaryCheckBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignAccentRadioButton}", "{$resourceType MaterialDesignSecondaryRadioButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignActionAccentToggleButton}", "{$resourceType MaterialDesignActionSecondaryToggleButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignChoiceChipAccentListBox}", "{$resourceType MaterialDesignChoiceChipSecondaryListBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignChoiceChipAccentListBoxItem}", "{$resourceType MaterialDesignChoiceChipSecondaryListBoxItem}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignChoiceChipAccentOutlineListBox}", "{$resourceType MaterialDesignChoiceChipSecondaryOutlineListBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignChoiceChipAccentOutlineListBoxItem}", "{$resourceType MaterialDesignChoiceChipSecondaryOutlineListBoxItem}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignChoiceChipAccentOutlineRadioButton}", "{$resourceType MaterialDesignChoiceChipSecondaryOutlineRadioButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignChoiceChipAccentRadioButton}", "{$resourceType MaterialDesignChoiceChipSecondaryRadioButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFilterChipAccentCheckBox}", "{$resourceType MaterialDesignFilterChipSecondaryCheckBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFilterChipAccentListBoxItem}", "{$resourceType MaterialDesignFilterChipSecondaryListBoxItem}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFilterChipAccentListBox}", "{$resourceType MaterialDesignFilterChipSecondaryListBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFilterChipAccentOutlineCheckBox}", "{$resourceType MaterialDesignFilterChipSecondaryOutlineCheckBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFilterChipAccentOutlineListBox}", "{$resourceType MaterialDesignFilterChipSecondaryOutlineListBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFilterChipAccentOutlineListBoxItem}", "{$resourceType MaterialDesignFilterChipSecondaryOutlineListBoxItem}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFlatAccentButton}", "{$resourceType MaterialDesignFlatSecondaryMidBgButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFlatAccentBgButton}", "{$resourceType MaterialDesignFlatSecondaryBgButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFloatingActionMiniAccentButton}", "{$resourceType MaterialDesignFloatingActionMiniSecondaryButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignFloatingActionAccentButton}", "{$resourceType MaterialDesignFloatingActionSecondaryButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignMultiFloatingActionAccentPopupBox}", "{$resourceType MaterialDesignMultiFloatingActionSecondaryPopupBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignNavigationAccentListBoxItem}", "{$resourceType MaterialDesignNavigationSecondaryListBoxItem}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignNavigationAccentListBox}", "{$resourceType MaterialDesignNavigationSecondaryListBox}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignRaisedAccentButton}", "{$resourceType MaterialDesignRaisedSecondaryButton}" $fileContents = $fileContents -replace "\{$resourceType\ MaterialDesignSwitchAccentToggleButton}", "{$resourceType MaterialDesignSwitchSecondaryToggleButton}" } if ($fileContents.Length -ne $fileLength) { Set-Content -Path $file -Value $fileContents -Encoding utf8BOM -NoNewline } } ================================================ FILE: build/UpdateNugets.ps1 ================================================ param( [string]$Path, [string]$MDIXVersion = "1.0.0", [string]$MDIXColorsVersion = "1.0.0", [string]$MDIXMahAppsVersion = "1.0.0" ) function Get-VersionString { param ( [string]$Version ) $incrementCallback = { [int]$args[0].Groups[1].Value + 1 } $releaseVersionCallback = { "$($args[0].Groups[1].Value).$($args[0].Groups[2].Value)" } $re = [regex]"^(\d+)\.(\d+\.\d+).*" $releaseVersion = $re.Replace($Version, $releaseVersionCallback) $nextVersion = $re.Replace($Version, $incrementCallback) return "[$releaseVersion,$nextVersion)" } Push-Location "$(Join-Path $PSScriptRoot "..")" $Path = Resolve-Path $Path nupkgwrench nuspec dependencies modify "$Path" --dependency-id "MaterialDesignThemes" --dependency-version "$(Get-VersionString $MDIXVersion)" nupkgwrench nuspec dependencies modify "$Path" --dependency-id "MaterialDesignColors" --dependency-version "$(Get-VersionString $MDIXColorsVersion)" nupkgwrench nuspec dependencies modify "$Path" --dependency-id "MaterialDesignThemes.MahApps" --dependency-version "$(Get-VersionString $MDIXMahAppsVersion)" Pop-Location ================================================ FILE: docs/Freezable_Object_for_Enhanced_Performance.md ================================================ [Home](..\README.md) > Using `Freezable` Objects for Enhanced Performance --- # Using `Freezable` Objects for Enhanced Performance ## Background information WPF provides the `Freezable` class for objects that can be made immutable to optimize performance, such as brushes, pens, and transforms. ## Setting Objects as `Freezable` When an object is frozen, it becomes immutable, which reduces memory usage and allows WPF to optimize rendering. ```csharp SolidColorBrush myBrush = new SolidColorBrush(Colors.Blue); if (myBrush.CanFreeze) { myBrush.Freeze(); } ``` Frozen objects cannot be modified, so only freeze objects that don’t require changes. ## Benefits of Freezable Objects Freezable objects improve rendering speed, especially for large visuals or repeated animations. This technique is particularly useful in complex UIs with many reused resources. ================================================ FILE: docs/Optimize_UI_Thread_Performance.md ================================================ [Home](..\README.md) > How to Optimize UI Thread Performance? --- # How to Optimize UI Thread Performance? ## Background information The UI thread in WPF is responsible for rendering controls and handling user interactions. Heavy computations or complex bindings on the UI thread can lead to sluggish performance and poor user experience. ## Using `Dispatcher.BeginInvoke` For non-UI-intensive tasks that still need to interact with the UI, use `Dispatcher.BeginInvoke` to move tasks off the UI thread without blocking it: ```csharp // Execute this in the background without freezing the UI Dispatcher.BeginInvoke((Action)(() => { // Update UI elements here })); ``` ## Avoiding Complex Bindings Complex bindings, especially with large data sets, can slow down the UI. Consider simplifying bindings, reducing converters, or using `INotifyPropertyChanged` with view models to optimize data flow. ```xaml ``` > [!NOTE] > Always test performance impacts when using nested or complex bindings. ## Use `VirtualizingStackPanel` for Large Lists For large collections, use `VirtualizingStackPanel` to only create visuals for items in view: ```xaml ``` This reduces memory usage and improves scrolling performance in lists. ================================================ FILE: docs/Optimizing-WPF-Rendering-Performance.md ================================================ [Home](..\README.md) > Optimizing WPF UI Animation and Rendering Performance --- # Optimizing WPF UI Animation and Rendering Performance ## Background Information WPF applications often have complex animations and UI interactions, which can lead to performance bottlenecks if not optimized. Understanding the techniques for efficient rendering and leveraging WPF's internal capabilities can significantly enhance the user experience by making the interface smoother and more responsive. ## Reducing Visual Complexity One effective approach to improving rendering performance is reducing visual complexity. This involves: - **Minimizing Visual Layers**: Each layer that a control or element has can add rendering overhead. Consider consolidating overlapping elements. - **Avoiding Overdraw**: Redundant drawing layers, where multiple visual elements overlap, increase rendering work for the GPU. Arrange visuals to reduce the overdraw effect. - **Limiting the Use of Effects**: Avoid heavy effects such as `DropShadowEffect` or `BlurEffect` where possible, as these can slow down rendering. ## Using the `RenderOptions` Property The `RenderOptions` class in WPF provides properties for fine-tuning rendering options. The `BitmapScalingMode` property, for instance, helps adjust the scaling performance of images. ```xaml ``` Setting `BitmapScalingMode` to `LowQuality` helps improve performance when scaling images, especially useful for animations. > [!TIP] > Use `HighQuality` scaling mode sparingly, as it increases GPU workload. ## Implementing Virtualization For controls that display large data sets, such as `ListView` or `DataGrid`, enable virtualization to improve scrolling performance: ```xaml ``` Virtualization helps reduce memory usage by creating only the items currently in view, thus speeding up scrolling and rendering. ## Optimize Animation with CompositionTarget For custom animations, consider leveraging `CompositionTarget.Rendering`, which allows you to hook into the render loop directly: ```csharp CompositionTarget.Rendering += (s, e) => { // Custom animation logic }; ``` This method provides more control over frame-by-frame updates, but should be used cautiously as it can impact performance if not handled efficiently. ## Example Comparison | Method | Performance Impact | | ---------------------------------- | ---------------------------------------------------------------------------------------------------- | | Reducing Visual Layers | Lowers CPU and GPU workload by limiting the number of visual elements rendered | | Using `RenderOptions.BitmapScalingMode` | Improves image scaling performance, particularly during animation | | Enabling Virtualization | Optimizes scrolling in large data sets, leading to faster rendering times | | `CompositionTarget` for Animations | Provides smoother animations at the expense of higher complexity; best suited for high-priority elements | ## Further Reading Additional resources for improving WPF performance: - [Optimizing WPF Application Performance](https://learn.microsoft.com/dotnet/desktop/wpf/advanced/optimizing-wpf-application-performance?view=netdesktop-7.0) - [Rendering Performance Best Practices](https://learn.microsoft.com/dotnet/desktop/wpf/graphics-multimedia/rendering-performance-best-practices?view=netdesktop-7.0) ================================================ FILE: docs/Reducing_Layout_Complexity.md ================================================ # Reducing Layout Complexity ## Background information Complex layouts can slow down WPF performance, especially with nested controls or excessive use of `Grid` and `StackPanel`. ## Avoid Nested Grids and StackPanels Overuse of nested layouts can create rendering bottlenecks. Try to simplify the structure or use a `UniformGrid` or `DockPanel` for simpler arrangements. ```xaml ``` ## Prefer Static Resources Over Dynamic Resources Static resources are faster to load compared to dynamic ones. Use dynamic resources only if you need runtime changes in resource values. ```xaml ================================================ FILE: src/MahMaterialDragablzMashUp/Dialogs.xaml.cs ================================================ namespace MahMaterialDragablzMashUp; /// /// Interaction logic for Dialogs.xaml /// public partial class Dialogs : UserControl { public Dialogs() { InitializeComponent(); } } ================================================ FILE: src/MahMaterialDragablzMashUp/DialogsViewModel.cs ================================================ using MahApps.Metro.Controls; using MahApps.Metro.Controls.Dialogs; namespace MahMaterialDragablzMashUp; public class DialogsViewModel { public ICommand ShowInputDialogCommand { get; } public ICommand ShowProgressDialogCommand { get; } public ICommand ShowLeftFlyoutCommand { get; } private ResourceDictionary DialogDictionary = new ResourceDictionary() { Source = new Uri("pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Dialogs.xaml") }; public DialogsViewModel() { ShowInputDialogCommand = new AnotherCommandImplementation(_ => InputDialog()); ShowProgressDialogCommand = new AnotherCommandImplementation(_ => ProgressDialog()); ShowLeftFlyoutCommand = new AnotherCommandImplementation(_ => ShowLeftFlyout()); } public Flyout? LeftFlyout { get; set; } private void InputDialog() { var metroDialogSettings = new MetroDialogSettings { CustomResourceDictionary = DialogDictionary, NegativeButtonText = "CANCEL" }; DialogCoordinator.Instance.ShowInputAsync(this, "MahApps Dialog", "Using Material Design Themes", metroDialogSettings); } private async void ProgressDialog() { var metroDialogSettings = new MetroDialogSettings { CustomResourceDictionary = DialogDictionary, NegativeButtonText = "CANCEL" }; var controller = await DialogCoordinator.Instance.ShowProgressAsync(this, "MahApps Dialog", "Using Material Design Themes (WORK IN PROGRESS)", true, metroDialogSettings); controller.SetIndeterminate(); await Task.Delay(3000); await controller.CloseAsync(); } private void ShowLeftFlyout() { ((MainWindow)Application.Current.MainWindow).LeftFlyout.IsOpen = !((MainWindow)Application.Current.MainWindow).LeftFlyout.IsOpen; } } ================================================ FILE: src/MahMaterialDragablzMashUp/FlyoutContent.xaml ================================================  ================================================ FILE: src/MahMaterialDragablzMashUp/FlyoutContent.xaml.cs ================================================ namespace MahMaterialDragablzMashUp; /// /// Interaction logic for FlyoutContent.xaml /// public partial class FlyoutContent : UserControl { public FlyoutContent() { InitializeComponent(); } } ================================================ FILE: src/MahMaterialDragablzMashUp/Mah.xaml ================================================  All controls using MahApps themes, will use Material Design pallete. MahApps Dragablz Material Standard Style Alternate Style Light Dark ================================================ FILE: src/MahMaterialDragablzMashUp/PaletteSelector.xaml.cs ================================================ namespace MahMaterialDragablzMashUp; /// /// Interaction logic for Palette.xaml /// public partial class PaletteSelector : UserControl { public PaletteSelector() { InitializeComponent(); } } ================================================ FILE: src/MahMaterialDragablzMashUp/PaletteSelectorViewModel.cs ================================================ using System.ComponentModel; using MaterialDesignColors; using MaterialDesignThemes.Wpf; namespace MahMaterialDragablzMashUp; public class PaletteSelectorViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; public PaletteSelectorViewModel() { Swatches = new SwatchesProvider().Swatches; PaletteHelper paletteHelper = new PaletteHelper(); Theme theme = paletteHelper.GetTheme(); IsDarkTheme = theme.GetBaseTheme() == BaseTheme.Dark; } public ICommand ToggleStyleCommand { get; } = new AnotherCommandImplementation(o => ApplyStyle((bool)o!)); public IEnumerable Swatches { get; } public ICommand ApplyPrimaryCommand { get; } = new AnotherCommandImplementation(o => ApplyPrimary((Swatch)o!)); public ICommand ApplySecondaryCommand { get; } = new AnotherCommandImplementation(o => ApplySecondary((Swatch)o!)); private bool _isDarkTheme; public bool IsDarkTheme { get => _isDarkTheme; set { if (_isDarkTheme != value) { _isDarkTheme = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsDarkTheme))); ApplyBase(value); } } } private static void ApplyStyle(bool alternate) { var resourceDictionary = new ResourceDictionary { Source = new Uri(@"pack://application:,,,/Dragablz;component/Themes/materialdesign.xaml") }; var styleKey = alternate ? "MaterialDesignAlternateTabablzControlStyle" : "MaterialDesignTabablzControlStyle"; var style = (Style)resourceDictionary[styleKey]; foreach (var tabablzControl in Dragablz.TabablzControl.GetLoadedInstances()) { tabablzControl.Style = style; } } private static void ApplyBase(bool isDark) => ModifyTheme(theme => theme.SetBaseTheme(isDark ? BaseTheme.Dark : BaseTheme.Light)); private static void ApplyPrimary(Swatch swatch) => ModifyTheme(theme => theme.SetPrimaryColor(swatch.ExemplarHue.Color)); private static void ApplySecondary(Swatch swatch) { if (swatch.SecondaryExemplarHue is Hue secondaryHue) { ModifyTheme(theme => theme.SetSecondaryColor(secondaryHue.Color)); } } private static void ModifyTheme(Action modificationAction) { PaletteHelper paletteHelper = new PaletteHelper(); Theme theme = paletteHelper.GetTheme(); modificationAction?.Invoke(theme); paletteHelper.SetTheme(theme); } } ================================================ FILE: src/MahMaterialDragablzMashUp/Properties/AssemblyInfo.cs ================================================ using System.Runtime.InteropServices; // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] //In order to begin building localizable applications, set //CultureYouAreCodingWith in your .csproj file //inside a . For example, if you are using US english //in your source files, set the to en-US. Then uncomment //the NeutralResourceLanguage attribute below. Update the "en-US" in //the line below to match the UICulture setting in the project file. //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] [assembly: ThemeInfo( ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located //(used if a resource is not found in the page, // or application resource dictionaries) ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located //(used if a resource is not found in the page, // app, or any theme specific resource dictionaries) )] ================================================ FILE: src/MahMaterialDragablzMashUp/Properties/Resources.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace MahAppsDragablzDemo.Properties; using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MahAppsDragablzDemo.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } } ================================================ FILE: src/MahMaterialDragablzMashUp/Properties/Resources.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/MahMaterialDragablzMashUp/Properties/Settings.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace MahAppsDragablzDemo.Properties; [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { get { return defaultInstance; } } } ================================================ FILE: src/MahMaterialDragablzMashUp/Properties/Settings.settings ================================================  ================================================ FILE: src/MahMaterialDragablzMashUp/XamlDisplayEx.cs ================================================ namespace MahAppsDragablzDemo; public static class XamlDisplayEx { public static readonly DependencyProperty ButtonDockProperty = DependencyProperty.RegisterAttached( "ButtonDock", typeof(Dock), typeof(XamlDisplayEx), new PropertyMetadata(default(Dock))); public static void SetButtonDock(DependencyObject element, Dock value) { element.SetValue(ButtonDockProperty, value); } public static Dock GetButtonDock(DependencyObject element) { return (Dock)element.GetValue(ButtonDockProperty); } } ================================================ FILE: src/MainDemo.Wpf/App.config ================================================ ================================================ FILE: src/MainDemo.Wpf/App.manifest ================================================  PerMonitorV2, PerMonitor, System true ================================================ FILE: src/MainDemo.Wpf/App.xaml ================================================ 124 50 ================================================ FILE: src/MainDemo.Wpf/Buttons.xaml.cs ================================================ using System.Diagnostics; using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo; public partial class Buttons { public Buttons() { DataContext = new ButtonsViewModel(); InitializeComponent(); } private void ButtonBase_OnClick(object sender, RoutedEventArgs e) => Debug.WriteLine("Just checking we haven't suppressed the button."); private void PopupBox_OnOpened(object sender, RoutedEventArgs e) => Debug.WriteLine("Just making sure the popup has opened."); private void PopupBox_OnClosed(object sender, RoutedEventArgs e) => Debug.WriteLine("Just making sure the popup has closed."); private void CountingButton_OnClick(object sender, RoutedEventArgs e) { if (CountingBadge.Badge == null || Equals(CountingBadge.Badge, string.Empty)) CountingBadge.Badge = 0; int next = int.Parse(CountingBadge.Badge.ToString() ?? "0") + 1; CountingBadge.Badge = next < 21 ? (object)next : null; } } ================================================ FILE: src/MainDemo.Wpf/Cards.xaml ================================================  Cycling Outlined style ================================================ FILE: src/MainDemo.Wpf/ColorTool.xaml.cs ================================================ using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo; public partial class ColorTool { public ColorTool() { DataContext = new ColorToolViewModel(); InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/ColorZones.xaml ================================================  Information Links: ================================================ FILE: src/MainDemo.Wpf/Domain/DocumentationLinks.xaml.cs ================================================ namespace MaterialDesignDemo.Domain; /// /// Interaction logic for DocumentationLinks.xaml /// public partial class DocumentationLinks : UserControl { public DocumentationLinks() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/Domain/FieldsViewModel.cs ================================================ using System.Collections.ObjectModel; using System.Windows.Media; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo.Domain; public partial class FieldsViewModel : ObservableObject { private string? _password1Validated = "pre-filled"; private string? _password2Validated = "pre-filled"; private readonly List? _originalAutoSuggestBox1Suggestions; private readonly List>? _originalAutoSuggestBox2Suggestions; private readonly List _originalAutoSuggestBox3Suggestions; [ObservableProperty] private string? _name; [ObservableProperty] private string? _name2; [ObservableProperty] private string? _text1; [ObservableProperty] private string? _text2; [ObservableProperty] private string? _password1 = string.Empty; [ObservableProperty] private string? _password2 = "pre-filled"; public string? Password1Validated { get => _password1Validated; set { if (string.IsNullOrEmpty(value)) throw new ArgumentException("Password cannot be empty"); SetProperty(ref _password1Validated, value); } } public string? Password2Validated { get => _password2Validated; set { if (string.IsNullOrEmpty(value)) throw new ArgumentException("Password cannot be empty"); SetProperty(ref _password2Validated, value); } } public FieldsTestObject TestObject => new() { Name = "Mr. Test" }; [ObservableProperty] private ObservableCollection? _autoSuggestBox1Suggestions; [ObservableProperty] private ObservableCollection>? _autoSuggestBox2Suggestions; [ObservableProperty] private List? _autoSuggestBox3Suggestions; [ObservableProperty] private string? _autoSuggestBox1Text; partial void OnAutoSuggestBox1TextChanged(string? value) { if (_originalAutoSuggestBox1Suggestions != null && value != null) { var searchResult = _originalAutoSuggestBox1Suggestions.Where(x => IsMatch(x, value)); AutoSuggestBox1Suggestions = new(searchResult); } } [ObservableProperty] private string? _autoSuggestBox2Text; partial void OnAutoSuggestBox2TextChanged(string? value) { if (_originalAutoSuggestBox2Suggestions != null && value != null) { var searchResult = _originalAutoSuggestBox2Suggestions.Where(x => IsMatch(x.Key, value)); AutoSuggestBox2Suggestions = new(searchResult); } } [ObservableProperty] private string? _autoSuggestBox3Text; partial void OnAutoSuggestBox3TextChanged(string? value) { if (value is not null) { var searchResult = _originalAutoSuggestBox3Suggestions.Where(x => IsMatch(x, value)); AutoSuggestBox3Suggestions = new(searchResult); } } [RelayCommand] private void RemoveAutoSuggestBox3Suggestion(string suggestion) { _originalAutoSuggestBox3Suggestions.Remove(suggestion); if (string.IsNullOrEmpty(AutoSuggestBox3Text)) { AutoSuggestBox3Suggestions = new(_originalAutoSuggestBox3Suggestions); } else { var searchResult = _originalAutoSuggestBox3Suggestions.Where(x => IsMatch(x, AutoSuggestBox3Text!)); AutoSuggestBox3Suggestions = new(searchResult); } } public ICommand SetPassword1FromViewModelCommand { get; } public ICommand SetPassword2FromViewModelCommand { get; } public FieldsViewModel() { SetPassword1FromViewModelCommand = new AnotherCommandImplementation(_ => Password1 = "Set from ViewModel!"); SetPassword2FromViewModelCommand = new AnotherCommandImplementation(_ => Password2 = "Set from ViewModel!"); _originalAutoSuggestBox1Suggestions = [ "Burger", "Fries", "Shake", "Lettuce" ]; _originalAutoSuggestBox2Suggestions = new(GetColors()); _originalAutoSuggestBox3Suggestions = [ "jsmith", "jdoe", "mscott", "pparker", "bwilliams", "ljohnson", "abrown", "dlee", "cmiller", "tmoore" ]; AutoSuggestBox1Suggestions = new ObservableCollection(_originalAutoSuggestBox1Suggestions); } private static bool IsMatch(string item, string currentText) { #if NET6_0_OR_GREATER return item.Contains(currentText, StringComparison.OrdinalIgnoreCase); #else return item.IndexOf(currentText, StringComparison.OrdinalIgnoreCase) >= 0; #endif } private static IEnumerable> GetColors() { return typeof(Colors) .GetProperties() .Where(prop => typeof(Color).IsAssignableFrom(prop.PropertyType)) .Select(prop => new KeyValuePair(prop.Name, (Color)prop.GetValue(null)!)); } } public partial class FieldsTestObject : ObservableObject { [ObservableProperty] private string? _name; [ObservableProperty] private string? _content; } ================================================ FILE: src/MainDemo.Wpf/Domain/FutureDateValidationRule.cs ================================================ using System.Globalization; namespace MaterialDesignDemo.Domain; public class FutureDateValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { DateTime time; if (!DateTime.TryParse((value ?? "").ToString(), CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal | DateTimeStyles.AllowWhiteSpaces, out time)) return new ValidationResult(false, "Invalid date"); return time.Date <= DateTime.Now.Date ? new ValidationResult(false, "Future date required") : ValidationResult.ValidResult; } } ================================================ FILE: src/MainDemo.Wpf/Domain/IconPackViewModel.cs ================================================ using System.Windows.Media; using System.Windows.Media.Imaging; using BluwolfIcons; using MaterialDesignDemo.Shared.Domain; using MaterialDesignThemes.Wpf; using Microsoft.Win32; namespace MaterialDesignDemo.Domain; public class IconPackViewModel : ViewModelBase { private readonly Lazy> _packIconKinds; private readonly ISnackbarMessageQueue _snackbarMessageQueue; public IconPackViewModel(ISnackbarMessageQueue snackbarMessageQueue) { _snackbarMessageQueue = snackbarMessageQueue ?? throw new ArgumentNullException(nameof(snackbarMessageQueue)); OpenDotComCommand = new AnotherCommandImplementation(OpenDotCom); SearchCommand = new AnotherCommandImplementation(Search); CopyToClipboardCommand = new AnotherCommandImplementation(CopyToClipboard); _packIconKinds = new Lazy>(() => Enum.GetNames(typeof(PackIconKind)) .GroupBy(k => (PackIconKind)Enum.Parse(typeof(PackIconKind), k)) .Select(g => new PackIconKindGroup(g)) .OrderBy(x => x.Kind) .ToList()); var helper = new PaletteHelper(); if (helper.GetThemeManager() is { } themeManager) { themeManager.ThemeChanged += ThemeManager_ThemeChanged; } SetDefaultIconColors(); } private void ThemeManager_ThemeChanged(object? sender, ThemeChangedEventArgs e) => SetDefaultIconColors(); public ICommand OpenDotComCommand { get; } public ICommand SearchCommand { get; } public ICommand CopyToClipboardCommand { get; } private IEnumerable? _kinds; private PackIconKindGroup? _group; private string? _kind; private PackIconKind _packIconKind; public IEnumerable Kinds { get => _kinds ??= _packIconKinds.Value; set => SetProperty(ref _kinds, value); } public PackIconKindGroup? Group { get => _group; set { if (SetProperty(ref _group, value)) { Kind = value?.Kind; } } } public string? Kind { get => _kind; set { if (SetProperty(ref _kind, value)) { PackIconKind = value != null ? (PackIconKind)Enum.Parse(typeof(PackIconKind), value) : default; } } } public PackIconKind PackIconKind { get => _packIconKind; set => SetProperty(ref _packIconKind, value); } private void OpenDotCom(object? _) => Link.OpenInBrowser("https://materialdesignicons.com/"); private async void Search(object? obj) { var text = obj as string; if (string.IsNullOrWhiteSpace(text)) { Kinds = _packIconKinds.Value; } else { Kinds = await Task.Run(() => _packIconKinds.Value .Where(x => x.Aliases.Any(a => a.IndexOf(text, StringComparison.CurrentCultureIgnoreCase) >= 0)) .ToList()); } } private void CopyToClipboard(object? obj) { var toBeCopied = $""; Clipboard.SetDataObject(toBeCopied); _snackbarMessageQueue.Enqueue(toBeCopied + " copied to clipboard"); } private void SetDefaultIconColors() { var helper = new PaletteHelper(); Theme theme = helper.GetTheme(); GeneratedIconBackground = theme.Background; GeneratedIconForeground = theme.PrimaryMid.Color; } private Color _generatedIconBackground; public Color GeneratedIconBackground { get => _generatedIconBackground; set => SetProperty(ref _generatedIconBackground, value); } private Color _generatedIconForeground; public Color GeneratedIconForeground { get => _generatedIconForeground; set => SetProperty(ref _generatedIconForeground, value); } private ICommand? _saveIconCommand; public ICommand SaveIconCommand => _saveIconCommand ??= new AnotherCommandImplementation(OnSaveIcon); private void OnSaveIcon(object? _) { var saveDialog = new SaveFileDialog { DefaultExt = ".ico", Title = "Save Icon (.ico)", Filter = "Icon Files|*.ico|All Files|*", CheckPathExists = true, OverwritePrompt = true, RestoreDirectory = true }; if (saveDialog.ShowDialog() != true) return; var icon = new Icon(); //TODO: Make this size list configurable foreach (var size in new[] { 256, 128, 64, 48, 32, 24, 16 }) { RenderTargetBitmap bmp = RenderImage(size); icon.Images.Add(new BmpIconImage(bmp)); } icon.Save(saveDialog.FileName); RenderTargetBitmap RenderImage(int size) { var packIcon = new PackIcon { Kind = PackIconKind, Background = new SolidColorBrush(GeneratedIconBackground), Foreground = new SolidColorBrush(GeneratedIconForeground), Width = size, Height = size, Style = (Style)Application.Current.FindResource(typeof(PackIcon)) }; packIcon.Measure(new Size(size, size)); packIcon.Arrange(new Rect(0, 0, size, size)); packIcon.UpdateLayout(); RenderTargetBitmap bmp = new(size, size, 96, 96, PixelFormats.Pbgra32); bmp.Render(packIcon); return bmp; } } } ================================================ FILE: src/MainDemo.Wpf/Domain/IsCheckedValidationRule.cs ================================================ using System.Globalization; namespace MaterialDesignDemo.Domain; public class IsCheckedValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { if (value is bool && (bool)value) { return ValidationResult.ValidResult; } return new ValidationResult(false, "Option must be checked"); } } ================================================ FILE: src/MainDemo.Wpf/Domain/Link.cs ================================================ using System.Diagnostics; using System.Runtime.InteropServices; namespace MaterialDesignDemo.Domain; public static class Link { public static void OpenInBrowser(string? url) { if (url is not null && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); } } } ================================================ FILE: src/MainDemo.Wpf/Domain/ListsAndGridsViewModel.cs ================================================ using System.Collections.ObjectModel; using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo.Domain; public class ListsAndGridsViewModel : ViewModelBase { public ListsAndGridsViewModel() { Items1 = CreateData(); Items2 = CreateData(); Items3 = CreateData(); Items4 = CreateData(); foreach (var model in Items1) { model.PropertyChanged += (sender, args) => { if (args.PropertyName == nameof(SelectableViewModel.IsSelected)) OnPropertyChanged(nameof(IsAllItems1Selected)); }; } Files = new List(); for (int i = 0; i < 1000; i++) { Files.Add(Path.GetRandomFileName()); } } public bool? IsAllItems1Selected { get { var selected = Items1.Select(item => item.IsSelected).Distinct().ToList(); return selected.Count == 1 ? selected.Single() : (bool?)null; } set { if (value.HasValue) { SelectAll(value.Value, Items1); OnPropertyChanged(); } } } private static void SelectAll(bool select, IEnumerable models) { foreach (var model in models) { model.IsSelected = select; } } private static ObservableCollection CreateData() { return new ObservableCollection { new SelectableViewModel { Code = 'M', Name = "Material Design", Description = "Material Design in XAML Toolkit" }, new SelectableViewModel { Code = 'D', Name = "Dragablz", Description = "Dragablz Tab Control", Food = "Fries" }, new SelectableViewModel { Code = 'P', Name = "Predator", Description = "If it bleeds, we can kill it" } }; } public ObservableCollection Items1 { get; } public ObservableCollection Items2 { get; } public ObservableCollection Items3 { get; } public ObservableCollection Items4 { get; } public IEnumerable Foods => new[] { "Burger", "Fries", "Shake", "Lettuce" }; public IList Files { get; } public IEnumerable SelectionUnits => new[] { DataGridSelectionUnit.FullRow, DataGridSelectionUnit.Cell, DataGridSelectionUnit.CellOrRowHeader }; } ================================================ FILE: src/MainDemo.Wpf/Domain/MainWindowViewModel.cs ================================================ using System.Collections.ObjectModel; using System.ComponentModel; using System.Configuration; using System.Reflection; using System.Windows.Data; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using MaterialDesignColors; using MaterialDesignDemo.Shared.Domain; using MaterialDesignThemes.Wpf; using MaterialDesignThemes.Wpf.Transitions; namespace MaterialDesignDemo.Domain; public partial class MainWindowViewModel : ObservableObject { public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue, string? startupPage) { DemoItems = [ new DemoItem( "Home", typeof(Home), [ new DocumentationLink( DocumentationLinkType.Wiki, $"{ConfigurationManager.AppSettings["GitHub"]}/wiki", "WIKI"), DocumentationLink.DemoPageLink() ] ) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled }, .. GenerateDemoItems(snackbarMessageQueue).OrderBy(i => i.Name), ]; SelectedItem = DemoItems.FirstOrDefault(di => string.Equals(di.Name, startupPage, StringComparison.CurrentCultureIgnoreCase)) ?? DemoItems.First(); _demoItemsView = CollectionViewSource.GetDefaultView(DemoItems); _demoItemsView.Filter = DemoItemsFilter; LoadVersions(); } private readonly ICollectionView _demoItemsView; [ObservableProperty] private string? _searchKeyword; partial void OnSearchKeywordChanged(string? oldValue, string? newValue) { _demoItemsView.Refresh(); } [ObservableProperty] private string? _nugetVersions; private void LoadVersions() { string? mdixVersion = GetVersion("MDIXVersion"); string? mdixColorsVersion = GetVersion("MDIXColorsVersion"); NugetVersions = $""" MDIX: {mdixVersion} MDIX Colors: {mdixColorsVersion} """; static string? GetVersion(string attributeKey) { return typeof(T).Assembly .GetCustomAttributes() .SingleOrDefault(x => x.Key == attributeKey)?.Value; } } public ObservableCollection DemoItems { get; } [ObservableProperty] private DemoItem? _selectedItem; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(MoveNextCommand))] [NotifyCanExecuteChangedFor(nameof(MovePrevCommand))] private int _selectedIndex; [ObservableProperty] private bool _controlsEnabled = true; [RelayCommand] private void OnHome() { SearchKeyword = string.Empty; SelectedIndex = 0; } [RelayCommand(CanExecute = nameof(CanMovePrevious))] private void OnMovePrev() { if (!string.IsNullOrWhiteSpace(SearchKeyword)) SearchKeyword = string.Empty; SelectedIndex--; } private bool CanMovePrevious() => SelectedIndex > 0; [RelayCommand(CanExecute = nameof(CanMoveNext))] private void OnMoveNext() { if (!string.IsNullOrWhiteSpace(SearchKeyword)) SearchKeyword = string.Empty; SelectedIndex++; } private bool CanMoveNext() => SelectedIndex < DemoItems.Count - 1; private static IEnumerable GenerateDemoItems(ISnackbarMessageQueue snackbarMessageQueue) { yield return new DemoItem( "Palette", typeof(PaletteSelector), [ DocumentationLink.WikiLink("Brush-Names", "Brushes"), DocumentationLink.WikiLink("Custom-Palette-Hues", "Custom Palettes"), DocumentationLink.WikiLink("Swatches-and-Recommended-Colors", "Swatches"), DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.DemoPageLink("Demo View Model","Domain"), DocumentationLink.ApiLink() ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled }; yield return new DemoItem( "ColorTool", typeof(ColorTool), [ DocumentationLink.WikiLink("Brush-Names", "Brushes"), DocumentationLink.WikiLink("Custom-Palette-Hues", "Custom Palettes"), DocumentationLink.WikiLink("Swatches-and-Recommended-Colors", "Swatches"), DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.DemoPageLink("Demo View Model","Domain"), DocumentationLink.ApiLink() ]); yield return new DemoItem( "Button", typeof(Buttons), [ DocumentationLink.WikiLink("Button-Styles", "Buttons"), DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.DemoPageLink("Demo View Model", "Domain"), DocumentationLink.StyleLink("Button"), DocumentationLink.StyleLink("PopupBox"), DocumentationLink.ApiLink() ]); yield return new DemoItem( "Toggle", typeof(Toggles), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("ToggleButton"), DocumentationLink.StyleLink("CheckBox"), DocumentationLink.ApiLink() ]); yield return new DemoItem( "RatingBar", typeof(RatingBar), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("RatingBar"), DocumentationLink.ApiLink() ]); yield return new DemoItem( "Field", typeof(Fields), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("TextBox") ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled, }; yield return new DemoItem( "Fields line up", typeof(FieldsLineUp), [ DocumentationLink.DemoPageLink() ]); yield return new DemoItem( "ComboBox", typeof(ComboBoxes), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("ComboBox") ]); yield return new DemoItem( "Picker", typeof(Pickers), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("Clock"), DocumentationLink.StyleLink("DatePicker"), DocumentationLink.ApiLink() ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled, }; yield return new DemoItem( "Slider", typeof(Sliders), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("Slider") ]); yield return new DemoItem( "Chip", typeof(Chips), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("Chip"), DocumentationLink.ApiLink() ]); yield return new DemoItem( "Typography", typeof(Typography), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("TextBlock") ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Auto }; yield return new DemoItem( "Card", typeof(Cards), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("Card"), DocumentationLink.ApiLink() ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled }; yield return new DemoItem( "Icons", typeof(IconPack), [ DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.DemoPageLink("Demo View Model", "Domain"), DocumentationLink.ApiLink() ], new IconPackViewModel(snackbarMessageQueue)) { //The icons view handles its own scrolling HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled, VerticalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled }; yield return new DemoItem( "ColorZone", typeof(ColorZones), [ DocumentationLink.DemoPageLink(), DocumentationLink.ApiLink() ]); yield return new DemoItem( "List", typeof(Lists), [ DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.DemoPageLink("Demo View Model", "Domain"), DocumentationLink.StyleLink("ListBox"), DocumentationLink.StyleLink("ListView") ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled, }; yield return new DemoItem( "Tab", typeof(Tabs), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("TabControl") ]); yield return new DemoItem( "Tree", typeof(Trees), [ DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.DemoPageLink("Demo View Model", "Domain"), DocumentationLink.StyleLink("TreeView") ]); yield return new DemoItem( "DataGrid", typeof(DataGrids), [ DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.DemoPageLink("Demo View Model", "Domain"), DocumentationLink.StyleLink("DataGrid") ]); yield return new DemoItem( "Expander", typeof(Expander), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("Expander") ]); yield return new DemoItem( "GroupBox", typeof(GroupBoxes), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("GroupBox") ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled, }; yield return new DemoItem( "Menu & ToolBar", typeof(MenusAndToolBars), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("Menu"), DocumentationLink.StyleLink("ToolBar") ]); yield return new DemoItem( "StatusBar", typeof(StatusBars), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("StatusBar") ]); yield return new DemoItem( "Progress Indicator", typeof(Progress), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("ProgressBar") ]); yield return new DemoItem( "NavigationRail", typeof(NavigationRail), [ DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.StyleLink("TabControl"), ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled, }; yield return new DemoItem( "Dialog", typeof(Dialogs), [ DocumentationLink.WikiLink("Dialogs", "Dialogs"), DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.DemoPageLink("Demo View Model", "Domain"), DocumentationLink.ApiLink() ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Auto }; yield return new DemoItem( "Drawer", typeof(Drawers), [ DocumentationLink.DemoPageLink("Demo View"), DocumentationLink.ApiLink() ]); yield return new DemoItem( "Snackbar", typeof(Snackbars), [ DocumentationLink.WikiLink("Snackbar", "Snackbar"), DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("Snackbar"), DocumentationLink.ApiLink(), DocumentationLink.ApiLink() ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Auto }; yield return new DemoItem( "Transition", typeof(Transitions), [ DocumentationLink.WikiLink("Transitions", "Transitions"), DocumentationLink.DemoPageLink(), DocumentationLink.ApiLink("Transitions"), DocumentationLink.ApiLink("Transitions"), DocumentationLink.ApiLink("Transitions"), ]); yield return new DemoItem( "Elevation", typeof(Elevation), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("Shadows"), DocumentationLink.SpecsLink("https://material.io/design/environment/elevation.html", "Elevation") ]) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled, }; yield return new DemoItem( "Smart Hint", typeof(SmartHint), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("SmartHint"), ]) { //The smart hint view handles its own scrolling HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled, VerticalScrollBarVisibilityRequirement = ScrollBarVisibility.Disabled }; yield return new DemoItem( "PopupBox", typeof(PopupBox), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("PopupBox"), ]); yield return new DemoItem(nameof(NumericUpDown), typeof(NumericUpDown), [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink(nameof(NumericUpDown)), DocumentationLink.ApiLink(), DocumentationLink.ApiLink(), DocumentationLink.ApiLink() ]); yield return new DemoItem( "ToolTips", typeof(ToolTips), [ DocumentationLink.DemoPageLink(), DocumentationLink.DemoPageLink("Demo View Model", "Domain"), ]); } private bool DemoItemsFilter(object obj) { string? searchKeyword = SearchKeyword; if (string.IsNullOrWhiteSpace(searchKeyword)) { return true; } return obj is DemoItem item #if NET6_0_OR_GREATER && item.Name.Contains(searchKeyword, StringComparison.OrdinalIgnoreCase); #else && item.Name.IndexOf(searchKeyword, StringComparison.OrdinalIgnoreCase) >= 0; #endif } } ================================================ FILE: src/MainDemo.Wpf/Domain/NotEmptyValidationRule.cs ================================================ using System.Globalization; namespace MaterialDesignDemo.Domain; public class NotEmptyValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { return string.IsNullOrWhiteSpace((value ?? "").ToString()) ? new ValidationResult(false, "Field is required.") : ValidationResult.ValidResult; } } ================================================ FILE: src/MainDemo.Wpf/Domain/PaletteSelectorViewModel.cs ================================================ using MaterialDesignColors; using MaterialDesignDemo.Shared.Domain; using MaterialDesignThemes.Wpf; namespace MaterialDesignDemo.Domain; public class PaletteSelectorViewModel : ViewModelBase { public PaletteSelectorViewModel() { Swatches = new SwatchesProvider().Swatches; } public IEnumerable Swatches { get; } public ICommand ApplyPrimaryCommand { get; } = new AnotherCommandImplementation(o => ApplyPrimary((Swatch)o!)); private static void ApplyPrimary(Swatch swatch) => ModifyTheme(theme => theme.SetPrimaryColor(swatch.ExemplarHue.Color)); public ICommand ApplySecondaryCommand { get; } = new AnotherCommandImplementation(o => ApplySecondary((Swatch)o!)); private static void ApplySecondary(Swatch swatch) { if (swatch is { SecondaryExemplarHue: not null }) { ModifyTheme(theme => theme.SetSecondaryColor(swatch.SecondaryExemplarHue.Color)); } } private static void ModifyTheme(Action modificationAction) { var paletteHelper = new PaletteHelper(); Theme theme = paletteHelper.GetTheme(); modificationAction?.Invoke(theme); paletteHelper.SetTheme(theme); } } ================================================ FILE: src/MainDemo.Wpf/Domain/PickersViewModel.cs ================================================ using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo.Domain; public class PickersViewModel : ViewModelBase { private DateTime _date; private DateTime _time; private string? _validatingTime; private DateTime? _futureValidatingDate; public PickersViewModel() { Date = DateTime.Now; Time = DateTime.Now; } public DateTime Date { get => _date; set => SetProperty(ref _date, value); } public DateTime Time { get => _time; set => SetProperty(ref _time, value); } public string? ValidatingTime { get => _validatingTime; set => SetProperty(ref _validatingTime, value); } public DateTime? FutureValidatingDate { get => _futureValidatingDate; set => SetProperty(ref _futureValidatingDate, value); } } ================================================ FILE: src/MainDemo.Wpf/Domain/Sample4Dialog.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/Domain/Sample4Dialog.xaml.cs ================================================ namespace MaterialDesignDemo.Domain; /// /// Interaction logic for SampleDialog.xaml /// public partial class Sample4Dialog : UserControl { public Sample4Dialog() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/Domain/SampleDialog.xaml ================================================  New contact: ================================================ FILE: src/MainDemo.Wpf/Domain/SampleDialog.xaml.cs ================================================ namespace MaterialDesignDemo.Domain; /// /// Interaction logic for SampleDialog.xaml /// public partial class SampleDialog : UserControl { public SampleDialog() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/Domain/SampleDialogViewModel.cs ================================================ using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo.Domain; public class SampleDialogViewModel : ViewModelBase { private string? _name; public string? Name { get => _name; set => SetProperty(ref _name, value); } } ================================================ FILE: src/MainDemo.Wpf/Domain/SampleMessageDialog.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/Domain/SampleMessageDialog.xaml.cs ================================================ namespace MaterialDesignDemo.Domain; /// /// Interaction logic for SampleMessageDialog.xaml /// public partial class SampleMessageDialog : UserControl { public SampleMessageDialog() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/Domain/SampleProgressDialog.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/Domain/SampleProgressDialog.xaml.cs ================================================ namespace MaterialDesignDemo.Domain; /// /// Interaction logic for SampleProgressDialog.xaml /// public partial class SampleProgressDialog : UserControl { public SampleProgressDialog() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/Domain/SelectableViewModel.cs ================================================ using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo.Domain; public class SelectableViewModel : ViewModelBase { private bool _isSelected; private string? _name; private string? _description; private char _code; private double _numeric; private string? _food; private string? _files; private VehicleType _vehicleType; public bool IsSelected { get => _isSelected; set => SetProperty(ref _isSelected, value); } public char Code { get => _code; set => SetProperty(ref _code, value); } public string? Name { get => _name; set => SetProperty(ref _name, value); } public string? Description { get => _description; set => SetProperty(ref _description, value); } public double Numeric { get => _numeric; set => SetProperty(ref _numeric, value); } public string? Food { get => _food; set => SetProperty(ref _food, value); } public string? Files { get => _files; set => SetProperty(ref _files, value); } public VehicleType VehicleType { get => _vehicleType; set => SetProperty(ref _vehicleType, value); } } public enum VehicleType { Car, Bus, Motorcycle, Van, Scooter, Truck } ================================================ FILE: src/MainDemo.Wpf/Domain/SimpleDataTemplateSelector.cs ================================================ namespace MaterialDesignDemo.Domain; public class SimpleDataTemplateSelector : DataTemplateSelector { public DataTemplate? FixedTemplate { get; set; } public override DataTemplate? SelectTemplate(object item, DependencyObject container) { return FixedTemplate; } } ================================================ FILE: src/MainDemo.Wpf/Domain/SimpleDateValidationRule.cs ================================================ using System.Globalization; namespace MaterialDesignDemo.Domain; public class SimpleDateValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { return DateTime.TryParse((value ?? "").ToString(), CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal | DateTimeStyles.AllowWhiteSpaces, out _) ? ValidationResult.ValidResult : new ValidationResult(false, "Invalid date"); } } ================================================ FILE: src/MainDemo.Wpf/Domain/SlidersViewModel.cs ================================================ using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo.Domain; public class SlidersViewModel : ViewModelBase { public SliderViewModel DiscreteHorizontal { get; } = new(); public SliderViewModel DiscreteVertical { get; } = new() { Maximum = 100000, TickFrequency = 10000, Value = 50000 }; } public class SliderViewModel : ViewModelBase { private double _minimum; private double _maximum = 100.0; private double _tickFrequency = 10.0; private double _value = 50.0; public double Minimum { get => _minimum; set => SetProperty(ref _minimum, value); } public double Maximum { get => _maximum; set => SetProperty(ref _maximum, value); } public double TickFrequency { get => _tickFrequency; set => SetProperty(ref _tickFrequency, value); } public double Value { get => _value; set => SetProperty(ref _value, value); } } ================================================ FILE: src/MainDemo.Wpf/Domain/SmartHintViewModel.cs ================================================ using System.Windows.Media; using MaterialDesignDemo.Shared.Domain; using MaterialDesignThemes.Wpf; namespace MaterialDesignDemo.Domain; internal class SmartHintViewModel : ViewModelBase { public static Point DefaultFloatingOffset { get; } = new(0, 0); public static FontFamily DefaultFontFamily = (FontFamily)new MaterialDesignFontExtension().ProvideValue(null!); private bool _floatHint = true; private FloatingHintHorizontalAlignment _selectedAlignment = FloatingHintHorizontalAlignment.Inherit; private FloatingHintHorizontalAlignment _selectedFloatingAlignment = FloatingHintHorizontalAlignment.Inherit; private double _selectedFloatingScale = 0.75; private bool _showClearButton = true; private bool _showLeadingIcon = true; private bool _showTrailingIcon = true; private string _hintText = "Hint text"; private string _helperText = "Helper text"; private Point _selectedFloatingOffset = DefaultFloatingOffset; private bool _applyCustomPadding; private Thickness _selectedCustomPadding = new(5); private double _selectedCustomHeight = double.NaN; private VerticalAlignment _selectedVerticalAlignment = VerticalAlignment.Stretch; private double _selectedLeadingIconSize = 20; private double _selectedTrailingIconSize = 20; private VerticalAlignment _selectedIconVerticalAlignment = VerticalAlignment.Center; private string? _prefixText = "pre"; private string? _suffixText = "suf"; private double _selectedFontSize = double.NaN; private FontFamily? _selectedFontFamily = DefaultFontFamily; private bool _controlsEnabled = true; private bool _rippleOnFocus = false; private bool _textBoxAcceptsReturn = false; private bool _textBoxIsReadOnly = false; private int _maxLength; private PrefixSuffixVisibility _selectedPrefixVisibility = PrefixSuffixVisibility.WhenFocusedOrNonEmpty; private PrefixSuffixHintBehavior _selectedPrefixHintBehavior = PrefixSuffixHintBehavior.AlignWithPrefixSuffix; private PrefixSuffixVisibility _selectedSuffixVisibility = PrefixSuffixVisibility.WhenFocusedOrNonEmpty; private PrefixSuffixHintBehavior _selectedSuffixHintBehavior = PrefixSuffixHintBehavior.AlignWithPrefixSuffix; private bool _newSpecHighlightingEnabled; private ScrollBarVisibility _selectedVerticalScrollBarVisibility = ScrollBarVisibility.Auto; private ScrollBarVisibility _selectedHorizontalScrollBarVisibility = ScrollBarVisibility.Auto; private Thickness _outlineStyleBorderThickness = new(1); private Thickness _outlineStyleActiveBorderThickness = new(2); private TextWrapping _textBoxTextWrapping = TextWrapping.Wrap; private double _selectedMaxWidth = 200; public IEnumerable HorizontalAlignmentOptions { get; } = Enum.GetValues(typeof(FloatingHintHorizontalAlignment)).OfType(); public IEnumerable FloatingScaleOptions { get; } = [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0]; public IEnumerable FloatingOffsetOptions { get; } = [DefaultFloatingOffset, new Point(0, -25), new Point(0, -16), new Point(16, -16), new Point(-16, -16), new Point(0, -50), new Point(-50, -50), new Point(50, -50)]; public IEnumerable ComboBoxOptions { get; } = ["Option 1", "Option 2", "Option 3"]; public IEnumerable CustomPaddingOptions { get; } = [new Thickness(0), new Thickness(5), new Thickness(10), new Thickness(15)]; public IEnumerable CustomHeightOptions { get; } = [double.NaN, 50, 75, 100, 150]; public IEnumerable VerticalAlignmentOptions { get; } = Enum.GetValues(typeof(VerticalAlignment)).OfType(); public IEnumerable IconSizeOptions { get; } = [10.0, 15, 20, 30, 50, 75]; public IEnumerable FontSizeOptions { get; } = [double.NaN, 8, 12, 16, 20, 24, 28]; public IEnumerable FontFamilyOptions { get; } = new FontFamily[] { DefaultFontFamily }.Concat(Fonts.SystemFontFamilies.OrderBy(f => f.Source)); public IEnumerable PrefixSuffixVisibilityOptions { get; } = Enum.GetValues(typeof(PrefixSuffixVisibility)).OfType(); public IEnumerable PrefixSuffixHintBehaviorOptions { get; } = Enum.GetValues(typeof(PrefixSuffixHintBehavior)).OfType(); public IEnumerable ScrollBarVisibilityOptions { get; } = Enum.GetValues(typeof(ScrollBarVisibility)).OfType(); public IEnumerable CustomOutlineStyleBorderThicknessOptions { get; } = [new Thickness(1), new Thickness(2), new Thickness(3), new Thickness(4), new Thickness(5), new Thickness(6) ]; public IEnumerable TextWrappingOptions { get; } = Enum.GetValues(typeof(TextWrapping)).OfType(); public IEnumerable MaxWidthOptions { get; } = [double.NaN, 200]; public IEnumerable AutoSuggestBoxSuggestions { get; } = ["alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliette", "kilo", "lima"]; public bool FloatHint { get => _floatHint; set => SetProperty(ref _floatHint, value); } public FloatingHintHorizontalAlignment SelectedAlignment { get => _selectedAlignment; set => SetProperty(ref _selectedAlignment, value); } public FloatingHintHorizontalAlignment SelectedFloatingAlignment { get => _selectedFloatingAlignment; set => SetProperty(ref _selectedFloatingAlignment, value); } public double SelectedFloatingScale { get => _selectedFloatingScale; set => SetProperty(ref _selectedFloatingScale, value); } public Point SelectedFloatingOffset { get => _selectedFloatingOffset; set => SetProperty(ref _selectedFloatingOffset, value); } public bool ShowClearButton { get => _showClearButton; set => SetProperty(ref _showClearButton, value); } public bool ShowLeadingIcon { get => _showLeadingIcon; set => SetProperty(ref _showLeadingIcon, value); } public bool ShowTrailingIcon { get => _showTrailingIcon; set => SetProperty(ref _showTrailingIcon, value); } public string HintText { get => _hintText; set => SetProperty(ref _hintText, value); } public string HelperText { get => _helperText; set => SetProperty(ref _helperText, value); } public bool ApplyCustomPadding { get => _applyCustomPadding; set => SetProperty(ref _applyCustomPadding, value); } public Thickness SelectedCustomPadding { get => _selectedCustomPadding; set => SetProperty(ref _selectedCustomPadding, value); } public double SelectedCustomHeight { get => _selectedCustomHeight; set => SetProperty(ref _selectedCustomHeight, value); } public VerticalAlignment SelectedVerticalAlignment { get => _selectedVerticalAlignment; set => SetProperty(ref _selectedVerticalAlignment, value); } public double SelectedLeadingIconSize { get => _selectedLeadingIconSize; set => SetProperty(ref _selectedLeadingIconSize, value); } public double SelectedTrailingIconSize { get => _selectedTrailingIconSize; set => SetProperty(ref _selectedTrailingIconSize, value); } public VerticalAlignment SelectedIconVerticalAlignment { get => _selectedIconVerticalAlignment; set => SetProperty(ref _selectedIconVerticalAlignment, value); } public string? PrefixText { get => _prefixText; set => SetProperty(ref _prefixText, value); } public string? SuffixText { get => _suffixText; set => SetProperty(ref _suffixText, value); } public double SelectedFontSize { get => _selectedFontSize; set => SetProperty(ref _selectedFontSize, value); } public FontFamily? SelectedFontFamily { get => _selectedFontFamily; set => SetProperty(ref _selectedFontFamily, value); } public bool ControlsEnabled { get => _controlsEnabled; set => SetProperty(ref _controlsEnabled, value); } public bool RippleOnFocus { get => _rippleOnFocus; set => SetProperty(ref _rippleOnFocus, value); } public bool TextBoxAcceptsReturn { get => _textBoxAcceptsReturn; set => SetProperty(ref _textBoxAcceptsReturn, value); } public bool TextBoxIsReadOnly { get => _textBoxIsReadOnly; set => SetProperty(ref _textBoxIsReadOnly, value); } public bool ShowCharacterCounter { get => MaxLength > 0; set => MaxLength = value ? 50 : 0; } public int MaxLength { get => _maxLength; set { if (SetProperty(ref _maxLength, value)) { OnPropertyChanged(nameof(ShowCharacterCounter)); } } } public PrefixSuffixVisibility SelectedPrefixVisibility { get => _selectedPrefixVisibility; set => SetProperty(ref _selectedPrefixVisibility, value); } public PrefixSuffixHintBehavior SelectedPrefixHintBehavior { get => _selectedPrefixHintBehavior; set => SetProperty(ref _selectedPrefixHintBehavior, value); } public PrefixSuffixVisibility SelectedSuffixVisibility { get => _selectedSuffixVisibility; set => SetProperty(ref _selectedSuffixVisibility, value); } public PrefixSuffixHintBehavior SelectedSuffixHintBehavior { get => _selectedSuffixHintBehavior; set => SetProperty(ref _selectedSuffixHintBehavior, value); } public bool NewSpecHighlightingEnabled { get => _newSpecHighlightingEnabled; set => SetProperty(ref _newSpecHighlightingEnabled, value); } public ScrollBarVisibility SelectedVerticalScrollBarVisibility { get => _selectedVerticalScrollBarVisibility; set => SetProperty(ref _selectedVerticalScrollBarVisibility, value); } public ScrollBarVisibility SelectedHorizontalScrollBarVisibility { get => _selectedHorizontalScrollBarVisibility; set => SetProperty(ref _selectedHorizontalScrollBarVisibility, value); } public Thickness OutlineStyleBorderThickness { get => _outlineStyleBorderThickness; set => SetProperty(ref _outlineStyleBorderThickness, value); } public Thickness OutlineStyleActiveBorderThickness { get => _outlineStyleActiveBorderThickness; set => SetProperty(ref _outlineStyleActiveBorderThickness, value); } public TextWrapping TextBoxTextWrapping { get => _textBoxTextWrapping; set => SetProperty(ref _textBoxTextWrapping, value); } public double SelectedMaxWidth { get => _selectedMaxWidth; set => SetProperty(ref _selectedMaxWidth, value); } } ================================================ FILE: src/MainDemo.Wpf/Domain/TabsViewModel.cs ================================================ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo.Domain; internal partial class TabsViewModel : ObservableObject { public ObservableCollection CustomTabs { get; } public List LongList { get; } public CustomTab? SelectedTab { get; set; } public string? VeryLongText { get; set; } = @" Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dictum eleifend tellus, quis accumsan neque facilisis ac. Pellentesque non dignissim nisl, id egestas mauris. Suspendisse dui nisi, vestibulum et tincidunt sed, porta id lorem. Quisque iaculis nulla eget feugiat tristique. Suspendisse risus justo, condimentum sed venenatis id, aliquam at lectus. Fusce ut commodo dui. Vivamus eget iaculis sapien. Suspendisse tincidunt, lectus sed pretium porttitor, tortor odio vehicula sem, sed euismod ante erat vitae velit. Quisque maximus ut sem non imperdiet. Ut non libero sit amet risus fringilla convallis vitae sed turpis. Duis aliquet nibh magna, et ultrices tortor rhoncus id. Morbi sed gravida neque. Nulla ornare posuere nisi, et pulvinar nibh euismod a. Nam aliquam ullamcorper congue. Sed sagittis hendrerit leo vitae lacinia. Integer lobortis, orci quis mattis venenatis, felis quam condimentum lorem, sit amet lacinia orci mi eu felis. Suspendisse potenti. Cras viverra tellus odio, in facilisis urna ornare vitae. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nullam sem nunc, posuere at tortor ut, iaculis dictum nisl. Cras blandit in ligula nec imperdiet. Maecenas molestie velit in sapien feugiat, in euismod lectus varius. Mauris quis accumsan arcu. Donec massa est, pretium id nibh sed, varius luctus metus. Vivamus finibus placerat est sit amet molestie. In tincidunt enim a rhoncus viverra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam accumsan, erat vel consectetur tincidunt, mi turpis pulvinar mauris, at ultricies purus massa at mi. Etiam non tristique erat, eu ultricies nisi. In imperdiet sollicitudin pulvinar. Aliquam non nibh nunc. Vestibulum hendrerit libero eu felis aliquam, et ornare leo pharetra. Cras semper rutrum lectus at venenatis. Ut facilisis rutrum felis, eget facilisis neque gravida quis. Vestibulum ornare mollis pharetra. Sed placerat sapien non quam fringilla fermentum. Nullam ex leo, condimentum sit amet magna vitae, condimentum volutpat risus. Aenean scelerisque neque cursus consequat elementum. Proin id tortor nec risus lacinia porta. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam massa ligula, condimentum pellentesque lacus id, ornare accumsan lectus. Fusce viverra nunc sit amet maximus tincidunt. Sed dapibus nulla eget tempus euismod. Aliquam fringilla turpis ut fringilla efficitur. Cras posuere suscipit ligula eget posuere. In aliquet non ligula at consequat. Ut venenatis nunc quis est congue, consequat rutrum justo vehicula. Cras tortor ante, condimentum non venenatis non, venenatis efficitur ex. Nulla a porta libero, quis hendrerit ex. In ut pharetra sem. Nunc gravida ante rhoncus commodo aliquet. Integer luctus blandit libero, sed faucibus ligula ornare ut. Mauris facilisis, urna eu fermentum mollis, mauris massa commodo odio, a venenatis nunc nunc sollicitudin nibh. Ut mattis ipsum nec lacus mattis fringilla. Proin vulputate id velit a finibus. Ut nunc ex, elementum porttitor finibus vel, pellentesque vel turpis. Cras fringilla eleifend libero, ac feugiat arcu vehicula ornare. Nullam pretium finibus blandit. Etiam at urna facilisis, posuere felis non, congue velit. Pellentesque tortor erat, mattis at augue eu, egestas interdum nunc. Aliquam tortor lorem, venenatis eget vestibulum vitae, maximus eget nunc. Vestibulum et leo venenatis, rutrum lacus eget, mattis quam."; public TabsViewModel() { var closeCommand = new AnotherCommandImplementation(tab => { if (tab is CustomTab castedTab) CustomTabs?.Remove(castedTab); }); CustomTabs = new() { new CustomTab(closeCommand) { CustomHeader = "Custom tab 1", CustomContent = "Custom content 1" }, new CustomTab(closeCommand) { CustomHeader = "Custom tab 2", CustomContent = "Custom content 2" }, new CustomTab(closeCommand) { CustomHeader = "Custom tab 3", CustomContent = "Custom content 3", }, }; LongList = Enumerable.Range(1, 20).ToList(); } } internal partial class CustomTab : ObservableObject { public ICommand CloseCommand { get; } public CustomTab(ICommand closeCommand) => CloseCommand = closeCommand; [ObservableProperty] private string? _customHeader; [ObservableProperty] private string? _customContent; } ================================================ FILE: src/MainDemo.Wpf/Domain/ThemeSettingsViewModel.cs ================================================ using MaterialDesignDemo.Shared.Domain; using MaterialDesignThemes.Wpf; namespace MaterialDesignDemo.Domain; public class ThemeSettingsViewModel : ViewModelBase { public ThemeSettingsViewModel() { PaletteHelper paletteHelper = new PaletteHelper(); Theme theme = paletteHelper.GetTheme(); IsDarkTheme = theme.GetBaseTheme() == BaseTheme.Dark; if (theme is Theme internalTheme) { _isColorAdjusted = internalTheme.ColorAdjustment is not null; var colorAdjustment = internalTheme.ColorAdjustment ?? new ColorAdjustment(); _desiredContrastRatio = colorAdjustment.DesiredContrastRatio; _contrastValue = colorAdjustment.Contrast; _colorSelectionValue = colorAdjustment.Colors; } if (paletteHelper.GetThemeManager() is { } themeManager) { themeManager.ThemeChanged += (_, e) => { IsDarkTheme = e.NewTheme?.GetBaseTheme() == BaseTheme.Dark; }; } } private bool _isDarkTheme; public bool IsDarkTheme { get => _isDarkTheme; set { if (SetProperty(ref _isDarkTheme, value)) { ModifyTheme(theme => theme.SetBaseTheme(value ? BaseTheme.Dark : BaseTheme.Light)); } } } private bool _isColorAdjusted; public bool IsColorAdjusted { get => _isColorAdjusted; set { if (SetProperty(ref _isColorAdjusted, value)) { ModifyTheme(theme => { if (theme is Theme internalTheme) { internalTheme.ColorAdjustment = value ? new ColorAdjustment { DesiredContrastRatio = DesiredContrastRatio, Contrast = ContrastValue, Colors = ColorSelectionValue } : null; } }); } } } private float _desiredContrastRatio = 4.5f; public float DesiredContrastRatio { get => _desiredContrastRatio; set { if (SetProperty(ref _desiredContrastRatio, value)) { ModifyTheme(theme => { if (theme is Theme internalTheme && internalTheme.ColorAdjustment != null) internalTheme.ColorAdjustment.DesiredContrastRatio = value; }); } } } public IEnumerable ContrastValues => Enum.GetValues(typeof(Contrast)).Cast(); private Contrast _contrastValue; public Contrast ContrastValue { get => _contrastValue; set { if (SetProperty(ref _contrastValue, value)) { ModifyTheme(theme => { if (theme is Theme internalTheme && internalTheme.ColorAdjustment != null) internalTheme.ColorAdjustment.Contrast = value; }); } } } public IEnumerable ColorSelectionValues => Enum.GetValues(typeof(ColorSelection)).Cast(); private ColorSelection _colorSelectionValue; public ColorSelection ColorSelectionValue { get => _colorSelectionValue; set { if (SetProperty(ref _colorSelectionValue, value)) { ModifyTheme(theme => { if (theme is Theme internalTheme && internalTheme.ColorAdjustment != null) internalTheme.ColorAdjustment.Colors = value; }); } } } private static void ModifyTheme(Action modificationAction) { var paletteHelper = new PaletteHelper(); Theme theme = paletteHelper.GetTheme(); modificationAction?.Invoke(theme); paletteHelper.SetTheme(theme); } } ================================================ FILE: src/MainDemo.Wpf/Domain/TreesViewModel.cs ================================================ using System.Collections; using System.Collections.ObjectModel; using System.Windows.Documents; using CommunityToolkit.Mvvm.ComponentModel; using MaterialDesignDemo.Shared.Domain; using MaterialDesignThemes.Wpf; namespace MaterialDesignDemo.Domain; public class TreeExampleSimpleTemplateSelector : DataTemplateSelector { public DataTemplate? PlanetTemplate { get; set; } public DataTemplate? SolarSystemTemplate { get; set; } public override DataTemplate? SelectTemplate(object item, DependencyObject container) { if (item is Planet) return PlanetTemplate; if (item?.ToString() == "Solar System") return SolarSystemTemplate; return TreeViewAssist.SuppressAdditionalTemplate; } } public sealed class Movie { public Movie(string name, string director) { Name = name; Director = director; } public string Name { get; } public string Director { get; } } public class Planet { public string? Name { get; set; } public double DistanceFromSun { get; set; } public double DistanceFromEarth { get; set; } public double Velocity { get; set; } } public partial class TestItem : ObservableObject { public TestItem? Parent { get; set; } public string Name { get; } public ObservableCollection Items { get; } // This property is used to determine if the item is expanded or not. // With the TreeListView control, the UI items are virtualized. Without // this property, the IsExpanded state of the TreeListViewItem would be lost // when it is recycled. // // For more information see: // https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/issues/3640#issuecomment-2274086113 // // https://learn.microsoft.com/dotnet/desktop/wpf/advanced/optimizing-performance-controls?view=netframeworkdesktop-4.8&WT.mc_id=DT-MVP-5003472 [ObservableProperty] private bool _isExpanded; public TestItem(string name, IEnumerable items) { Name = name; Items = new ObservableCollection(items); } } public sealed class MovieCategory { public MovieCategory(string name, params Movie[] movies) { Name = name; Movies = new ObservableCollection(movies); } public string Name { get; } public ObservableCollection Movies { get; } } public sealed class TreesViewModel : ViewModelBase { private object? _selectedItem; private TestItem? _selectedTreeItem; public ObservableCollection TreeItems { get; } = new(); public ObservableCollection MovieCategories { get; } public AnotherCommandImplementation AddCommand { get; } public AnotherCommandImplementation RemoveSelectedItemCommand { get; } public AnotherCommandImplementation AddListTreeItemCommand { get; } public AnotherCommandImplementation RemoveListTreeItemCommand { get; } public TestItem? SelectedTreeItem { get => _selectedTreeItem; set => SetProperty(ref _selectedTreeItem, value); } public object? SelectedItem { get => _selectedItem; set => SetProperty(ref _selectedItem, value); } public TreesViewModel() { Random random = new(); for(int i = 0; i < 10; i++) { TreeItems.Add(CreateTestItem(random, 1)); } static TestItem CreateTestItem(Random random, int depth) { int numberOfChildren = depth < 5 ? random.Next(0, 6) : 0; var children = Enumerable.Range(0, numberOfChildren).Select(_ => CreateTestItem(random, depth + 1)); var rv = new TestItem(GenerateString(random.Next(4, 10)), children); foreach(var child in rv.Items) { child.Parent = rv; } return rv; } AddListTreeItemCommand = new(_ => { if (SelectedTreeItem is { } treeItem) { var newItem = CreateTestItem(random, 1); newItem.Parent = treeItem; treeItem.Items.Add(newItem); } else { TreeItems.Add(CreateTestItem(random, 1)); } }); RemoveListTreeItemCommand = new(items => { if (items is IEnumerable enumerable) { foreach(TestItem testItem in enumerable) { if (testItem.Parent is { } parent) { parent.Items.Remove(testItem); } else { TreeItems.Remove(testItem); } } } if (SelectedTreeItem is { } selectedItem) { if (selectedItem.Parent is { } parent) { parent.Items.Remove(selectedItem); } else { TreeItems.Remove(selectedItem); } SelectedTreeItem = null; } }); MovieCategories = new ObservableCollection { new MovieCategory("Action", new Movie ("Predator", "John McTiernan"), new Movie("Alien", "Ridley Scott"), new Movie("Prometheus", "Ridley Scott")), new MovieCategory("Comedy", new Movie("EuroTrip", "Jeff Schaffer"), new Movie("EuroTrip", "Jeff Schaffer") ) }; MovieCategories.Add(MovieCategories[0]); MovieCategories.Add(MovieCategories[1]); AddCommand = new AnotherCommandImplementation( _ => { if (!MovieCategories.Any()) { MovieCategories.Add(new MovieCategory(GenerateString(15))); } else { var index = new Random().Next(0, MovieCategories.Count); MovieCategories[index].Movies.Add( new Movie(GenerateString(15), GenerateString(20))); } }); RemoveSelectedItemCommand = new AnotherCommandImplementation( _ => { var movieCategory = SelectedItem as MovieCategory; if (movieCategory != null) { MovieCategories.Remove(movieCategory); } else { var movie = SelectedItem as Movie; if (movie == null) return; MovieCategories.FirstOrDefault(v => v.Movies.Contains(movie))?.Movies.Remove(movie); } }, _ => SelectedItem != null); } private static string GenerateString(int length) { var random = new Random(); return string.Join(string.Empty, Enumerable.Range(0, length) .Select(v => (char)random.Next('a', 'z' + 1))); } } ================================================ FILE: src/MainDemo.Wpf/Drawers.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/Fields.xaml.cs ================================================ using System.Windows.Navigation; using MaterialDesignDemo.Domain; namespace MaterialDesignDemo; public partial class Fields { public Fields() { InitializeComponent(); DataContext = new FieldsViewModel(); } private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e) => Link.OpenInBrowser(e.Uri.AbsoluteUri); } ================================================ FILE: src/MainDemo.Wpf/FieldsLineUp.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/FieldsLineUp.xaml.cs ================================================ using System.Globalization; using System.Windows.Data; using MaterialDesignThemes.Wpf; namespace MaterialDesignDemo; public partial class FieldsLineUp { private IEnumerable Controls => FieldsLineUpGrid.Children.OfType(); private class ValidationErrorRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) => value is string errorMessage && !string.IsNullOrWhiteSpace(errorMessage) ? new ValidationResult(false, errorMessage) : ValidationResult.ValidResult; } private static readonly ValidationErrorRule ValidationRule = new ValidationErrorRule(); public FieldsLineUp() { InitializeComponent(); HorizontalPaddingSlider.Value = Controls.OfType().First().Padding.Left; HorizontalPaddingSlider.ValueChanged += delegate { UpdateThickness(HorizontalPaddingSlider, PaddingProperty, true); }; VerticalPaddingSlider.Value = Controls.OfType().First().Padding.Top; VerticalPaddingSlider.ValueChanged += delegate { UpdateThickness(VerticalPaddingSlider, PaddingProperty, false); }; HorizontalTextBoxViewMarginSlider.Value = ((Thickness)Controls.OfType().First().GetValue(TextFieldAssist.TextBoxViewMarginProperty)).Left; HorizontalTextBoxViewMarginSlider.ValueChanged += delegate { UpdateThickness(HorizontalTextBoxViewMarginSlider, TextFieldAssist.TextBoxViewMarginProperty, true); }; ValidationErrorTextBox.TextChanged += delegate { foreach (var control in Controls) control.GetBindingExpression(TagProperty)!.UpdateSource(); }; foreach (var control in Controls) { control.SetBinding(HintAssist.HintProperty, new Binding(nameof(TextBox.Text)) { ElementName = nameof(HintTextBox) }); control.SetBinding(HintAssist.HelperTextProperty, new Binding(nameof(TextBox.Text)) { ElementName = nameof(HelperTextBox) }); control.SetBinding(TextFieldAssist.HasClearButtonProperty, new Binding(nameof(CheckBox.IsChecked)) { ElementName = nameof(HasClearButtonCheckBox) }); control.SetBinding(TextFieldAssist.PrefixTextProperty, new Binding(nameof(TextBox.Text)) { ElementName = nameof(PrefixTextBox) }); control.SetBinding(TextFieldAssist.SuffixTextProperty, new Binding(nameof(TextBox.Text)) { ElementName = nameof(SuffixTextBox) }); control.SetBinding(TagProperty, new Binding(nameof(TextBox.Text)) { Mode = BindingMode.TwoWay, ElementName = nameof(ValidationErrorTextBox), ValidationRules = { ValidationRule }, ValidatesOnDataErrors = true }); control.VerticalAlignment = VerticalAlignment.Top; control.Margin = new Thickness(2, 10, 2, 10); if (control is ComboBox comboBox) comboBox.SetBinding(ComboBox.IsEditableProperty, new Binding(nameof(CheckBox.IsChecked)) { ElementName = nameof(IsEditableCheckBox) }); if (control is TextBoxBase tb) tb.SetBinding(TextBoxBase.IsReadOnlyProperty, new Binding(nameof(CheckBox.IsChecked)) { ElementName = nameof(IsReadOnlyCheckBox) }); SetValue(control); } } private void UpdateThickness(RangeBase slider, DependencyProperty property, bool horizontal) { var newValue = slider.Value; foreach (var element in Controls) { var current = (Thickness)element.GetValue(property); var updated = horizontal ? new Thickness(newValue, current.Top, newValue, current.Bottom) : new Thickness(current.Left, newValue, current.Right, newValue); element.SetValue(property, updated); } } private static void SetValue(Control control) { switch (control) { case MaterialDesignThemes.Wpf.AutoSuggestBox autoSuggestBox: autoSuggestBox.Text = nameof(MaterialDesignThemes.Wpf.AutoSuggestBox.Text); break; case TextBox textBox: textBox.Text = nameof(TextBox.Text); break; case PasswordBox passwordBox: passwordBox.Password = nameof(PasswordBox.Password); break; case ComboBox comboBox: foreach (var number in Enumerable.Range(1, 5)) comboBox.Items.Add(new ComboBoxItem { Content = nameof(ComboBox.Text) + number }); comboBox.SelectedIndex = 0; break; case DatePicker datePicker: datePicker.SelectedDate = DateTime.Now; break; case TimePicker timePicker: timePicker.SelectedTime = DateTime.Now; break; case MaterialDesignThemes.Wpf.NumericUpDown numericUpDown: numericUpDown.Value = 0; break; default: throw new NotSupportedException(control.GetType().FullName); } } } ================================================ FILE: src/MainDemo.Wpf/GroupBoxes.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/GroupBoxes.xaml.cs ================================================ namespace MaterialDesignDemo; public partial class GroupBoxes { public GroupBoxes() => InitializeComponent(); } ================================================ FILE: src/MainDemo.Wpf/Home.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/Home.xaml.cs ================================================ using System.Configuration; using MaterialDesignDemo.Domain; namespace MaterialDesignDemo; public partial class Home { public Home() => InitializeComponent(); private void GitHubButton_OnClick(object sender, RoutedEventArgs e) => Link.OpenInBrowser(ConfigurationManager.AppSettings["GitHub"]); private void TwitterButton_OnClick(object sender, RoutedEventArgs e) => Link.OpenInBrowser("https://twitter.com/James_Willock"); private void ChatButton_OnClick(object sender, RoutedEventArgs e) => Link.OpenInBrowser("https://gitter.im/ButchersBoy/MaterialDesignInXamlToolkit"); private void EmailButton_OnClick(object sender, RoutedEventArgs e) => Link.OpenInBrowser("mailto://james@dragablz.net"); private void DonateButton_OnClick(object sender, RoutedEventArgs e) => Link.OpenInBrowser("https://opencollective.com/materialdesigninxaml"); } ================================================ FILE: src/MainDemo.Wpf/IconPack.xaml ================================================  For more information on Material Design Icons see the official website: materialdesignicons.com ================================================ FILE: src/MainDemo.Wpf/PaletteSelector.xaml.cs ================================================ using MaterialDesignDemo.Domain; namespace MaterialDesignDemo; public partial class PaletteSelector { public PaletteSelector() { DataContext = new PaletteSelectorViewModel(); InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/Pickers.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/Pickers.xaml.cs ================================================ using System.Diagnostics; using System.Globalization; using MaterialDesignDemo.Domain; using MaterialDesignThemes.Wpf; namespace MaterialDesignDemo; public partial class Pickers { public Pickers() { DataContext = new PickersViewModel(); InitializeComponent(); FutureDatePicker.BlackoutDates.AddDatesInPast(); LoadLocales(); LocaleCombo.SelectionChanged += LocaleCombo_SelectionChanged; LocaleCombo.SelectedItem = "fr-CA"; } private void LocaleCombo_SelectionChanged(object sender, SelectionChangedEventArgs e) { try { var lang = System.Windows.Markup.XmlLanguage.GetLanguage((string)LocaleCombo.SelectedItem); LocaleDatePicker.Language = lang; LocaleDatePickerRTL.Language = lang; } catch { LocaleCombo.SelectedItem = "fr-CA"; } //HACK: The calendar only refresh when we change the date LocaleDatePicker.DisplayDate = LocaleDatePicker.DisplayDate.AddDays(1); LocaleDatePicker.DisplayDate = LocaleDatePicker.DisplayDate.AddDays(-1); LocaleDatePickerRTL.DisplayDate = LocaleDatePickerRTL.DisplayDate.AddDays(1); LocaleDatePickerRTL.DisplayDate = LocaleDatePickerRTL.DisplayDate.AddDays(-1); } private void LoadLocales() { foreach (var ci in CultureInfo.GetCultures(CultureTypes.AllCultures) .Where(ci => ci.Calendar is GregorianCalendar) .OrderBy(ci => ci.Name)) { LocaleCombo.Items.Add(ci.Name); } } public void CalendarDialogOpenedEventHandler(object sender, DialogOpenedEventArgs eventArgs) => Calendar.SelectedDate = ((PickersViewModel)DataContext).Date; public void CalendarDialogClosingEventHandler(object sender, DialogClosingEventArgs eventArgs) { if (!Equals(eventArgs.Parameter, "1")) return; if (!Calendar.SelectedDate.HasValue) { eventArgs.Cancel(); return; } ((PickersViewModel)DataContext).Date = Calendar.SelectedDate.Value; } public void ClockDialogOpenedEventHandler(object sender, DialogOpenedEventArgs eventArgs) => Clock.Time = ((PickersViewModel)DataContext).Time; public void ClockDialogClosingEventHandler(object sender, DialogClosingEventArgs eventArgs) { if (Equals(eventArgs.Parameter, "1")) ((PickersViewModel)DataContext).Time = Clock.Time; } private void PresetTimePicker_SelectedTimeChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs e) { var oldValue = e.OldValue.HasValue ? e.OldValue.Value.ToLongTimeString() : "NULL"; var newValue = e.NewValue.HasValue ? e.NewValue.Value.ToLongTimeString() : "NULL"; Debug.WriteLine($"PresentTimePicker's SelectedTime changed from {oldValue} to {newValue}"); } public void CombinedDialogOpenedEventHandler(object sender, DialogOpenedEventArgs eventArgs) { CombinedCalendar.SelectedDate = ((PickersViewModel)DataContext).Date; CombinedClock.Time = ((PickersViewModel)DataContext).Time; } public void CombinedDialogClosingEventHandler(object sender, DialogClosingEventArgs eventArgs) { if (Equals(eventArgs.Parameter, "1") && CombinedCalendar.SelectedDate is DateTime selectedDate) { var combined = selectedDate.AddSeconds(CombinedClock.Time.TimeOfDay.TotalSeconds); ((PickersViewModel)DataContext).Time = combined; ((PickersViewModel)DataContext).Date = combined; } } } ================================================ FILE: src/MainDemo.Wpf/PopupBox.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/Tabs.xaml.cs ================================================ using MaterialDesignDemo.Domain; namespace MaterialDesignDemo; /// /// Interaction logic for Tabs.xaml /// public partial class Tabs { public Tabs() { DataContext = new TabsViewModel(); InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/ThemeSettings.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/ThemeSettings.xaml.cs ================================================ using MaterialDesignDemo.Domain; namespace MaterialDesignDemo; public partial class ThemeSettings { public ThemeSettings() { DataContext = new ThemeSettingsViewModel(); InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/Toggles.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/Toggles.xaml.cs ================================================ namespace MaterialDesignDemo; public partial class Toggles { public Toggles() => InitializeComponent(); } ================================================ FILE: src/MainDemo.Wpf/ToolTips.xaml ================================================  0,16,0,0 ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide1_Intro.xaml.cs ================================================ using MaterialDesignDemo.Domain; using MaterialDesignDemo.Shared.Domain; namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for Slide1_Intro.xaml /// public partial class Slide1_Intro : UserControl { public Slide1_Intro() { DataContext = new Slide1ViewModel(); InitializeComponent(); } public class Slide1ViewModel : ViewModelBase { private string? _name; public string? Name { get => _name; set => SetProperty(ref _name, value); } } } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide2_Intro.xaml ================================================  The transition will originate from where the user clicks the button. Experiment with the back/forward buttons. ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide2_Intro.xaml.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for Slide2_Intro.xaml /// public partial class Slide2_Intro : UserControl { public Slide2_Intro() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide3_Intro.xaml ================================================  OK, we've seen some cool stuff. Let's take a look at some more transition types. ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide3_Intro.xaml.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for Slide3_Intro.xaml /// public partial class Slide3_Intro : UserControl { public Slide3_Intro() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide4_CombineTransitions.xaml ================================================  You can combine some transition effects too. Did you see how this page slid in from the bottom and left? Next we will look at some granular transitions on individual elements. ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide4_CombineTransitions.xaml.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for Slide4_CombineTransitions.xaml /// public partial class Slide4_CombineTransitions : UserControl { public Slide4_CombineTransitions() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide5_TransitioningContent.xaml ================================================  Contacts ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide5_TransitioningContent.xaml.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for Slide5_TransitioningContent.xaml /// public partial class Slide5_TransitioningContent : UserControl { public Slide5_TransitioningContent() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide6_Origins.xaml ================================================  You can set .DefaultTransitionOrigin, to help with transitions such as the circle wipe, which are triggered from code. ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide6_Origins.xaml.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for Slide6_Origins.xaml /// public partial class Slide6_Origins : UserControl { public Slide6_Origins() { InitializeComponent(); } private void FirstSlideButton_OnClick(object sender, RoutedEventArgs e) { Transitioner.SelectedIndex = 0; } private void SecondSlideButton_OnClick(object sender, RoutedEventArgs e) { Transitioner.SelectedIndex = 1; } } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide7_MVVM.xaml ================================================  That's the end of the demo for now; a full MVVM demo coming soon! ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide7_MVVM.xaml.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for Slide7_MVVM.xaml /// public partial class Slide7_MVVM : UserControl { public Slide7_MVVM() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide7_MasterModel.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; public class Slide7_MasterModel { } public class Slide8_DetailsModel { } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide8_Details.xaml ================================================  ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/Slide8_Details.xaml.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for Slide8_Details.xaml /// public partial class Slide8_Details : UserControl { public Slide8_Details() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/TransitionsDemoHome.xaml ================================================  Transitions Demo ================================================ FILE: src/MainDemo.Wpf/TransitionsDemo/TransitionsDemoHome.xaml.cs ================================================ namespace MaterialDesignDemo.TransitionsDemo; /// /// Interaction logic for TransitionsDemoHome.xaml /// public partial class TransitionsDemoHome : UserControl { public TransitionsDemoHome() { InitializeComponent(); } } ================================================ FILE: src/MainDemo.Wpf/Trees.xaml ================================================  Windows