├── .gitattributes ├── .gitignore ├── License.md ├── OLDDOCS.md ├── README.md ├── WpfMaterialForms.sln ├── WpfMaterialForms.sln.DotSettings ├── appveyor.yml ├── doc ├── dialog.png ├── email.png ├── login.png ├── settings.png └── user.png └── src ├── Demo ├── Material.Application │ ├── Commands │ │ ├── IMenuCommand.cs │ │ ├── IRefreshableCommand.cs │ │ ├── Internal │ │ │ ├── AsyncRouteActionCommand.cs │ │ │ ├── AsyncRouteCommand.cs │ │ │ ├── AsyncRouteValueCommand.cs │ │ │ ├── Menu │ │ │ │ ├── AsyncRouteActionMenuCommand.cs │ │ │ │ ├── AsyncRouteMenuCommand.cs │ │ │ │ ├── AsyncRouteValueMenuCommand.cs │ │ │ │ ├── RouteActionMenuCommand.cs │ │ │ │ ├── RouteMenuCommand.cs │ │ │ │ └── RouteValueMenuCommand.cs │ │ │ ├── RouteActionCommand.cs │ │ │ ├── RouteCommand.cs │ │ │ └── RouteValueCommand.cs │ │ └── UntrackedCommand.cs │ ├── Controls │ │ ├── AlignableWrapPanel.cs │ │ ├── BindingProxy.cs │ │ ├── ConfirmableButton.cs │ │ ├── ISortable.cs │ │ ├── LockableToggleButton.cs │ │ ├── MaterialRoutesWindow.xaml │ │ ├── MaterialRoutesWindow.xaml.cs │ │ ├── NullAsSeparatorTemplateSelector.cs │ │ ├── PageableCollection.cs │ │ ├── ScrollViewerExtensions.cs │ │ ├── SortableDataGrid.cs │ │ └── SortablePageableCollection.cs │ ├── Helpers │ │ ├── CollectionHelpers.cs │ │ ├── ExceptionHelpers.cs │ │ ├── Internal │ │ │ ├── AttachedProperties.cs │ │ │ ├── ErrorMessages.cs │ │ │ ├── IocHelpers.cs │ │ │ └── RouteErrorListenerExtensions.cs │ │ ├── LanguageHelpers.cs │ │ └── PathHelpers.cs │ ├── Infrastructure │ │ ├── AppController.cs │ │ ├── IContext.cs │ │ ├── IDialogService.cs │ │ ├── IFilePicker.cs │ │ ├── ILocalizationService.cs │ │ ├── IMainWindowController.cs │ │ ├── IMainWindowLocator.cs │ │ ├── INotificationService.cs │ │ ├── IPaletteService.cs │ │ ├── IServiceLocator.cs │ │ ├── ISingleton.cs │ │ └── Internal │ │ │ ├── DefaultAppModule.cs │ │ │ ├── DialogFilePicker.cs │ │ │ ├── DialogFileSaver.cs │ │ │ ├── DialogHostService.cs │ │ │ ├── DispatcherContext.cs │ │ │ ├── NinjectServiceLocator.cs │ │ │ ├── PaletteService.cs │ │ │ ├── ServiceLocatorRouteFactory.cs │ │ │ ├── SnackbarNotificationService.cs │ │ │ └── XamlLocalizationService.cs │ ├── Localization │ │ └── Language.cs │ ├── Material.Application.csproj │ ├── MaterialDesign │ │ ├── CustomErrorTemplate.xaml │ │ ├── CustomPasswordBoxHintProxy.cs │ │ ├── CustomTextBoxHintProxy.cs │ │ └── MaterialDesignHelper.cs │ ├── Models │ │ ├── CommandRefreshSource.cs │ │ ├── Model.cs │ │ ├── ObjectPresenter.cs │ │ ├── PropertyRefreshSource.cs │ │ └── RefreshSource.cs │ ├── Properties │ │ ├── Annotations.cs │ │ └── AssemblyInfo.cs │ ├── Routing │ │ ├── Default │ │ │ └── ListRoute.cs │ │ ├── IRouteErrorListener.cs │ │ ├── IRouteFactory.cs │ │ ├── IRouteStack.cs │ │ ├── IRouteWrapper.cs │ │ ├── Internal │ │ │ ├── RouteItem.cs │ │ │ ├── RouteStack.cs │ │ │ └── RouteWrapperInternal.cs │ │ ├── Route.cs │ │ ├── RouteActivationMethod.cs │ │ ├── RouteConfig.cs │ │ ├── RouteEventError.cs │ │ ├── RouteEventType.cs │ │ ├── RouteTransitionException.cs │ │ └── TransientRoute.cs │ ├── ValueConverters │ │ ├── CollectionToVisibilityConverter.cs │ │ ├── NullToVisibilityConverter.cs │ │ └── VariableExpanderConverter.cs │ ├── Views │ │ ├── CollectionView.xaml │ │ ├── CollectionView.xaml.cs │ │ ├── FormView.xaml │ │ ├── FormView.xaml.cs │ │ ├── LoadingView.xaml │ │ ├── LoadingView.xaml.cs │ │ └── View.cs │ ├── app.config │ └── packages.config └── MaterialForms.Demo │ ├── App.config │ ├── App.xaml │ ├── App.xaml.cs │ ├── FodyWeavers.xml │ ├── Infrastructure │ └── DemoAppController.cs │ ├── MaterialForms.Demo.csproj │ ├── ModelTypeToVisibilityConverter.cs │ ├── Models │ ├── DataTypes.cs │ ├── ExamplePresenter.cs │ ├── FoodSelection.cs │ ├── Home │ │ └── Introduction.cs │ ├── Login.cs │ ├── ProgressModel.cs │ ├── Selection.cs │ ├── Settings.cs │ └── User.cs │ ├── OldDemo │ ├── ComplexWindow.cs │ ├── MainWindow.xaml │ └── MainWindow.xaml.cs │ ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings │ ├── Routes │ ├── ExamplesRoute.cs │ ├── HomeRoute.cs │ └── XmlExamplesRoute.cs │ ├── ViewBindings.xaml │ ├── Views │ ├── ExamplesView.xaml │ ├── ExamplesView.xaml.cs │ ├── FormView.xaml │ ├── FormView.xaml.cs │ ├── XmlExamplesView.xaml │ └── XmlExamplesView.xaml.cs │ └── packages.config ├── MaterialForms.Tests ├── BoundExpressionTests.cs ├── MaterialFormTests.cs ├── MaterialForms.Tests.csproj └── Properties │ └── AssemblyInfo.cs └── MaterialForms ├── App.config ├── AttachedProperties └── PasswordBoxHelper.cs ├── Components └── LoadingButton.cs ├── FodyWeavers.xml ├── Mappers └── MaterialMapper.cs ├── MaterialForms.csproj ├── MaterialForms.csproj.DotSettings ├── MaterialForms.nuspec ├── Old ├── ColorAssist.cs ├── Controls │ ├── ButtonControl.xaml │ ├── ButtonControl.xaml.cs │ ├── CaptionControl.xaml │ ├── CaptionControl.xaml.cs │ ├── CheckBoxControl.xaml │ ├── CheckBoxControl.xaml.cs │ ├── ComboBoxControl.xaml │ ├── ComboBoxControl.xaml.cs │ ├── DatePickerControl.xaml │ ├── DatePickerControl.xaml.cs │ ├── FileLoaderControl.xaml │ ├── FileLoaderControl.xaml.cs │ ├── KeyValueControl.xaml │ ├── KeyValueControl.xaml.cs │ ├── MultiLineTextControl.xaml │ ├── MultiLineTextControl.xaml.cs │ ├── MultiSchemaControl.xaml │ ├── MultiSchemaControl.xaml.cs │ ├── PasswordTextControl.xaml │ ├── PasswordTextControl.xaml.cs │ ├── ProgressControl.xaml │ ├── ProgressControl.xaml.cs │ ├── SingleLineTextControl.xaml │ ├── SingleLineTextControl.xaml.cs │ ├── SliderControl.xaml │ ├── SliderControl.xaml.cs │ ├── SwitchControl.xaml │ ├── SwitchControl.xaml.cs │ ├── TimePickerControl.xaml │ └── TimePickerControl.xaml.cs ├── DataSchema │ ├── BooleanSchema.cs │ ├── CaptionSchema.cs │ ├── CommandSchema.cs │ ├── DateSchema.cs │ ├── IntegerSchema.cs │ ├── KeyValueSchema.cs │ ├── MultiSchema.cs │ ├── NumberRangeSchema.cs │ ├── PasswordSchema.cs │ ├── ProgressSchema.cs │ ├── SchemaBase.cs │ ├── SelectionSchema.cs │ ├── SingleFileSchema.cs │ ├── StringSchema.cs │ └── TimeSchema.cs ├── DelegateCommand.cs ├── Extensions │ └── InitializerExtensions.cs ├── Forms │ ├── DialogActionListener.cs │ ├── DialogFactory.cs │ ├── DialogSession.cs │ ├── DialogTheme.cs │ ├── DispatcherOption.cs │ ├── FormActionCallback.cs │ ├── MaterialApplication.cs │ ├── MaterialDialog.cs │ ├── MaterialForm.cs │ ├── MaterialWindow.cs │ ├── Session.cs │ ├── WindowFactory.cs │ └── WindowSession.cs ├── IViewProvider.cs ├── MaterialFormsWindow.xaml ├── MaterialFormsWindow.xaml.cs ├── PasswordHelpers.cs ├── ProgressBarSmoother.cs ├── SessionAssist.cs ├── Tasks │ ├── ProgressController.cs │ ├── ProgressDialogOptions.cs │ └── TaskRunner.cs ├── Validation │ ├── ValidationCallback.cs │ └── Validators.cs ├── ValueConverters │ ├── BoolInversionConverter.cs │ ├── BoolToResizeModeConverter.cs │ ├── FormEmptyMarginConverter.cs │ ├── StringToIntegerConverter.cs │ ├── StringToVisibilityConverter.cs │ └── ValueToPercentConverter.cs └── Views │ ├── DialogView.xaml │ ├── DialogView.xaml.cs │ ├── FormView.xaml │ └── FormView.xaml.cs ├── Properties ├── Annotations.cs ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Settings.Designer.cs └── Settings.settings ├── Resources ├── DialogViewResources.xaml ├── Material.xaml └── TextStyles.xaml ├── Themes ├── Elements │ └── Text.xaml ├── Generic.xaml ├── Material.xaml ├── Material │ ├── Element.Action.xaml │ ├── Element.Text.xaml │ ├── Field.CheckBox.xaml │ ├── Field.Converted.xaml │ ├── Field.DatePicker.xaml │ ├── Field.Password.xaml │ ├── Field.Progress.xaml │ ├── Field.Selection.xaml │ ├── Field.Slider.xaml │ ├── Field.String.xaml │ ├── Field.Switch.xaml │ └── IconStyles.xaml ├── Metro.xaml ├── Metro │ ├── Element.Action.xaml │ ├── Element.Text.xaml │ ├── Field.CheckBox.xaml │ ├── Field.Converted.xaml │ ├── Field.Password.xaml │ ├── Field.String.xaml │ ├── Field.Switch.xaml │ └── IconStyles.xaml ├── Wpf.xaml └── Wpf │ ├── Element.Action.xaml │ ├── Field.CheckBox.xaml │ ├── Field.Converted.xaml │ ├── Field.Password.xaml │ ├── Field.String.xaml │ ├── Field.Switch.xaml │ └── IconStyles.xaml └── Wpf ├── ActionEventArgs.cs ├── Annotations ├── BindingAttribute.cs ├── CardAttribute.cs ├── Content │ ├── ActionAttribute.cs │ ├── BreakAttribute.cs │ ├── DividerAttribute.cs │ ├── FormContentAttribute.cs │ └── TextElementAttribute.cs ├── DefaultFields.cs ├── Display │ ├── PasswordAttribute.cs │ ├── ProgressAttribute.cs │ ├── SliderAttribute.cs │ └── ToggleAttribute.cs ├── EnumDisplayAttribute.cs ├── FieldAttribute.cs ├── FieldIgnoreAttribute.cs ├── FormAttribute.cs ├── Must.cs ├── ReplaceAttribute.cs ├── ResourceAttribute.cs ├── SelectFromAttribute.cs ├── SelectionType.cs ├── ValidationAction.cs └── ValueAttribute.cs ├── Controls ├── ActionPanel.cs ├── DynamicForm.cs ├── IDynamicForm.cs ├── MaterialDialog.cs ├── SelectTextOnFocus.cs └── TextProperties.cs ├── Fields ├── BindingProvider.cs ├── ContentElement.cs ├── DataFormField.cs ├── Defaults │ ├── ActionAlignerElement.cs │ ├── ActionElement.cs │ ├── BooleanField.cs │ ├── BreakElement.cs │ ├── CardElement.cs │ ├── ConvertedField.cs │ ├── DateField.cs │ ├── DividerElement.cs │ ├── HeadingElement.cs │ ├── ProgressField.cs │ ├── SelectionField.cs │ ├── SliderField.cs │ ├── StringField.cs │ ├── TextElement.cs │ └── TitleElement.cs ├── FormBindingExtension.cs ├── FormDefinition.cs ├── FormElement.cs ├── FormField.cs ├── FormRow.cs ├── IBindingProvider.cs ├── IDataBindingProvider.cs ├── IFormDefinition.cs ├── ReplacementPipe.cs ├── StringTypeConverter.cs └── ValueBindingProvider.cs ├── FormBuilding ├── CustomCulture.cs ├── Defaults │ ├── Initializers │ │ ├── BindingInitializer.cs │ │ ├── FieldInitializer.cs │ │ └── ValidatorInitializer.cs │ ├── Primitive.cs │ ├── Properties │ │ ├── SelectFromBuilder.cs │ │ └── SliderBuilder.cs │ └── Types │ │ ├── DefaultTypeBuilders.cs │ │ ├── ProgressBuilder.cs │ │ └── TypeBuilder.cs ├── Deserializers.cs ├── DynamicProperty.cs ├── FormBuilder.cs ├── IFieldBuilder.cs ├── IFieldInitializer.cs ├── IFormProperty.cs ├── PropertyInfoWrapper.cs ├── Utilities.cs └── ValidatorProvider.cs ├── Forms ├── ActionEventArgs.cs ├── Alert.cs ├── Base │ ├── DialogBase.cs │ └── FormBase.cs ├── Confirm.cs └── Prompt.cs ├── IActionHandler.cs ├── ModelState.cs ├── Resources ├── BindingOptions.cs ├── BindingProxy.cs ├── BoolProxy.cs ├── BoundExpression.cs ├── BoundValue.cs ├── CoercedValueProvider.cs ├── ContextPropertyBinding.cs ├── ConvertedDataBinding.cs ├── ConvertedDirectBinding.cs ├── DataBinding.cs ├── DeferredProxyResource.cs ├── DirectBinding.cs ├── DynamicResource.cs ├── EnumerableStringValueProvider.cs ├── EnumerableValueProvider.cs ├── FormResourceContext.cs ├── IProxy.cs ├── IResourceContext.cs ├── IValueProvider.cs ├── LiteralValue.cs ├── PropertyBinding.cs ├── ProxyResource.cs ├── Resource.cs ├── StaticResource.cs ├── StringProxy.cs └── ValueConverters │ ├── AsBoolConverter.cs │ ├── BoolOrVisibilityConverter.cs │ ├── ConverterWrapper.cs │ ├── IsEmptyConverter.cs │ ├── IsNotEmptyConverter.cs │ ├── IsNotNullConverter.cs │ ├── IsNullConverter.cs │ ├── LengthValueConverter.cs │ ├── NegateConverter.cs │ ├── ToLowerConverter.cs │ ├── ToStringConverter.cs │ ├── ToUpperConverter.cs │ └── VisibilityConverter.cs └── Validation ├── ComparisonValidator.cs ├── ConversionValidator.cs ├── EmptyValidator.cs ├── EqualsValidator.cs ├── ExistsInValidator.cs ├── FalseValidator.cs ├── FieldValidator.cs ├── GreaterThanEqualValidator.cs ├── GreaterThanValidator.cs ├── IErrorStringProvider.cs ├── IValidatorProvider.cs ├── LessThanEqualValidator.cs ├── LessThanValidator.cs ├── MatchPatternValidator.cs ├── MethodInvocationValidator.cs ├── NotEmptyValidator.cs ├── NotEqualsValidator.cs ├── NotExistsInValidator.cs ├── NotMatchPatternValidator.cs ├── NotNullValidator.cs ├── NullValidator.cs ├── TrueValidator.cs ├── ValidationContext.cs └── ValidationPipe.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Edon Gashi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # We've moved! 2 | Due to bigger plans we have created an organization and we moved to https://github.com/WPF-Forge/Forge.Forms 3 | 4 | # Read this for 1.1.2 5 | If you are looking for version 1.1.2 check out branch 1.1.2. Otherwise navigate to the Forge.Forms repository. 6 | -------------------------------------------------------------------------------- /WpfMaterialForms.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | True -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 2.0.0.{build} 2 | 3 | branches: 4 | 5 | only: 6 | 7 | - master 8 | 9 | only_commits: 10 | message: /\[Build\]/ 11 | 12 | image: Visual Studio 2017 13 | 14 | configuration: Release 15 | 16 | platform: Any CPU 17 | 18 | init: 19 | 20 | - ps: >- 21 | 22 | $newVersion = $env:appveyor_build_version.Substring(0,$env:appveyor_build_version.LastIndexOf('.')); 23 | Update-AppveyorBuild -Version "$newVersion-ci$(Get-Date -format yyyyMMdd)-$(Get-Date -format HHmmss)" 24 | 25 | assembly_info: 26 | 27 | patch: true 28 | 29 | file: '**\AssemblyInfo.*' 30 | 31 | assembly_version: 2.0.0.0 32 | 33 | assembly_file_version: 2.0.0.{build} 34 | 35 | assembly_informational_version: 2.0.0.{build} 36 | 37 | before_build: 38 | 39 | - ps: nuget restore 40 | 41 | build: 42 | 43 | project: src\MaterialForms\MaterialForms.csproj 44 | 45 | verbosity: minimal 46 | 47 | after_build: 48 | 49 | - ps: nuget pack src\MaterialForms\MaterialForms.csproj -Version $env:APPVEYOR_BUILD_VERSION -IncludeReferencedProjects 50 | 51 | artifacts: 52 | 53 | - path: '**\MaterialForms.*.nupkg' 54 | 55 | deploy: 56 | 57 | - provider: NuGet 58 | 59 | api_key: 60 | 61 | secure: ALElYwQcTMo/PpXFNBakLvjgDsuJHunVnIhbccQulTM/9mCNRhyD1HpEehGD46n/ 62 | -------------------------------------------------------------------------------- /doc/dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edongashi/WpfMaterialForms/7f19ac3e6a9919f11ae826efc4dd23ac7e7b8d12/doc/dialog.png -------------------------------------------------------------------------------- /doc/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edongashi/WpfMaterialForms/7f19ac3e6a9919f11ae826efc4dd23ac7e7b8d12/doc/email.png -------------------------------------------------------------------------------- /doc/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edongashi/WpfMaterialForms/7f19ac3e6a9919f11ae826efc4dd23ac7e7b8d12/doc/login.png -------------------------------------------------------------------------------- /doc/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edongashi/WpfMaterialForms/7f19ac3e6a9919f11ae826efc4dd23ac7e7b8d12/doc/settings.png -------------------------------------------------------------------------------- /doc/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edongashi/WpfMaterialForms/7f19ac3e6a9919f11ae826efc4dd23ac7e7b8d12/doc/user.png -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/IMenuCommand.cs: -------------------------------------------------------------------------------- 1 | using MaterialDesignThemes.Wpf; 2 | 3 | namespace Material.Application.Commands 4 | { 5 | public interface IMenuCommand : IRefreshableCommand 6 | { 7 | string CommandText { get; } 8 | 9 | PackIconKind? IconKind { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/IRefreshableCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | 3 | namespace Material.Application.Commands 4 | { 5 | public interface IRefreshableCommand : ICommand 6 | { 7 | void RaiseCanExecuteChanged(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/Internal/Menu/AsyncRouteActionMenuCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Material.Application.Routing; 4 | using MaterialDesignThemes.Wpf; 5 | 6 | namespace Material.Application.Commands 7 | { 8 | internal class AsyncRouteActionMenuCommand : AsyncRouteActionCommand, IMenuCommand 9 | { 10 | public AsyncRouteActionMenuCommand(Route route, string commandText, PackIconKind? iconKind, Func execute, 11 | Func canExecute) 12 | : base(route, execute, canExecute) 13 | { 14 | CommandText = commandText; 15 | IconKind = iconKind; 16 | } 17 | 18 | public string CommandText { get; } 19 | 20 | public PackIconKind? IconKind { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/Internal/Menu/AsyncRouteMenuCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Material.Application.Routing; 4 | using MaterialDesignThemes.Wpf; 5 | 6 | namespace Material.Application.Commands 7 | { 8 | internal class AsyncRouteMenuCommand : AsyncRouteCommand, IMenuCommand 9 | where TParameter : class 10 | { 11 | public AsyncRouteMenuCommand(Route route, string commandText, PackIconKind? iconKind, 12 | Func execute, Predicate canExecute, bool ignoreNullParameters) 13 | : base(route, execute, canExecute, ignoreNullParameters) 14 | { 15 | CommandText = commandText; 16 | IconKind = iconKind; 17 | } 18 | 19 | public string CommandText { get; } 20 | 21 | public PackIconKind? IconKind { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/Internal/Menu/AsyncRouteValueMenuCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Material.Application.Routing; 4 | using MaterialDesignThemes.Wpf; 5 | 6 | namespace Material.Application.Commands 7 | { 8 | internal class AsyncRouteValueMenuCommand : AsyncRouteValueCommand, IMenuCommand 9 | where TParameter : struct 10 | { 11 | public AsyncRouteValueMenuCommand(Route route, string commandText, PackIconKind? iconKind, 12 | Func execute, Predicate canExecute) 13 | : base(route, execute, canExecute) 14 | { 15 | CommandText = commandText; 16 | IconKind = iconKind; 17 | } 18 | 19 | public string CommandText { get; } 20 | 21 | public PackIconKind? IconKind { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/Internal/Menu/RouteActionMenuCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Material.Application.Routing; 3 | using MaterialDesignThemes.Wpf; 4 | 5 | namespace Material.Application.Commands 6 | { 7 | internal class RouteActionMenuCommand : RouteActionCommand, IMenuCommand 8 | { 9 | public RouteActionMenuCommand(Route route, string commandText, PackIconKind? iconKind, Action execute, 10 | Func canExecute) 11 | : base(route, execute, canExecute) 12 | { 13 | CommandText = commandText; 14 | IconKind = iconKind; 15 | } 16 | 17 | public string CommandText { get; } 18 | 19 | public PackIconKind? IconKind { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/Internal/Menu/RouteMenuCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Material.Application.Routing; 3 | using MaterialDesignThemes.Wpf; 4 | 5 | namespace Material.Application.Commands 6 | { 7 | internal class RouteMenuCommand : RouteCommand, IMenuCommand where TParameter : class 8 | { 9 | public RouteMenuCommand(Route route, string commandText, PackIconKind? iconKind, Action execute, 10 | Predicate canExecute, bool ignoreNullParameters) 11 | : base(route, execute, canExecute, ignoreNullParameters) 12 | { 13 | CommandText = commandText; 14 | IconKind = iconKind; 15 | } 16 | 17 | public string CommandText { get; } 18 | 19 | public PackIconKind? IconKind { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/Internal/Menu/RouteValueMenuCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Material.Application.Routing; 3 | using MaterialDesignThemes.Wpf; 4 | 5 | namespace Material.Application.Commands 6 | { 7 | internal class RouteValueMenuCommand : RouteValueCommand, IMenuCommand 8 | where TParameter : struct 9 | { 10 | public RouteValueMenuCommand(Route route, string commandText, PackIconKind? iconKind, Action execute, 11 | Predicate canExecute) 12 | : base(route, execute, canExecute) 13 | { 14 | CommandText = commandText; 15 | IconKind = iconKind; 16 | } 17 | 18 | public string CommandText { get; } 19 | 20 | public PackIconKind? IconKind { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Commands/UntrackedCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Material.Application.Commands 4 | { 5 | public class UntrackedCommand : IRefreshableCommand 6 | { 7 | private readonly Predicate canExecute; 8 | private readonly Action execute; 9 | 10 | public UntrackedCommand(Action execute) : this(execute, null) 11 | { 12 | } 13 | 14 | public UntrackedCommand(Action execute, 15 | Predicate canExecute) 16 | { 17 | this.execute = execute; 18 | this.canExecute = canExecute; 19 | } 20 | 21 | public event EventHandler CanExecuteChanged; 22 | 23 | public bool CanExecute(object parameter) 24 | { 25 | return canExecute == null || canExecute(parameter); 26 | } 27 | 28 | public void Execute(object parameter) 29 | { 30 | execute(parameter); 31 | } 32 | 33 | public void RaiseCanExecuteChanged() 34 | { 35 | CanExecuteChanged?.Invoke(this, EventArgs.Empty); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Controls/BindingProxy.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace Material.Application.Controls 4 | { 5 | public class BindingProxy : Freezable 6 | { 7 | public static readonly DependencyProperty DataProperty = DependencyProperty.Register( 8 | nameof(Data), 9 | typeof(object), 10 | typeof(BindingProxy), 11 | new UIPropertyMetadata(null)); 12 | 13 | public object Data 14 | { 15 | get { return GetValue(DataProperty); } 16 | set { SetValue(DataProperty, value); } 17 | } 18 | 19 | protected override Freezable CreateInstanceCore() 20 | { 21 | return new BindingProxy(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Controls/ConfirmableButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | 6 | namespace Material.Application.Controls 7 | { 8 | public class ConfirmableButton : Button 9 | { 10 | public static readonly DependencyProperty ConfirmationFunctionProperty = 11 | DependencyProperty.Register("ConfirmationFunction", 12 | typeof(Func>), 13 | typeof(ConfirmableButton), 14 | new FrameworkPropertyMetadata(null)); 15 | 16 | public Func> ConfirmationFunction 17 | { 18 | get { return (Func>)GetValue(ConfirmationFunctionProperty); } 19 | set { SetValue(ConfirmationFunctionProperty, value); } 20 | } 21 | 22 | protected override async void OnClick() 23 | { 24 | var confirmed = true; 25 | var confirmationFunction = ConfirmationFunction; 26 | if (confirmationFunction != null) 27 | { 28 | try 29 | { 30 | confirmed = await confirmationFunction(this); 31 | } 32 | catch 33 | { 34 | // ignored 35 | } 36 | } 37 | 38 | if (confirmed) 39 | { 40 | base.OnClick(); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Controls/ISortable.cs: -------------------------------------------------------------------------------- 1 | namespace Material.Application.Controls 2 | { 3 | public interface ISortable 4 | { 5 | void Sort(string propertyName, string direction); 6 | } 7 | } -------------------------------------------------------------------------------- /src/Demo/Material.Application/Controls/LockableToggleButton.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls.Primitives; 3 | 4 | namespace Material.Application.Controls 5 | { 6 | internal class LockableToggleButton : ToggleButton 7 | { 8 | public static readonly DependencyProperty LockToggleProperty = 9 | DependencyProperty.Register("LockToggle", typeof(bool), typeof(LockableToggleButton), 10 | new UIPropertyMetadata(false)); 11 | 12 | public LockableToggleButton() 13 | { 14 | SetResourceReference(StyleProperty, typeof(ToggleButton)); 15 | } 16 | 17 | public bool LockToggle 18 | { 19 | get { return (bool)GetValue(LockToggleProperty); } 20 | set { SetValue(LockToggleProperty, value); } 21 | } 22 | 23 | protected override void OnToggle() 24 | { 25 | if (!LockToggle) 26 | { 27 | base.OnToggle(); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Controls/MaterialRoutesWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Media; 4 | using MahApps.Metro.Controls; 5 | using Material.Application.Infrastructure; 6 | using Material.Application.Routing; 7 | 8 | namespace Material.Application.Controls 9 | { 10 | /// 11 | /// Interaction logic for MaterialRoutesWindow.xaml 12 | /// 13 | public partial class MaterialRoutesWindow : MetroWindow 14 | { 15 | private readonly AppController controller; 16 | 17 | public MaterialRoutesWindow(AppController controller) 18 | { 19 | if (controller == null) 20 | { 21 | throw new ArgumentNullException(nameof(controller)); 22 | } 23 | 24 | DataContext = controller; 25 | this.controller = controller; 26 | InitializeComponent(); 27 | } 28 | 29 | public object CurrentView => VisualTreeHelper.GetChild(RouteContentPresenter, 0); 30 | 31 | private void MenuRoute_Click(object sender, RoutedEventArgs e) 32 | { 33 | if (!controller.IsMenuOpen) 34 | { 35 | return; 36 | } 37 | 38 | controller.IsMenuOpen = false; 39 | var route = ((FrameworkElement)sender).DataContext as Route; 40 | controller.Routes.Change(route); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Controls/NullAsSeparatorTemplateSelector.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace Material.Application.Controls 5 | { 6 | internal class NullAsSeparatorTemplateSelector : DataTemplateSelector 7 | { 8 | public override DataTemplate SelectTemplate(object item, DependencyObject container) 9 | { 10 | var element = container as FrameworkElement; 11 | if (element == null) 12 | { 13 | return null; 14 | } 15 | 16 | if (item == null) 17 | { 18 | return element.FindResource("SeparatorDataTemplate") as DataTemplate; 19 | } 20 | 21 | return element.FindResource("ItemDataTemplate") as DataTemplate; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Helpers/CollectionHelpers.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Material.Application.Helpers 4 | { 5 | public static class CollectionHelpers 6 | { 7 | public static bool IsNullOrEmpty(ICollection collection) 8 | { 9 | return collection == null || collection.Count == 0; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Helpers/Internal/ErrorMessages.cs: -------------------------------------------------------------------------------- 1 | namespace Material.Application.Helpers 2 | { 3 | internal static class ErrorMessages 4 | { 5 | public const string MustHaveRoutes = "Current object must be associated with a route stack."; 6 | 7 | public const string RoutesAssociatedWithOtherStack = "Route is already associated with another stack."; 8 | 9 | public const string MustBeActiveRoute = 10 | "Cannot initiate route transitions if current object is not the active route."; 11 | 12 | public const string MainWindowNotFound = "No window has been shown for current controller."; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Helpers/Internal/IocHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Ninject.Parameters; 4 | 5 | namespace Material.Application.Helpers 6 | { 7 | internal static class IocHelpers 8 | { 9 | public static IParameter MapParameter(KeyValuePair parameter) 10 | { 11 | var key = parameter.Key; 12 | if (string.IsNullOrEmpty(key)) 13 | { 14 | throw new InvalidOperationException("Null or empty key provided as parameter name."); 15 | } 16 | 17 | if (char.IsUpper(key[0])) 18 | { 19 | return new PropertyValue(key, parameter.Value); 20 | } 21 | 22 | return new ConstructorArgument(key, parameter.Value); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Helpers/Internal/RouteErrorListenerExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Material.Application.Routing; 3 | 4 | namespace Material.Application.Helpers 5 | { 6 | internal static class RouteErrorListenerExtensions 7 | { 8 | public static void TryOnRouteEventException(this IRouteErrorListener listener, Route route, 9 | RouteEventType eventType, Exception exception) 10 | { 11 | if (listener == null) 12 | { 13 | return; 14 | } 15 | 16 | try 17 | { 18 | listener.OnRouteEventException(route, eventType, exception); 19 | } 20 | catch 21 | { 22 | // ignored 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Helpers/LanguageHelpers.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Reflection; 3 | using System.Windows.Markup; 4 | 5 | namespace Material.Application.Helpers 6 | { 7 | public static class LanguageHelpers 8 | { 9 | public static XmlLanguage CreateXmlLanguage(string name, CultureInfo cultureInfo) 10 | { 11 | var xmlLanguage = XmlLanguage.GetLanguage(name); 12 | var cultureProperty = xmlLanguage.GetType() 13 | .GetField("_specificCulture", BindingFlags.NonPublic | BindingFlags.Instance); 14 | cultureProperty?.SetValue(xmlLanguage, cultureInfo); 15 | return xmlLanguage; 16 | } 17 | 18 | public static CultureInfo CreateCulture(string name) 19 | { 20 | return CreateCulture(name, "dd/MM/yyyy", "/"); 21 | } 22 | 23 | public static CultureInfo CreateCulture(string name, string datePattern, string dateSeperator) 24 | { 25 | var cultureInfo = CultureInfo.CreateSpecificCulture(name); 26 | cultureInfo.DateTimeFormat.ShortDatePattern = datePattern; 27 | cultureInfo.DateTimeFormat.DateSeparator = dateSeperator; 28 | return cultureInfo; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/IContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Material.Application.Infrastructure 4 | { 5 | public interface IContext 6 | { 7 | bool IsSynchronized { get; } 8 | 9 | void Invoke(Action action); 10 | } 11 | 12 | public static class ContextExtensions 13 | { 14 | public static void VerifyAccess(this IContext context) 15 | { 16 | if (!context.IsSynchronized) 17 | { 18 | throw new InvalidOperationException( 19 | "The calling thread does not have access to this synchronization context."); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/IFilePicker.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Material.Application.Infrastructure 4 | { 5 | public interface IFilePicker 6 | { 7 | string GetFile(string fileName, string filter); 8 | } 9 | 10 | public interface IFileSaver 11 | { 12 | string GetFile(string fileName, string filter); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/ILocalizationService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using Material.Application.Localization; 4 | 5 | namespace Material.Application.Infrastructure 6 | { 7 | public interface ILocalizationService 8 | { 9 | Language CurrentLanguage { get; } 10 | 11 | string GetString(string key); 12 | 13 | event EventHandler LanguageChanged; 14 | 15 | void SwitchLanguage(string languageKey); 16 | 17 | void RegisterLanguage(string languageKey, Language language); 18 | 19 | Language GetLanguage(string languageKey); 20 | } 21 | 22 | public static class LocalizationServiceExtensions 23 | { 24 | public static void SubscribeLanguageChanged(this ILocalizationService localizationService, 25 | EventHandler handler) 26 | { 27 | WeakEventManager.AddHandler(localizationService, 28 | nameof(ILocalizationService.LanguageChanged), handler); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/IMainWindowController.cs: -------------------------------------------------------------------------------- 1 | namespace Material.Application.Infrastructure 2 | { 3 | public interface IMainWindowController 4 | { 5 | string Title { get; set; } 6 | 7 | double FontSize { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/IMainWindowLocator.cs: -------------------------------------------------------------------------------- 1 | using Material.Application.Controls; 2 | 3 | namespace Material.Application.Infrastructure 4 | { 5 | public interface IMainWindowLocator 6 | { 7 | MaterialRoutesWindow GetMainWindow(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/INotificationService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Material.Application.Infrastructure 4 | { 5 | public interface INotificationService 6 | { 7 | void Notify(string message); 8 | 9 | void Notify(string message, string actionLabel, Action action); 10 | 11 | void ForceNotify(string message); 12 | 13 | void ForceNotify(string message, string actionLabel, Action action); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/IPaletteService.cs: -------------------------------------------------------------------------------- 1 | namespace Material.Application.Infrastructure 2 | { 3 | public interface IPaletteService 4 | { 5 | bool DarkMode { get; set; } 6 | 7 | string LightModePrimary { get; set; } 8 | 9 | string LightModeAccent { get; set; } 10 | 11 | string DarkModePrimary { get; set; } 12 | 13 | string DarkModeAccent { get; set; } 14 | 15 | void RefreshTheme(); 16 | 17 | void RefreshPalette(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/ISingleton.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using Material.Application.Properties; 4 | 5 | namespace Material.Application.Infrastructure 6 | { 7 | public interface ISingleton where T : class 8 | { 9 | T Instance { get; set; } 10 | } 11 | 12 | public class Singleton : ISingleton, INotifyPropertyChanged where T : class 13 | { 14 | private T instance; 15 | 16 | public Singleton(T instance) 17 | { 18 | Instance = instance; 19 | } 20 | 21 | public T Instance 22 | { 23 | get { return instance; } 24 | set 25 | { 26 | if (Equals(value, instance)) return; 27 | instance = value; 28 | OnPropertyChanged(); 29 | } 30 | } 31 | 32 | public event PropertyChangedEventHandler PropertyChanged; 33 | 34 | [NotifyPropertyChangedInvocator] 35 | protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 36 | { 37 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/Internal/DialogFilePicker.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | 3 | namespace Material.Application.Infrastructure 4 | { 5 | internal class DialogFilePicker : IFilePicker 6 | { 7 | public string GetFile(string fileName, string filter) 8 | { 9 | var openFileDialog = new OpenFileDialog 10 | { 11 | FileName = fileName ?? string.Empty, 12 | Filter = filter 13 | }; 14 | 15 | return openFileDialog.ShowDialog() == true ? openFileDialog.FileName : null; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/Internal/DialogFileSaver.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | 3 | namespace Material.Application.Infrastructure 4 | { 5 | internal class DialogFileSaver : IFileSaver 6 | { 7 | public string GetFile(string fileName, string filter) 8 | { 9 | var saveFileDialog = new SaveFileDialog 10 | { 11 | FileName = fileName ?? string.Empty, 12 | Filter = filter 13 | }; 14 | 15 | return saveFileDialog.ShowDialog() == true ? saveFileDialog.FileName : null; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/Internal/DialogHostService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Material.Application.Helpers; 3 | using MaterialForms; 4 | 5 | namespace Material.Application.Infrastructure 6 | { 7 | internal class DialogHostService : IDialogService 8 | { 9 | private readonly IMainWindowLocator windowLocator; 10 | 11 | public DialogHostService(IMainWindowLocator windowLocator) 12 | { 13 | this.windowLocator = windowLocator; 14 | } 15 | 16 | public DialogSession ShowTrackedDialog(MaterialDialog dialog, double width) 17 | { 18 | var window = windowLocator.GetMainWindow(); 19 | if (window == null) 20 | { 21 | throw new InvalidOperationException(ErrorMessages.MainWindowNotFound); 22 | } 23 | 24 | return dialog.ShowTracked(window.RootDialog.Identifier.ToString(), width); 25 | } 26 | 27 | public void CloseDialogs() 28 | { 29 | var window = windowLocator.GetMainWindow(); 30 | if (window == null) 31 | { 32 | return; 33 | } 34 | 35 | window.RootDialog.IsOpen = false; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/Internal/DispatcherContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Threading; 3 | 4 | namespace Material.Application.Infrastructure 5 | { 6 | internal class DispatcherContext : IContext 7 | { 8 | private readonly Dispatcher dispatcher; 9 | 10 | public DispatcherContext(Dispatcher dispatcher) 11 | { 12 | this.dispatcher = dispatcher; 13 | } 14 | 15 | public bool IsSynchronized => dispatcher.CheckAccess(); 16 | 17 | public void Invoke(Action action) => dispatcher.Invoke(action); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/Internal/NinjectServiceLocator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Material.Application.Helpers; 5 | using Ninject; 6 | 7 | namespace Material.Application.Infrastructure 8 | { 9 | internal class NinjectServiceLocator : IServiceLocator 10 | { 11 | private readonly IKernel kernel; 12 | 13 | public NinjectServiceLocator(IKernel kernel) 14 | { 15 | this.kernel = kernel; 16 | } 17 | 18 | public T Get(IDictionary parameters) => parameters == null 19 | ? kernel.Get() 20 | : kernel.Get(parameters.Select(IocHelpers.MapParameter).ToArray()); 21 | 22 | public object Get(Type type, IDictionary parameters) => parameters == null 23 | ? kernel.Get(type) 24 | : kernel.Get(type, parameters.Select(IocHelpers.MapParameter).ToArray()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/Internal/PaletteService.cs: -------------------------------------------------------------------------------- 1 | using MaterialDesignThemes.Wpf; 2 | 3 | namespace Material.Application.Infrastructure 4 | { 5 | internal class PaletteService : IPaletteService 6 | { 7 | public bool DarkMode { get; set; } 8 | 9 | public string LightModePrimary { get; set; } 10 | 11 | public string LightModeAccent { get; set; } 12 | 13 | public string DarkModePrimary { get; set; } 14 | 15 | public string DarkModeAccent { get; set; } 16 | 17 | public void RefreshTheme() 18 | { 19 | new PaletteHelper().SetLightDark(DarkMode); 20 | } 21 | 22 | public void RefreshPalette() 23 | { 24 | var paletteHelper = new PaletteHelper(); 25 | if (DarkMode) 26 | { 27 | if (DarkModePrimary != null) 28 | { 29 | paletteHelper.ReplacePrimaryColor(DarkModePrimary); 30 | } 31 | 32 | if (DarkModeAccent != null) 33 | { 34 | paletteHelper.ReplaceAccentColor(DarkModeAccent); 35 | } 36 | } 37 | else 38 | { 39 | if (LightModePrimary != null) 40 | { 41 | paletteHelper.ReplacePrimaryColor(LightModePrimary); 42 | } 43 | 44 | if (LightModeAccent != null) 45 | { 46 | paletteHelper.ReplaceAccentColor(LightModeAccent); 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Infrastructure/Internal/ServiceLocatorRouteFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Material.Application.Routing; 4 | 5 | namespace Material.Application.Infrastructure 6 | { 7 | internal class ServiceLocatorRouteFactory : IRouteFactory 8 | { 9 | private readonly IServiceLocator serviceLocator; 10 | 11 | public ServiceLocatorRouteFactory(IServiceLocator serviceLocator) 12 | { 13 | this.serviceLocator = serviceLocator; 14 | } 15 | 16 | public Route Get(Type routeType, IDictionary parameters) 17 | => (Route)serviceLocator.Get(routeType, parameters); 18 | 19 | public IRouteWrapper Get(Route caller, Type routeType, IDictionary parameters) 20 | => new RouteWrapperInternal(caller, (Route)serviceLocator.Get(routeType, parameters)); 21 | 22 | public TRoute Get(IDictionary parameters) where TRoute : Route 23 | => serviceLocator.Get(parameters); 24 | 25 | public IRouteWrapper Get(Route caller, IDictionary parameters) 26 | where TRoute : Route => new RouteWrapperInternal(caller, serviceLocator.Get(parameters)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Localization/Language.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace Material.Application.Localization 4 | { 5 | public class Language 6 | { 7 | public Language(string name, string dictionaryUri, CultureInfo cultureInfo) 8 | { 9 | Name = name; 10 | DictionaryUri = dictionaryUri; 11 | CultureInfo = cultureInfo; 12 | } 13 | 14 | public string Name { get; } 15 | 16 | public string DictionaryUri { get; } 17 | 18 | public CultureInfo CultureInfo { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/MaterialDesign/MaterialDesignHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Reflection; 3 | using System.Windows.Controls; 4 | using MaterialDesignThemes.Wpf; 5 | 6 | namespace Material.Application.MaterialDesign 7 | { 8 | public static partial class MaterialDesignHelper 9 | { 10 | public static void ReplaceDefaultHintProxies() 11 | { 12 | var list = (IList)typeof(HintProxyFabric).GetField("Builders", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); 13 | list.RemoveAt(2); 14 | list.RemoveAt(1); 15 | HintProxyFabric.RegisterBuilder(c => c is TextBox, c => new CustomTextBoxHintProxy((TextBox)c)); 16 | HintProxyFabric.RegisterBuilder(c => c is PasswordBox, c => new CustomPasswordBoxHintProxy((PasswordBox)c)); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Models/CommandRefreshSource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using Material.Application.Commands; 4 | 5 | namespace Material.Application.Models 6 | { 7 | public class CommandRefreshSource : IEnumerable 8 | { 9 | private readonly List commands = new List(); 10 | 11 | public IEnumerator GetEnumerator() => commands.GetEnumerator(); 12 | 13 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 14 | 15 | public void Add(IRefreshableCommand command) 16 | { 17 | if (command != null && !commands.Contains(command)) 18 | { 19 | commands.Add(command); 20 | } 21 | } 22 | 23 | public bool Remove(IRefreshableCommand command) => commands.Remove(command); 24 | 25 | public void Refresh() 26 | { 27 | foreach (var command in commands) 28 | { 29 | command.RaiseCanExecuteChanged(); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Models/ObjectPresenter.cs: -------------------------------------------------------------------------------- 1 | namespace Material.Application.Models 2 | { 3 | public class ObjectPresenter 4 | { 5 | public ObjectPresenter(object instance, string displayString) 6 | { 7 | Object = instance; 8 | DisplayString = displayString; 9 | } 10 | 11 | public object Object { get; } 12 | 13 | public string DisplayString { get; } 14 | 15 | public override string ToString() => DisplayString; 16 | } 17 | 18 | public class ObjectPresenter : ObjectPresenter 19 | { 20 | public ObjectPresenter(T instance, string displayString) 21 | : base(instance, displayString) 22 | { 23 | Object = instance; 24 | } 25 | 26 | public new T Object { get; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Models/PropertyRefreshSource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Material.Application.Models 5 | { 6 | public class PropertyRefreshSource : IEnumerable 7 | { 8 | private readonly Model model; 9 | private readonly List properties = new List(); 10 | 11 | public PropertyRefreshSource(Model model) 12 | { 13 | this.model = model; 14 | } 15 | 16 | public IEnumerator GetEnumerator() => properties.GetEnumerator(); 17 | 18 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 19 | 20 | public void Add(string propertyName) 21 | { 22 | if (!properties.Contains(propertyName)) 23 | { 24 | properties.Add(propertyName); 25 | } 26 | } 27 | 28 | public bool Remove(string propertyName) => properties.Remove(propertyName); 29 | 30 | public void Refresh() 31 | { 32 | foreach (var property in properties) 33 | { 34 | model.NotifyPropertyChanged(property); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Models/RefreshSource.cs: -------------------------------------------------------------------------------- 1 | using Material.Application.Commands; 2 | 3 | namespace Material.Application.Models 4 | { 5 | public class RefreshSource 6 | { 7 | public RefreshSource(Model model) 8 | { 9 | Properties = new PropertyRefreshSource(model); 10 | Commands = new CommandRefreshSource(); 11 | } 12 | 13 | public PropertyRefreshSource Properties { get; } 14 | 15 | public CommandRefreshSource Commands { get; } 16 | 17 | public void Refresh() 18 | { 19 | Properties.Refresh(); 20 | Commands.Refresh(); 21 | } 22 | 23 | public RefreshSource WithProperties(params string[] properties) 24 | { 25 | if (properties != null) 26 | { 27 | foreach (var property in properties) 28 | { 29 | Properties.Add(property); 30 | } 31 | } 32 | 33 | return this; 34 | } 35 | 36 | public RefreshSource WithCommands(params IRefreshableCommand[] commands) 37 | { 38 | if (commands != null) 39 | { 40 | foreach (var command in commands) 41 | { 42 | Commands.Add(command); 43 | } 44 | } 45 | 46 | return this; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Routing/Default/ListRoute.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using System.Windows.Input; 4 | using Material.Application.Views; 5 | 6 | namespace Material.Application.Routing.Default 7 | { 8 | public class ListRoute : Route 9 | { 10 | private object selectedItem; 11 | private string displayMemberPath; 12 | 13 | public ListRoute(string title, IEnumerable items) 14 | { 15 | RouteConfig.Title = title; 16 | RouteConfig.KeyBindings.Add(new KeyBinding(PopRouteCommand, Key.Escape, ModifierKeys.None)); 17 | Items = new ObservableCollection(items); 18 | } 19 | 20 | public ObservableCollection Items { get; } 21 | 22 | public object SelectedItem 23 | { 24 | get => selectedItem; 25 | set 26 | { 27 | if (Equals(value, selectedItem)) return; 28 | selectedItem = value; 29 | NotifyPropertyChanged(); 30 | } 31 | } 32 | 33 | public string DisplayMemberPath 34 | { 35 | get => displayMemberPath; 36 | set 37 | { 38 | if (value == displayMemberPath) return; 39 | displayMemberPath = value; 40 | NotifyPropertyChanged(); 41 | } 42 | } 43 | 44 | protected internal override object CreateView(bool isReload) 45 | { 46 | return new CollectionView(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Routing/IRouteErrorListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | namespace Material.Application.Routing 5 | { 6 | public interface IRouteErrorListener 7 | { 8 | void OnRouteEventException(Route route, RouteEventType eventType, Exception exception); 9 | 10 | void OnRouteCommandException(Route route, ICommand command, Exception exception); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Routing/Internal/RouteItem.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Material.Application.Routing 4 | { 5 | internal class RouteItem 6 | { 7 | public RouteItem(Route route) 8 | { 9 | Route = route; 10 | CompletionSource = new TaskCompletionSource(); 11 | } 12 | 13 | public Route Route { get; } 14 | 15 | public TaskCompletionSource CompletionSource { get; } 16 | 17 | public object CachedView { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Routing/RouteActivationMethod.cs: -------------------------------------------------------------------------------- 1 | namespace Material.Application.Routing 2 | { 3 | public enum RouteActivationMethod 4 | { 5 | Pushed, 6 | Changed, 7 | Restored 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Routing/RouteEventError.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Material.Application.Routing 4 | { 5 | public class RouteEventError 6 | { 7 | public RouteEventError(RouteEventType routeEventType, Exception exception) 8 | { 9 | RouteEventType = routeEventType; 10 | Exception = exception; 11 | } 12 | 13 | public RouteEventType RouteEventType { get; } 14 | 15 | public Exception Exception { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Routing/RouteEventType.cs: -------------------------------------------------------------------------------- 1 | namespace Material.Application.Routing 2 | { 3 | public enum RouteEventType 4 | { 5 | Deactivating, 6 | Deactivated, 7 | Hiding, 8 | Hidden, 9 | Initializing, 10 | Initialized, 11 | Activating, 12 | Activated, 13 | Restoring, 14 | Restored, 15 | Ready, 16 | ViewCreation 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Routing/RouteTransitionException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Material.Application.Routing 4 | { 5 | public class RouteTransitionException : Exception 6 | { 7 | public RouteTransitionException(string message) 8 | : base(message) 9 | { 10 | } 11 | 12 | public RouteTransitionException(string message, Exception innerException) 13 | : base(message, innerException) 14 | { 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/ValueConverters/CollectionToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Windows; 6 | using System.Windows.Data; 7 | 8 | namespace Material.Application.ValueConverters 9 | { 10 | public class CollectionToVisibilityConverter : IValueConverter 11 | { 12 | public Visibility EmptyValue { get; set; } = Visibility.Hidden; 13 | 14 | public Visibility NotEmptyValue { get; set; } = Visibility.Visible; 15 | 16 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | var enumerable = value as IEnumerable; 19 | if (enumerable == null) 20 | { 21 | return EmptyValue; 22 | } 23 | 24 | return enumerable.Any() ? NotEmptyValue : EmptyValue; 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 28 | { 29 | return Binding.DoNothing; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/ValueConverters/NullToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace Material.Application.ValueConverters 7 | { 8 | internal class NullToVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | return value == null ? Visibility.Collapsed : Visibility.Visible; 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | return Binding.DoNothing; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/ValueConverters/VariableExpanderConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace Material.Application.ValueConverters 6 | { 7 | public class VariableExpanderConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return Environment.ExpandEnvironmentVariables(value?.ToString() ?? string.Empty); 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return Binding.DoNothing; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Views/CollectionView.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 24 | 25 | 26 | 32 | 33 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Views/CollectionView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace Material.Application.Views 4 | { 5 | /// 6 | /// Interaction logic for CollectionView.xaml 7 | /// 8 | public partial class CollectionView : UserControl 9 | { 10 | public CollectionView() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Views/FormView.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | 27 | 28 | 29 | 35 | 36 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Views/FormView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace Material.Application.Views 4 | { 5 | /// 6 | /// Interaction logic for FormView.xaml 7 | /// 8 | public partial class FormView : UserControl 9 | { 10 | public FormView() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Views/LoadingView.xaml: -------------------------------------------------------------------------------- 1 |  10 | 13 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Views/LoadingView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace Material.Application.Views 4 | { 5 | /// 6 | /// Interaction logic for Loading.xaml 7 | /// 8 | internal partial class LoadingView : UserControl 9 | { 10 | public LoadingView(string message) 11 | { 12 | InitializeComponent(); 13 | if (!string.IsNullOrWhiteSpace(message)) 14 | { 15 | MessageTextBlock.Text = message; 16 | } 17 | else 18 | { 19 | StackPanel.Children.RemoveAt(1); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/Views/View.cs: -------------------------------------------------------------------------------- 1 | namespace Material.Application.Views 2 | { 3 | public static class View 4 | { 5 | public static object Loading() => new LoadingView(null); 6 | 7 | public static object Loading(string message) => new LoadingView(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Demo/Material.Application/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using MaterialForms.Demo.Infrastructure; 4 | 5 | namespace MaterialForms.Demo { 6 | /// 7 | /// Interaction logic for App.xaml 8 | /// 9 | public partial class App : Application { 10 | [STAThread] 11 | public static void Main () { 12 | var app = new App (); 13 | app.InitializeComponent (); 14 | app.Run (); 15 | } 16 | 17 | public DemoAppController Controller { get; } 18 | 19 | public App () { 20 | 21 | Controller = new DemoAppController (); 22 | } 23 | 24 | protected void OnStartup (object sender, StartupEventArgs e) { 25 | Controller.ShowApplicationWindow (); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Infrastructure/DemoAppController.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using MahApps.Metro.Controls; 3 | using Material.Application.Infrastructure; 4 | using Material.Application.Routing; 5 | using MaterialForms.Demo.Models; 6 | using MaterialForms.Demo.Routes; 7 | using MaterialForms.Mappers; 8 | using MaterialForms.Wpf.Annotations; 9 | using MaterialForms.Wpf.Controls; 10 | using Proxier.Mappers; 11 | 12 | namespace MaterialForms.Demo.Infrastructure { 13 | public class LoginExtensions : MaterialMapper { 14 | public LoginExtensions () { 15 | AddPropertyAttribute(i => i.RememberMe,() => new FieldAttribute { Name = "sdfgsrysert" }); 16 | } 17 | 18 | public override void Action(Login model, string action, object parameter) 19 | { 20 | base.Action(model, action, parameter); 21 | } 22 | } 23 | 24 | public class DemoAppController : AppController { 25 | protected override void OnInitializing () { 26 | var factory = Routes.RouteFactory; 27 | Routes.MenuRoutes.Add (InitialRoute = factory.Get ()); 28 | Routes.MenuRoutes.Add (factory.Get ()); 29 | Routes.MenuRoutes.Add (factory.Get ()); 30 | FontSize = 15d; 31 | 32 | var window = new MetroWindow () { Content = new DynamicForm { Model = new Login () }, WindowStartupLocation = WindowStartupLocation.CenterScreen, Height = 200, Width = 200 }; 33 | window.Show (); 34 | } 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/ModelTypeToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.Demo 7 | { 8 | public class ModelTypeToVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (value == null || value is string || value is ValueType) 13 | { 14 | return Visibility.Collapsed; 15 | } 16 | 17 | return Visibility.Visible; 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 21 | { 22 | return Binding.DoNothing; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Models/ExamplePresenter.cs: -------------------------------------------------------------------------------- 1 | using Material.Application.Models; 2 | 3 | namespace MaterialForms.Demo.Models 4 | { 5 | public class ExamplePresenter : ObjectPresenter 6 | { 7 | public ExamplePresenter(object instance, string displayString, double preferredWidth) 8 | : base(instance, displayString) 9 | { 10 | PreferredWidth = preferredWidth; 11 | } 12 | 13 | public double PreferredWidth { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Models/Login.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using MaterialDesignThemes.Wpf; 4 | using MaterialForms.Wpf; 5 | using MaterialForms.Wpf.Annotations; 6 | using MaterialForms.Wpf.Annotations.Display; 7 | using PropertyChanged; 8 | 9 | namespace MaterialForms.Demo.Models 10 | { 11 | [Title("Login to continue")] 12 | [Action("cancel", "CANCEL", IsCancel = true)] 13 | [Action("login", "LOG IN", IsLoading = "{Binding Loading}", IsDefault = true)] 14 | [AddINotifyPropertyChangedInterface] 15 | public class Login : IActionHandler 16 | { 17 | // Enums may be deserialized from strings. 18 | [Field(Icon = "Account")] 19 | public string Username { get; set; } 20 | 21 | // Or be dynamically assigned... 22 | [Field(Icon = "{Property PasswordIcon}")] 23 | [Password] 24 | public string Password { get; set; } 25 | 26 | public bool RememberMe { get; set; } 27 | 28 | public bool Loading { get; set; } 29 | 30 | public PackIconKind PasswordIcon => PackIconKind.Key; 31 | 32 | /// 33 | public void HandleAction(object model, string action, object parameter) 34 | { 35 | Loading = !Loading; 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Models/ProgressModel.cs: -------------------------------------------------------------------------------- 1 | using MaterialForms.Wpf.Annotations; 2 | using MaterialForms.Wpf.Annotations.Display; 3 | 4 | namespace MaterialForms.Demo.Models 5 | { 6 | public class ProgressModel 7 | { 8 | [Text("Loading...")] 9 | 10 | [Field, Progress] 11 | public double Progress => 60d; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Models/Selection.cs: -------------------------------------------------------------------------------- 1 | using MaterialDesignThemes.Wpf; 2 | using MaterialForms.Wpf.Annotations; 3 | 4 | namespace MaterialForms.Demo.Models 5 | { 6 | public enum Gender 7 | { 8 | Male, 9 | Female 10 | } 11 | 12 | public enum AgeGroup 13 | { 14 | [EnumDisplay("0-18")] 15 | ZeroToEighteen, 16 | [EnumDisplay("18-39")] 17 | EighteenToThirtyNine, 18 | [EnumDisplay("40+")] 19 | FortyPlus 20 | } 21 | 22 | public enum YesNo 23 | { 24 | Yes, 25 | No 26 | } 27 | 28 | public class Selection 29 | { 30 | [SelectFrom(typeof(Gender), SelectionType = SelectionType.RadioButtons)] 31 | public Gender? Gender { get; set; } 32 | 33 | [SelectFrom(typeof(AgeGroup))] 34 | public AgeGroup AgeGroup { get; set; } 35 | 36 | [Field(Icon = PackIconKind.Star)] 37 | [SelectFrom(new[] { "Fantastic", "Good", "Average", "Bad" })] 38 | public string RateThisFeature { get; set; } 39 | 40 | [SelectFrom("{Binding Seats}", SelectionType = SelectionType.ComboBoxEditable)] 41 | public int NumberOfSeats { get; set; } 42 | 43 | [SelectFrom(typeof(YesNo?))] 44 | public YesNo? DeselectMe { get; set; } = YesNo.Yes; 45 | 46 | public int[] Seats => new[] { 1, 2, 3, 4 }; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MaterialForms.Demo.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/ViewBindings.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Views/ExamplesView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace MaterialForms.Demo.Views 4 | { 5 | /// 6 | /// Interaction logic for ExamplesView.xaml 7 | /// 8 | public partial class ExamplesView : UserControl 9 | { 10 | public ExamplesView() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Views/FormView.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | 27 | 28 | 29 | 35 | 36 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Views/FormView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace MaterialForms.Demo.Views 4 | { 5 | /// 6 | /// Interaction logic for FormView.xaml 7 | /// 8 | public partial class FormView : UserControl 9 | { 10 | public FormView() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Demo/MaterialForms.Demo/Views/XmlExamplesView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace MaterialForms.Demo.Views 17 | { 18 | /// 19 | /// Interaction logic for XmlExamplesView.xaml 20 | /// 21 | public partial class XmlExamplesView : UserControl 22 | { 23 | public XmlExamplesView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/MaterialForms.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MaterialForms.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MaterialForms.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("528fbdc1-500c-4c3b-ad72-f8fb49e778fe")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/MaterialForms/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/MaterialForms/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/MaterialForms/MaterialForms.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | True 4 | False 5 | False 6 | True -------------------------------------------------------------------------------- /src/MaterialForms/Old/ColorAssist.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Media; 8 | 9 | namespace MaterialForms 10 | { 11 | public class ColorAssist 12 | { 13 | public static readonly DependencyProperty ForegroundProperty = 14 | DependencyProperty.RegisterAttached( 15 | "Foreground", 16 | typeof(Brush), 17 | typeof(ColorAssist), 18 | new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.Inherits)); 19 | 20 | public static readonly DependencyProperty OpacityProperty = 21 | DependencyProperty.RegisterAttached( 22 | "Opacity", 23 | typeof(double), 24 | typeof(ColorAssist), 25 | new FrameworkPropertyMetadata(0.54d, FrameworkPropertyMetadataOptions.Inherits)); 26 | 27 | public static readonly DependencyProperty DisabledOpacityProperty = 28 | DependencyProperty.RegisterAttached( 29 | "DisabledOpacity", 30 | typeof(double), 31 | typeof(ColorAssist), 32 | new FrameworkPropertyMetadata(0.38d, FrameworkPropertyMetadataOptions.Inherits)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/ButtonControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class ButtonControl : UserControl 24 | { 25 | public ButtonControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/CaptionControl.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/CaptionControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class CaptionControl : UserControl 24 | { 25 | public CaptionControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/CheckBoxControl.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/CheckBoxControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class CheckBoxControl : UserControl 24 | { 25 | public CheckBoxControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/ComboBoxControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class ComboBoxControl : UserControl 24 | { 25 | public ComboBoxControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/DatePickerControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class DatePickerControl : UserControl 24 | { 25 | public DatePickerControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/FileLoaderControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using Microsoft.Win32; 17 | using MaterialForms; 18 | 19 | namespace MaterialForms.Controls 20 | { 21 | /// 22 | /// Interaction logic for SingleLineTextControl.xaml 23 | /// 24 | public partial class FileLoaderControl : UserControl 25 | { 26 | public FileLoaderControl() 27 | { 28 | InitializeComponent(); 29 | } 30 | 31 | private void Button_Click(object sender, RoutedEventArgs e) 32 | { 33 | var context = DataContext as SingleFileSchema; 34 | if (context == null) 35 | { 36 | return; 37 | } 38 | 39 | var dialog = new OpenFileDialog(); 40 | if (context.Filter != null) 41 | { 42 | dialog.Filter = context.Filter; 43 | } 44 | 45 | if (dialog.ShowDialog() == true) 46 | { 47 | var fileName = dialog.FileName; 48 | context.Value = fileName; 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/KeyValueControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class KeyValueControl : UserControl 24 | { 25 | public KeyValueControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/MultiLineTextControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class MultiLineTextControl : UserControl 24 | { 25 | public MultiLineTextControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/MultiSchemaControl.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/PasswordTextControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using System.Windows.Data; 7 | 8 | namespace MaterialForms.Controls 9 | { 10 | /// 11 | /// Interaction logic for SingleLineTextControl.xaml 12 | /// 13 | public partial class PasswordTextControl : UserControl 14 | { 15 | public static readonly DependencyProperty PasswordProperty = 16 | DependencyProperty.Register("Password", 17 | typeof(SecureString), 18 | typeof(PasswordBox), 19 | new PropertyMetadata(default(SecureString))); 20 | 21 | public SecureString Password 22 | { 23 | get { return (SecureString)ValueHolderControl.GetValue(PasswordProperty); } 24 | set { ValueHolderControl.SetValue(PasswordProperty, value); } 25 | } 26 | 27 | public PasswordTextControl() 28 | { 29 | InitializeComponent(); 30 | ValueHolderControl.PasswordChanged += (sender, args) => 31 | { 32 | Password = ((PasswordBox)sender).SecurePassword; 33 | }; 34 | 35 | var binding = new Binding("Value") 36 | { 37 | Mode = BindingMode.TwoWay, 38 | UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged 39 | }; 40 | 41 | ValueHolderControl.SetBinding(PasswordProperty, binding); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/ProgressControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class ProgressControl : UserControl 24 | { 25 | public ProgressControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/SingleLineTextControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Controls 6 | { 7 | /// 8 | /// Interaction logic for SingleLineTextControl.xaml 9 | /// 10 | public partial class SingleLineTextControl : UserControl 11 | { 12 | public SingleLineTextControl() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | public SingleLineTextControl(IValueConverter converter) 18 | { 19 | InitializeComponent(); 20 | var binding = new Binding("Value") { Converter = converter }; 21 | ValueHolderControl.SetBinding(TextBox.TextProperty, binding); 22 | } 23 | 24 | private void SingleLineTextControl_OnLoaded(object sender, RoutedEventArgs e) 25 | { 26 | ValueHolderControl.SelectAll(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/SliderControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class SliderControl : UserControl 24 | { 25 | public SliderControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/SwitchControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class SwitchControl : UserControl 24 | { 25 | public SwitchControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Controls/TimePickerControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using MaterialDesignThemes.Wpf; 16 | using MaterialForms; 17 | 18 | namespace MaterialForms.Controls 19 | { 20 | /// 21 | /// Interaction logic for SingleLineTextControl.xaml 22 | /// 23 | public partial class TimePickerControl : UserControl 24 | { 25 | public TimePickerControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/DataSchema/BooleanSchema.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using MaterialForms.Controls; 3 | 4 | namespace MaterialForms 5 | { 6 | public class BooleanSchema : SchemaBase 7 | { 8 | private bool value; 9 | private bool isCheckBox; 10 | 11 | public bool Value 12 | { 13 | get { return value; } 14 | set 15 | { 16 | if (value == this.value) return; 17 | this.value = value; 18 | OnPropertyChanged(); 19 | } 20 | } 21 | 22 | public bool IsCheckBox 23 | { 24 | get { return isCheckBox; } 25 | set 26 | { 27 | if (value == isCheckBox) return; 28 | isCheckBox = value; 29 | OnPropertyChanged(); 30 | OnPropertyChanged(nameof(View)); 31 | } 32 | } 33 | 34 | public override UserControl CreateView() 35 | { 36 | if (isCheckBox) 37 | { 38 | return new CheckBoxControl 39 | { 40 | DataContext = this 41 | }; 42 | } 43 | 44 | return new SwitchControl 45 | { 46 | DataContext = this 47 | }; 48 | } 49 | 50 | public override bool HoldsValue => true; 51 | 52 | public override object GetValue() => Value; 53 | 54 | public override void SetValue(object obj) 55 | { 56 | Value = obj as bool? ?? false; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/DataSchema/CaptionSchema.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using MaterialForms.Controls; 3 | 4 | namespace MaterialForms 5 | { 6 | public class CaptionSchema : SchemaBase 7 | { 8 | public override UserControl CreateView() 9 | { 10 | return new CaptionControl { DataContext = this }; 11 | } 12 | 13 | public override bool HoldsValue => false; 14 | 15 | public override object GetValue() => null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/DataSchema/DateSchema.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Controls; 3 | using MaterialForms.Controls; 4 | 5 | namespace MaterialForms 6 | { 7 | public class DateSchema : SchemaBase 8 | { 9 | private DateTime? value; 10 | 11 | public DateTime? Value 12 | { 13 | get { return value; } 14 | set 15 | { 16 | if (value.Equals(this.value)) return; 17 | this.value = value; 18 | OnPropertyChanged(); 19 | } 20 | } 21 | 22 | public override UserControl CreateView() 23 | { 24 | return new DatePickerControl 25 | { 26 | DataContext = this 27 | }; 28 | } 29 | 30 | public override bool HoldsValue => true; 31 | 32 | public override object GetValue() => Value; 33 | 34 | public override void SetValue(object obj) 35 | { 36 | Value = obj as DateTime?; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/DataSchema/KeyValueSchema.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Controls; 3 | using MaterialForms.Controls; 4 | 5 | namespace MaterialForms 6 | { 7 | public class KeyValueSchema : SchemaBase 8 | { 9 | private string value; 10 | 11 | public string Value 12 | { 13 | get { return value; } 14 | set 15 | { 16 | if (value == this.value) return; 17 | this.value = value; 18 | OnPropertyChanged(); 19 | } 20 | } 21 | 22 | public override UserControl CreateView() 23 | { 24 | return new KeyValueControl 25 | { 26 | DataContext = this 27 | }; 28 | } 29 | 30 | public override bool HoldsValue => true; 31 | 32 | public override object GetValue() => Value; 33 | 34 | public override void SetValue(object obj) 35 | { 36 | Value = obj?.ToString(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/DataSchema/PasswordSchema.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | using System.Windows.Controls; 3 | using MaterialForms.Controls; 4 | 5 | namespace MaterialForms 6 | { 7 | public class PasswordSchema : SchemaBase 8 | { 9 | private SecureString value; 10 | 11 | public SecureString Value 12 | { 13 | get { return value; } 14 | set 15 | { 16 | if (Equals(value, this.value)) return; 17 | this.value = value; 18 | OnPropertyChanged(); 19 | } 20 | } 21 | 22 | public override UserControl CreateView() 23 | { 24 | return new PasswordTextControl { DataContext = this }; 25 | } 26 | 27 | public override bool HoldsValue => true; 28 | 29 | public override object GetValue() => PasswordHelpers.ConvertToUnsecureString(Value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/DataSchema/SingleFileSchema.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using MaterialForms.Controls; 3 | 4 | namespace MaterialForms 5 | { 6 | public class SingleFileSchema : SchemaBase 7 | { 8 | private string value; 9 | 10 | public string Value 11 | { 12 | get { return value; } 13 | set 14 | { 15 | if (value == this.value) return; 16 | this.value = value; 17 | OnPropertyChanged(); 18 | } 19 | } 20 | 21 | public string Filter { get; set; } 22 | 23 | public ValidationCallback Validation { get; set; } 24 | 25 | public override UserControl CreateView() 26 | { 27 | return new FileLoaderControl() 28 | { 29 | DataContext = this 30 | }; 31 | } 32 | 33 | public override bool HoldsValue => true; 34 | 35 | public override object GetValue() => Value; 36 | 37 | public override void SetValue(object obj) 38 | { 39 | Value = obj?.ToString(); 40 | } 41 | 42 | protected override bool OnValidation() 43 | { 44 | var callback = Validation; 45 | if (callback == null) 46 | { 47 | return true; 48 | } 49 | 50 | Error = callback(value); 51 | return HasNoError; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/DataSchema/TimeSchema.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using MaterialForms.Controls; 3 | 4 | namespace MaterialForms 5 | { 6 | public class TimeSchema : SchemaBase 7 | { 8 | private string value; 9 | private bool is24Hours = true; 10 | 11 | public string Value 12 | { 13 | get { return value; } 14 | set 15 | { 16 | if (value == this.value) return; 17 | this.value = value; 18 | OnPropertyChanged(); 19 | } 20 | } 21 | 22 | public bool Is24Hours 23 | { 24 | get { return is24Hours; } 25 | set 26 | { 27 | if (value == is24Hours) return; 28 | is24Hours = value; 29 | OnPropertyChanged(); 30 | } 31 | } 32 | 33 | public override UserControl CreateView() 34 | { 35 | return new TimePickerControl 36 | { 37 | DataContext = this 38 | }; 39 | } 40 | 41 | public override bool HoldsValue => true; 42 | 43 | public override object GetValue() => Value; 44 | 45 | public override void SetValue(object obj) 46 | { 47 | Value = obj?.ToString(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/DelegateCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | namespace MaterialForms 5 | { 6 | public class DelegateCommand : ICommand 7 | { 8 | private readonly Predicate canExecute; 9 | private readonly Action execute; 10 | 11 | public event EventHandler CanExecuteChanged; 12 | 13 | public DelegateCommand(Action execute) 14 | : this(execute, null) 15 | { 16 | } 17 | 18 | public DelegateCommand(Action execute, 19 | Predicate canExecute) 20 | { 21 | this.execute = execute; 22 | this.canExecute = canExecute; 23 | } 24 | 25 | public bool CanExecute(object parameter) 26 | { 27 | return canExecute == null || canExecute(parameter); 28 | } 29 | 30 | public void Execute(object parameter) 31 | { 32 | execute(parameter); 33 | } 34 | 35 | public void RaiseCanExecuteChanged() 36 | { 37 | CanExecuteChanged?.Invoke(this, EventArgs.Empty); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Extensions/InitializerExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Extensions 4 | { 5 | /// 6 | /// Helper extensions for object initialization. 7 | /// 8 | public static class InitializerExtensions 9 | { 10 | public static T With(this T instance, Action action) where T : class 11 | { 12 | action(instance); 13 | return instance; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Forms/DialogActionListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace MaterialForms 5 | { 6 | public class DialogActionListener 7 | { 8 | public DialogActionListener(MaterialDialog dialog, string action) 9 | { 10 | if (string.IsNullOrEmpty(action)) 11 | { 12 | throw new ArgumentException(nameof(action)); 13 | } 14 | 15 | switch (action.ToLower()) 16 | { 17 | case "positive": 18 | dialog.OnPositiveAction = HandleAction; 19 | break; 20 | case "negative": 21 | dialog.OnNegativeAction = HandleAction; 22 | break; 23 | case "auxiliary": 24 | dialog.OnAuxiliaryAction = HandleAction; 25 | break; 26 | default: 27 | throw new InvalidOperationException("Invalid dialog action."); 28 | } 29 | } 30 | 31 | public bool ActionPerformed { get; private set; } 32 | 33 | private Task HandleAction(Session session) 34 | { 35 | ActionPerformed = true; 36 | return Task.CompletedTask; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Forms/DialogTheme.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialForms 2 | { 3 | /// 4 | /// Represents the color theme of the displayed dialog. 5 | /// 6 | public enum DialogTheme 7 | { 8 | /// 9 | /// Inherits the scheme used by the application. 10 | /// 11 | Inherit, 12 | /// 13 | /// Light background with dark foreground color. 14 | /// 15 | Light, 16 | /// 17 | /// Dark background with light foreground color. 18 | /// 19 | Dark 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Forms/DispatcherOption.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialForms 2 | { 3 | public enum DispatcherOption 4 | { 5 | CurrentThread, 6 | CurrentApplication, 7 | Custom 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Forms/FormActionCallback.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace MaterialForms 4 | { 5 | public delegate Task FormActionCallback(Session session); 6 | } 7 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/IViewProvider.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows.Controls; 3 | 4 | namespace MaterialForms 5 | { 6 | public interface IViewProvider : INotifyPropertyChanged 7 | { 8 | UserControl View { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/MaterialFormsWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Input; 4 | using MahApps.Metro.Controls; 5 | 6 | namespace MaterialForms 7 | { 8 | /// 9 | /// Interaction logic for MainWindow.xaml 10 | /// 11 | internal partial class MaterialFormsWindow : MetroWindow 12 | { 13 | public MaterialFormsWindow(WindowSession session, int dialogId = 0) 14 | { 15 | SetValue(SessionAssist.HostingSessionProperty, session); 16 | DataContext = session.Window; 17 | InitializeComponent(); 18 | var view = session.Window.Dialog.View; 19 | ContentPresenter.Content = view; 20 | Background = view.Background; 21 | // We need to remove view background as it blocks dragmove behavior 22 | view.Background = null; 23 | DialogHost.Identifier = "DialogHost" + dialogId; 24 | } 25 | 26 | private void CloseDialogCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) 27 | { 28 | DialogResult = e.Parameter as bool?; 29 | Close(); 30 | } 31 | 32 | private void CloseDialogCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) 33 | { 34 | e.CanExecute = true; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/PasswordHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security; 4 | 5 | namespace MaterialForms 6 | { 7 | public static class PasswordHelpers 8 | { 9 | public static string ConvertToUnsecureString(SecureString securePassword) 10 | { 11 | if (securePassword == null) 12 | { 13 | return null; 14 | } 15 | 16 | var unmanagedString = IntPtr.Zero; 17 | try 18 | { 19 | unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword); 20 | return Marshal.PtrToStringUni(unmanagedString); 21 | } 22 | finally 23 | { 24 | Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); 25 | } 26 | } 27 | 28 | //public static SecureString ConvertToSecureString(string password) 29 | //{ 30 | // if (password == null) 31 | // throw new ArgumentNullException(nameof(password)); 32 | 33 | // unsafe 34 | // { 35 | // fixed (char* passwordChars = password) 36 | // { 37 | // var securePassword = new SecureString(passwordChars, password.Length); 38 | // securePassword.MakeReadOnly(); 39 | // return securePassword; 40 | // } 41 | // } 42 | //} 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/ProgressBarSmoother.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using System.Windows.Controls.Primitives; 5 | using System.Windows.Media.Animation; 6 | 7 | namespace MaterialForms 8 | { 9 | internal class ProgressBarSmoother 10 | { 11 | public static double GetSmoothValue(DependencyObject obj) 12 | { 13 | return (double)obj.GetValue(SmoothValueProperty); 14 | } 15 | 16 | public static void SetSmoothValue(DependencyObject obj, double value) 17 | { 18 | obj.SetValue(SmoothValueProperty, value); 19 | } 20 | 21 | public static readonly DependencyProperty SmoothValueProperty = DependencyProperty.RegisterAttached( 22 | "SmoothValue", 23 | typeof(double), 24 | typeof(ProgressBarSmoother), 25 | new PropertyMetadata(0d, Changing)); 26 | 27 | private static void Changing(DependencyObject d, DependencyPropertyChangedEventArgs e) 28 | { 29 | var anim = new DoubleAnimation((double)e.NewValue, new TimeSpan(0, 0, 0, 0, 500)); 30 | (d as ProgressBar)?.BeginAnimation(RangeBase.ValueProperty, anim, HandoffBehavior.Compose); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/SessionAssist.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace MaterialForms 4 | { 5 | public static class SessionAssist 6 | { 7 | public static readonly DependencyProperty HostingSessionProperty = 8 | DependencyProperty.RegisterAttached( 9 | "HostingSession", 10 | typeof(Session), 11 | typeof(SessionAssist), 12 | new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Tasks/ProgressDialogOptions.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialForms.Tasks 2 | { 3 | public class ProgressDialogOptions 4 | { 5 | public string Message { get; set; } = null; 6 | 7 | public string Title { get; set; } = null; 8 | 9 | public string Cancel { get; set; } = null; 10 | 11 | public double Progress { get; set; } = 0d; 12 | 13 | public int Maximum { get; set; } = 100; 14 | 15 | public bool IsIndeterminate { get; set; } = false; 16 | } 17 | } -------------------------------------------------------------------------------- /src/MaterialForms/Old/Validation/ValidationCallback.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialForms 2 | { 3 | public delegate string ValidationCallback(T value); 4 | } 5 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Validation/Validators.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace MaterialForms 4 | { 5 | public static class Validators 6 | { 7 | public static string IsNotEmpty(string value) 8 | { 9 | return string.IsNullOrEmpty(value) ? "Value is required." : null; 10 | } 11 | 12 | public static string RequiredFile(string value) 13 | { 14 | if (string.IsNullOrWhiteSpace(value)) 15 | { 16 | return "Value is required."; 17 | } 18 | 19 | return !File.Exists(value) ? "File does not exist." : null; 20 | } 21 | 22 | public static string OptionalFile(string value) 23 | { 24 | if (string.IsNullOrWhiteSpace(value)) 25 | { 26 | return null; 27 | } 28 | 29 | return !File.Exists(value) ? "File does not exist." : null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/ValueConverters/BoolInversionConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.ValueConverters 7 | { 8 | internal class BoolInversionConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | return !(bool)value; 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | return Binding.DoNothing; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/ValueConverters/BoolToResizeModeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.ValueConverters 7 | { 8 | internal class BoolToResizeModeConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | return value is bool && (bool)value ? ResizeMode.CanResize : ResizeMode.CanMinimize; 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | return Binding.DoNothing; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/ValueConverters/FormEmptyMarginConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.ValueConverters 7 | { 8 | internal class FormEmptyMarginConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | var form = value as MaterialForm; 13 | return form != null && form.Count != 0 14 | ? new Thickness(0d, 0d, 0d, 8d) 15 | : new Thickness(0d, 0d, 0d, 4d); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return Binding.DoNothing; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/ValueConverters/StringToIntegerConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.ValueConverters 6 | { 7 | public class StringToIntegerConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return value?.ToString(); 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | int result; 17 | if (int.TryParse(value?.ToString(), out result)) 18 | { 19 | return result; 20 | } 21 | 22 | return null; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/ValueConverters/StringToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.ValueConverters 7 | { 8 | internal class StringToVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | return string.IsNullOrEmpty(value as string) ? Visibility.Collapsed : Visibility.Visible; 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | return Binding.DoNothing; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/ValueConverters/ValueToPercentConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.ValueConverters 6 | { 7 | internal class ValueToPercentConverter : IMultiValueConverter 8 | { 9 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | var value = System.Convert.ToDouble(values[0]); 12 | var maximum = System.Convert.ToDouble(values[1]); 13 | return Math.Round(100d * value / maximum) + "%"; 14 | } 15 | 16 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 17 | { 18 | return new[] { Binding.DoNothing }; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Views/FormView.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/MaterialForms/Old/Views/FormView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Input; 4 | 5 | namespace MaterialForms.Views 6 | { 7 | /// 8 | /// Interaction logic for FormView.xaml 9 | /// 10 | public partial class FormView : UserControl 11 | { 12 | public FormView() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | 18 | private void FormView_OnLoaded(object sender, RoutedEventArgs e) 19 | { 20 | try 21 | { 22 | var form = DataContext as MaterialForm; 23 | if (form == null) 24 | { 25 | return; 26 | } 27 | 28 | if (form.FocusedSchema < 0) 29 | { 30 | return; 31 | } 32 | 33 | if (ItemsControl.ItemContainerGenerator.Items.Count > form.FocusedSchema) 34 | { 35 | var element = ItemsControl.ItemContainerGenerator.ContainerFromIndex(form.FocusedSchema) as IInputElement; 36 | if (element == null) 37 | { 38 | return; 39 | } 40 | 41 | FocusManager.SetFocusedElement(this, element); 42 | } 43 | } 44 | catch 45 | { 46 | // ignored 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/MaterialForms/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MaterialForms.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MaterialForms/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/MaterialForms/Resources/Material.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/MaterialForms/Themes/Material/Field.Progress.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 20 | 21 | 22 | 28 | 29 | -------------------------------------------------------------------------------- /src/MaterialForms/Themes/Metro/IconStyles.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 13 | 14 | -------------------------------------------------------------------------------- /src/MaterialForms/Themes/Wpf/IconStyles.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 14 | 15 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/ActionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf 4 | { 5 | public class ActionEventArgs : EventArgs 6 | { 7 | public ActionEventArgs(object model, string action, object parameter) 8 | { 9 | Model = model; 10 | Action = action; 11 | Parameter = parameter; 12 | } 13 | 14 | public object Model { get; } 15 | 16 | public string Action { get; } 17 | 18 | public object Parameter { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/CardAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using MaterialForms.Wpf.Fields; 4 | using MaterialForms.Wpf.Fields.Defaults; 5 | 6 | namespace MaterialForms.Wpf.Annotations 7 | { 8 | public sealed class CardAttribute : FormContentAttribute 9 | { 10 | public CardAttribute(int rows, [CallerLineNumber] int position = 0) 11 | : base(position) 12 | { 13 | StartsNewRow = false; 14 | RowSpan = rows; 15 | } 16 | 17 | protected override FormElement CreateElement() 18 | { 19 | return new CardElement(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/Content/BreakAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using MaterialForms.Wpf.Fields; 5 | using MaterialForms.Wpf.Fields.Defaults; 6 | using MaterialForms.Wpf.FormBuilding; 7 | 8 | namespace MaterialForms.Wpf.Annotations 9 | { 10 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)] 11 | public class BreakAttribute : FormContentAttribute 12 | { 13 | public BreakAttribute([CallerLineNumber] int position = 0) : base(position) 14 | { 15 | } 16 | 17 | /// 18 | /// Height of the break. Accepts a double or a dynamic resource. 19 | /// 20 | public object Height { get; set; } = 8d; 21 | 22 | protected override FormElement CreateElement() 23 | { 24 | return new BreakElement 25 | { 26 | Height = Utilities.GetResource(Height, 8d, Deserializers.Double) 27 | }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/Content/DividerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using MaterialForms.Wpf.Fields; 5 | using MaterialForms.Wpf.Fields.Defaults; 6 | using MaterialForms.Wpf.FormBuilding; 7 | 8 | namespace MaterialForms.Wpf.Annotations 9 | { 10 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)] 11 | public class DividerAttribute : FormContentAttribute 12 | { 13 | public DividerAttribute([CallerLineNumber] int position = 0) 14 | : this(true, position) 15 | { 16 | } 17 | 18 | public DividerAttribute(bool hasMargin, [CallerLineNumber] int position = 0) : base(position) 19 | { 20 | HasMargin = hasMargin; 21 | } 22 | 23 | public object HasMargin { get; set; } 24 | 25 | protected override FormElement CreateElement() 26 | { 27 | return new DividerElement 28 | { 29 | HasMargin = Utilities.GetResource(HasMargin, true, Deserializers.Boolean) 30 | }; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/DefaultFields.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialForms.Wpf.Annotations 2 | { 3 | /// 4 | /// Specifies which fields are displayed by default. 5 | /// 6 | public enum DefaultFields 7 | { 8 | /// 9 | /// Properties with public getters and setters are displayed by default. 10 | /// 11 | AllExcludingReadonly, 12 | /// 13 | /// All public properties are displayed by default. 14 | /// 15 | AllIncludingReadonly, 16 | /// 17 | /// No properties are displayed by default. Use to add properties. 18 | /// 19 | None 20 | } 21 | } -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/Display/PasswordAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations.Display 4 | { 5 | [AttributeUsage(AttributeTargets.Property)] 6 | public sealed class PasswordAttribute : Attribute 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/Display/ProgressAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations.Display 4 | { 5 | [AttributeUsage(AttributeTargets.Property)] 6 | public class ProgressAttribute : Attribute 7 | { 8 | /// 9 | /// Progress maximum value. Accepts a numeric value or a dynamic resource. 10 | /// 11 | public object Maximum { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/Display/SliderAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations.Display 4 | { 5 | [AttributeUsage(AttributeTargets.Property)] 6 | public class SliderAttribute : Attribute 7 | { 8 | /// 9 | /// Slider minimum value. Accepts a numeric value or a dynamic resource. 10 | /// 11 | public object Minimum { get; set; } 12 | 13 | /// 14 | /// Slider maximum value. Accepts a numeric value or a dynamic resource. 15 | /// 16 | public object Maximum { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/Display/ToggleAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations.Display 4 | { 5 | [AttributeUsage(AttributeTargets.Property)] 6 | public sealed class ToggleAttribute : Attribute 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/EnumDisplayAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations 4 | { 5 | /// 6 | /// Allows specifying enum display text. 7 | /// 8 | [AttributeUsage(AttributeTargets.Field)] 9 | public sealed class EnumDisplayAttribute : Attribute 10 | { 11 | public EnumDisplayAttribute(string name) 12 | { 13 | Name = name; 14 | } 15 | 16 | /// 17 | /// Enumeration member name. Accepts a string or a dynamic expression. 18 | /// 19 | public string Name { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/FieldIgnoreAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations 4 | { 5 | /// 6 | /// Properties marked with this attribute will never be generated. 7 | /// 8 | [AttributeUsage(AttributeTargets.Property)] 9 | public sealed class FieldIgnoreAttribute : Attribute 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/FormAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations 4 | { 5 | /// 6 | /// Allows configuring generated forms. 7 | /// 8 | [AttributeUsage(AttributeTargets.Class)] 9 | public sealed class FormAttribute : Attribute 10 | { 11 | /// 12 | /// Specifies default field generation behavior. 13 | /// 14 | public DefaultFields Mode { get; set; } 15 | 16 | /// 17 | /// Specifies grid column widths. Positive values indicate star widths, negative values indicate pixel widths. 18 | /// 19 | public double[] Grid { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/ResourceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations 4 | { 5 | /// 6 | /// Allows attaching custom resources to fields or to the model. 7 | /// These resources become available to generated controls. 8 | /// 9 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)] 10 | public sealed class ResourceAttribute : Attribute 11 | { 12 | public ResourceAttribute(string name, object value) 13 | { 14 | Name = name; 15 | Value = value; 16 | } 17 | 18 | /// 19 | /// Resource name. Accepts a string. 20 | /// 21 | public string Name { get; } 22 | 23 | /// 24 | /// Resource value. Accepts an object or a dynamic expresion. 25 | /// 26 | public object Value { get; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/SelectFromAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Annotations 4 | { 5 | /// 6 | /// Specifies that a field can have values from a collection. 7 | /// 8 | [AttributeUsage(AttributeTargets.Property)] 9 | public sealed class SelectFromAttribute : Attribute 10 | { 11 | public SelectFromAttribute(object itemsSource) 12 | { 13 | ItemsSource = itemsSource; 14 | } 15 | 16 | /// 17 | /// Selection items source. Accepts an array, an enum type, or a dynamic resource. 18 | /// 19 | public object ItemsSource { get; set; } 20 | 21 | /// 22 | /// Display member path. Accepts a string or a dynamic expression. 23 | /// 24 | public string DisplayPath { get; set; } 25 | 26 | /// 27 | /// Display value path. Accepts a string or a dynamic expression. 28 | /// 29 | public string ValuePath { get; set; } 30 | 31 | /// 32 | /// Item string format. Accepts a string or a dynamic expression. 33 | /// 34 | public string ItemStringFormat { get; set; } 35 | 36 | /// 37 | /// Field selection type. Accepts a or a dynamic resource. 38 | /// 39 | public object SelectionType { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/SelectionType.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialForms.Wpf.Annotations 2 | { 3 | /// 4 | /// Determines how a selection field should be displayed. 5 | /// 6 | public enum SelectionType 7 | { 8 | /// 9 | /// A selectable ComboBox is displayed. 10 | /// 11 | ComboBox, 12 | /// 13 | /// An editable ComboBox is displayed. 14 | /// Falls back to a non-editable ComboBox if editing is not applicable for a property type. 15 | /// 16 | ComboBoxEditable, 17 | /// 18 | /// A list of radio buttons is displayed. 19 | /// 20 | RadioButtons 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Annotations/ValidationAction.cs: -------------------------------------------------------------------------------- 1 | namespace MaterialForms.Wpf.Annotations 2 | { 3 | /// 4 | /// Specifies field validation action when an event occurs. 5 | /// 6 | public enum ValidationAction 7 | { 8 | /// 9 | /// Does nothing. 10 | /// 11 | DoNothing, 12 | /// 13 | /// Validates the field. 14 | /// 15 | ValidateField, 16 | /// 17 | /// Clears the field of validation errors. 18 | /// 19 | ClearErrors 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Controls/IDynamicForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Controls 4 | { 5 | public interface IDynamicForm 6 | { 7 | object Model { get; } 8 | 9 | object Value { get; } 10 | 11 | object Context { get; } 12 | 13 | event EventHandler OnAction; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Controls/MaterialDialog.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace MaterialForms.Wpf.Controls 4 | { 5 | public abstract class MaterialDialog : ContentControl 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/ContentElement.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using MaterialDesignThemes.Wpf; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields.Defaults 6 | { 7 | public abstract class ContentElement : FormElement 8 | { 9 | public IValueProvider Content { get; set; } 10 | 11 | public IValueProvider Icon { get; set; } 12 | 13 | public IValueProvider IconPadding { get; set; } 14 | 15 | protected internal override void Freeze() 16 | { 17 | const string iconVisibility = "IconVisibility"; 18 | 19 | base.Freeze(); 20 | Resources.Add(nameof(Content), Content ?? LiteralValue.Null); 21 | Resources.Add(nameof(IconPadding), IconPadding ?? LiteralValue.False); 22 | 23 | if (Icon != null && !(Icon is LiteralValue v && v.Value == null)) 24 | { 25 | Resources.Add(iconVisibility, Icon.Wrap("ToVisibility")); 26 | Resources.Add(nameof(Icon), Icon); 27 | } 28 | else 29 | { 30 | Resources.Add(iconVisibility, new LiteralValue(Visibility.Collapsed)); 31 | Resources.Add(nameof(Icon), new LiteralValue((PackIconKind)(-2))); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/Defaults/ActionAlignerElement.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace MaterialForms.Wpf.Fields.Defaults 3 | { 4 | public class ActionAlignerElement 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/Defaults/BreakElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields.Defaults 6 | { 7 | public class BreakElement : FormElement 8 | { 9 | public IValueProvider Height { get; set; } 10 | 11 | protected internal override void Freeze() 12 | { 13 | base.Freeze(); 14 | Resources.Add(nameof(Height), Height ?? new LiteralValue(8d)); 15 | } 16 | 17 | protected internal override IBindingProvider CreateBindingProvider(IResourceContext context, IDictionary formResources) 18 | { 19 | return new BreakPresenter(context, Resources, formResources); 20 | } 21 | } 22 | 23 | public class BreakPresenter : BindingProvider 24 | { 25 | static BreakPresenter() 26 | { 27 | DefaultStyleKeyProperty.OverrideMetadata(typeof(BreakPresenter), new FrameworkPropertyMetadata(typeof(BreakPresenter))); 28 | } 29 | 30 | public BreakPresenter(IResourceContext context, IDictionary fieldResources, IDictionary formResources) 31 | : base(context, fieldResources, formResources, true) 32 | { 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/Defaults/CardElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields.Defaults 6 | { 7 | public class CardElement : FormElement 8 | { 9 | protected internal override IBindingProvider CreateBindingProvider(IResourceContext context, IDictionary formResources) 10 | { 11 | return new CardPresenter(context, Resources, formResources); 12 | } 13 | } 14 | 15 | public class CardPresenter : BindingProvider 16 | { 17 | static CardPresenter() 18 | { 19 | DefaultStyleKeyProperty.OverrideMetadata(typeof(CardPresenter), new FrameworkPropertyMetadata(typeof(CardPresenter))); 20 | } 21 | 22 | public CardPresenter(IResourceContext context, IDictionary fieldResources, IDictionary formResources) 23 | : base(context, fieldResources, formResources, true) 24 | { 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/Defaults/DateField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Fields.Defaults 7 | { 8 | public class DateField : DataFormField 9 | { 10 | /// 11 | /// 12 | /// 13 | public DateField(string key) : base(key, typeof(DateTime)) 14 | { 15 | } 16 | 17 | protected internal override IBindingProvider CreateBindingProvider(IResourceContext context, 18 | IDictionary formResources) 19 | { 20 | var datePresenter = new DatePresenter(context, Resources, formResources); 21 | return datePresenter; 22 | } 23 | } 24 | 25 | public class DatePresenter : ValueBindingProvider 26 | { 27 | static DatePresenter() 28 | { 29 | DefaultStyleKeyProperty.OverrideMetadata(typeof(DatePresenter), 30 | new FrameworkPropertyMetadata(typeof(DatePresenter))); 31 | } 32 | 33 | public DatePresenter(IResourceContext context, 34 | IDictionary fieldResources, 35 | IDictionary formResources) 36 | : base(context, fieldResources, formResources, true) 37 | { 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/Defaults/DividerElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields.Defaults 6 | { 7 | public class DividerElement : FormElement 8 | { 9 | public IValueProvider HasMargin { get; set; } 10 | 11 | protected internal override void Freeze() 12 | { 13 | base.Freeze(); 14 | Resources.Add(nameof(HasMargin), HasMargin ?? LiteralValue.True); 15 | } 16 | 17 | protected internal override IBindingProvider CreateBindingProvider(IResourceContext context, IDictionary formResources) 18 | { 19 | return new DividerPresenter(context, Resources, formResources); 20 | } 21 | } 22 | 23 | public class DividerPresenter : BindingProvider 24 | { 25 | static DividerPresenter() 26 | { 27 | DefaultStyleKeyProperty.OverrideMetadata(typeof(DividerPresenter), new FrameworkPropertyMetadata(typeof(DividerPresenter))); 28 | } 29 | 30 | public DividerPresenter(IResourceContext context, IDictionary fieldResources, IDictionary formResources) 31 | : base(context, fieldResources, formResources, true) 32 | { 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/Defaults/HeadingElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields.Defaults 6 | { 7 | public class HeadingElement : ContentElement 8 | { 9 | protected internal override IBindingProvider CreateBindingProvider(IResourceContext context, IDictionary formResources) 10 | { 11 | return new HeadingPresenter(context, Resources, formResources); 12 | } 13 | } 14 | 15 | public class HeadingPresenter : BindingProvider 16 | { 17 | static HeadingPresenter() 18 | { 19 | DefaultStyleKeyProperty.OverrideMetadata(typeof(HeadingPresenter), new FrameworkPropertyMetadata(typeof(HeadingPresenter))); 20 | } 21 | 22 | public HeadingPresenter(IResourceContext context, IDictionary fieldResources, IDictionary formResources) 23 | : base(context, fieldResources, formResources, true) 24 | { 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/Defaults/TextElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields.Defaults 6 | { 7 | public class TextElement : ContentElement 8 | { 9 | protected internal override IBindingProvider CreateBindingProvider(IResourceContext context, IDictionary formResources) 10 | { 11 | return new TextPresenter(context, Resources, formResources); 12 | } 13 | } 14 | 15 | public class TextPresenter : BindingProvider 16 | { 17 | static TextPresenter() 18 | { 19 | DefaultStyleKeyProperty.OverrideMetadata(typeof(TextPresenter), new FrameworkPropertyMetadata(typeof(TextPresenter))); 20 | } 21 | 22 | public TextPresenter(IResourceContext context, IDictionary fieldResources, IDictionary formResources) 23 | : base(context, fieldResources, formResources, true) 24 | { 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/Defaults/TitleElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields.Defaults 6 | { 7 | public class TitleElement : ContentElement 8 | { 9 | protected internal override IBindingProvider CreateBindingProvider(IResourceContext context, IDictionary formResources) 10 | { 11 | return new TitlePresenter(context, Resources, formResources); 12 | } 13 | } 14 | 15 | public class TitlePresenter : BindingProvider 16 | { 17 | static TitlePresenter() 18 | { 19 | DefaultStyleKeyProperty.OverrideMetadata(typeof(TitlePresenter), new FrameworkPropertyMetadata(typeof(TitlePresenter))); 20 | } 21 | 22 | public TitlePresenter(IResourceContext context, IDictionary fieldResources, IDictionary formResources) 23 | : base(context, fieldResources, formResources, true) 24 | { 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/FormElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using MaterialForms.Wpf.Controls; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields 6 | { 7 | /// 8 | /// Represents a form element, which is not necessarily an input field. 9 | /// 10 | public abstract class FormElement 11 | { 12 | protected FormElement() 13 | { 14 | Resources = new Dictionary(); 15 | } 16 | 17 | protected internal Position LinePosition { get; set; } 18 | 19 | public IDictionary Resources { get; set; } 20 | 21 | /// 22 | /// Gets or sets the bool resource that determines whether this element will be visible. 23 | /// 24 | public IValueProvider IsVisible { get; set; } 25 | 26 | protected internal virtual void Freeze() 27 | { 28 | Resources.Add(nameof(IsVisible), IsVisible ?? LiteralValue.True); 29 | } 30 | 31 | protected internal abstract IBindingProvider CreateBindingProvider( 32 | IResourceContext context, 33 | IDictionary formResources); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/FormRow.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace MaterialForms.Wpf.Fields 4 | { 5 | public class FormRow 6 | { 7 | public FormRow() 8 | : this(true, 1) 9 | { 10 | } 11 | 12 | public FormRow(bool startsNewRow, int rowSpan) 13 | { 14 | StartsNewRow = startsNewRow; 15 | RowSpan = rowSpan; 16 | Elements = new List(); 17 | } 18 | 19 | public bool StartsNewRow { get; } 20 | 21 | public int RowSpan { get; } 22 | 23 | public List Elements { get; } 24 | } 25 | 26 | public class FormElementContainer 27 | { 28 | public FormElementContainer(int column, int columnSpan, FormElement element) 29 | : this(column, columnSpan, new List { element }) 30 | { 31 | } 32 | 33 | public FormElementContainer(int column, int columnSpan, List elements) 34 | { 35 | Column = column; 36 | ColumnSpan = columnSpan; 37 | Elements = elements; 38 | } 39 | 40 | public int Column { get; } 41 | 42 | public int ColumnSpan { get; } 43 | 44 | public List Elements { get; } 45 | } 46 | 47 | public enum FormElementsAlignment 48 | { 49 | Stretch, 50 | Left, 51 | Right 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/IBindingProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Data; 2 | using MaterialForms.Wpf.Resources; 3 | 4 | namespace MaterialForms.Wpf.Fields 5 | { 6 | /// 7 | /// Provides bindings by resource name. 8 | /// 9 | public interface IBindingProvider 10 | { 11 | /// 12 | /// Returns a bound to the value returned by . 13 | /// 14 | /// Resource name. This is not the object property name. 15 | /// Returns a . 16 | BindingProxy this[string name] { get; } 17 | 18 | /// 19 | /// Resolves the value for the specified resource. 20 | /// The result may be a or a literal value. 21 | /// 22 | /// Resource name. This is not the object property name. 23 | /// Returns a or a literal value. 24 | object ProvideValue(string name); 25 | 26 | /// 27 | /// Gets called when a binding expression is resolved. 28 | /// 29 | void BindingCreated(BindingExpressionBase expression, string resource); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/IDataBindingProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows.Data; 3 | 4 | namespace MaterialForms.Wpf.Fields 5 | { 6 | public interface IDataBindingProvider : IBindingProvider 7 | { 8 | IEnumerable GetBindings(); 9 | 10 | void ClearBindings(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/IFormDefinition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields 6 | { 7 | public interface IFormDefinition 8 | { 9 | IReadOnlyList FormRows { get; } 10 | 11 | double[] Grid { get; set; } 12 | 13 | Type ModelType { get; } 14 | 15 | IDictionary Resources { get; } 16 | 17 | object CreateInstance(IResourceContext context); 18 | } 19 | } -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/StringTypeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.Wpf.Fields 7 | { 8 | public class StringTypeConverter : IValueConverter 9 | { 10 | private readonly Func deserializer; 11 | 12 | public StringTypeConverter(Func deserializer) 13 | { 14 | this.deserializer = deserializer; 15 | } 16 | 17 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | return value; 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | try 25 | { 26 | return deserializer(value as string, culture); 27 | } 28 | catch 29 | { 30 | return DependencyProperty.UnsetValue; 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Fields/ValueBindingProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows.Data; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Fields 6 | { 7 | /// 8 | /// Single source data binding provider that captures resources with name "Value". 9 | /// 10 | public class ValueBindingProvider : BindingProvider, IDataBindingProvider 11 | { 12 | public ValueBindingProvider(IResourceContext context, IDictionary fieldResources, IDictionary formResources, bool throwOnNotFound) 13 | : base(context, fieldResources, formResources, throwOnNotFound) 14 | { 15 | } 16 | 17 | public override void BindingCreated(BindingExpressionBase expression, string resource) 18 | { 19 | if (resource == "Value") 20 | { 21 | CurrentBindingExpression = expression; 22 | } 23 | } 24 | 25 | public BindingExpressionBase CurrentBindingExpression { get; private set; } 26 | 27 | public IEnumerable GetBindings() 28 | { 29 | return CurrentBindingExpression != null 30 | ? new[] { CurrentBindingExpression } 31 | : new BindingExpressionBase[0]; 32 | } 33 | 34 | public void ClearBindings() 35 | { 36 | CurrentBindingExpression = null; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/CustomCulture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | 5 | namespace MaterialForms.Wpf.FormBuilding 6 | { 7 | public static class ConversionCulture 8 | { 9 | /// 10 | /// Stores custom cultures which can be used for date and number conversion. 11 | /// 12 | public static readonly Dictionary CustomCultures = new Dictionary(); 13 | 14 | public static CultureInfo Get(string name) 15 | { 16 | if (name == null) 17 | { 18 | return null; 19 | } 20 | 21 | return CustomCultures.TryGetValue(name, out var value) 22 | ? value 23 | : CultureInfo.GetCultureInfo(name); 24 | } 25 | 26 | public static void Set(string name, CultureInfo cultureInfo) 27 | { 28 | CustomCultures[name] = cultureInfo; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/Defaults/Initializers/BindingInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MaterialForms.Wpf.Annotations; 3 | using MaterialForms.Wpf.Fields; 4 | using MaterialForms.Wpf.Fields.Defaults; 5 | 6 | namespace MaterialForms.Wpf.FormBuilding.Defaults.Initializers 7 | { 8 | internal class BindingInitializer : IFieldInitializer 9 | { 10 | public void Initialize(FormElement element, IFormProperty property, Func deserializer) 11 | { 12 | if (!(element is DataFormField field)) 13 | { 14 | return; 15 | } 16 | 17 | var attr = property.GetCustomAttribute(); 18 | if (attr == null) 19 | { 20 | return; 21 | } 22 | 23 | attr.Apply(field.BindingOptions); 24 | if (attr.ConversionErrorMessage != null && element is ConvertedField convertedField) 25 | { 26 | var errorProvider = Utilities.GetErrorProvider(attr.ConversionErrorMessage, property.Name); 27 | convertedField.ConversionErrorMessage = errorProvider; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/Defaults/Properties/SliderBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MaterialForms.Wpf.Annotations.Display; 3 | using MaterialForms.Wpf.Fields; 4 | using MaterialForms.Wpf.Fields.Defaults; 5 | 6 | namespace MaterialForms.Wpf.FormBuilding.Defaults.Properties 7 | { 8 | internal class SliderBuilder : IFieldBuilder 9 | { 10 | public FormElement TryBuild(IFormProperty property, Func deserializer) 11 | { 12 | var attr = property.GetCustomAttribute(); 13 | if (attr == null) 14 | { 15 | return null; 16 | } 17 | 18 | return new SliderField(property.Name, property.PropertyType) 19 | { 20 | // Since WPF slider uses doubles, we have to guess a double stringified value. 21 | // Defaults to 0d-10d. 22 | Minimum = Utilities.GetResource(attr.Minimum, 0d, Deserializers.Double), 23 | Maximum = Utilities.GetResource(attr.Maximum, 10d, Deserializers.Double) 24 | }; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/Defaults/Types/ProgressBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MaterialForms.Wpf.Annotations.Display; 3 | using MaterialForms.Wpf.Fields; 4 | using MaterialForms.Wpf.Fields.Defaults; 5 | using MaterialForms.Wpf.Resources; 6 | 7 | namespace MaterialForms.Wpf.FormBuilding.Defaults.Types 8 | { 9 | internal class ProgressBuilder : IFieldBuilder 10 | { 11 | public FormElement TryBuild(IFormProperty property, Func deserializer) 12 | { 13 | var attribute = property.GetCustomAttribute(); 14 | return attribute != null 15 | ? new ProgressField(property.Name) 16 | { 17 | Maximum = Utilities.GetResource(attribute.Maximum, 100d, Deserializers.Double) 18 | } 19 | : null; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/Defaults/Types/TypeBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using MaterialForms.Wpf.Fields; 4 | 5 | namespace MaterialForms.Wpf.FormBuilding.Defaults.Types 6 | { 7 | public abstract class TypeBuilder : IFieldBuilder 8 | { 9 | public FormElement TryBuild(IFormProperty property, Func deserializer) 10 | { 11 | if (property.PropertyType != typeof(T)) 12 | { 13 | return null; 14 | } 15 | 16 | return Build(property, deserializer); 17 | } 18 | 19 | protected abstract FormElement Build(IFormProperty property, Func deserializer); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/DynamicProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace MaterialForms.Wpf.FormBuilding 6 | { 7 | public class DynamicProperty : IFormProperty 8 | { 9 | private readonly Attribute[] attributes; 10 | 11 | public DynamicProperty(string name, Type propertyType, Attribute[] attributes) 12 | { 13 | this.attributes = attributes; 14 | Name = name; 15 | PropertyType = propertyType; 16 | } 17 | 18 | public string Name { get; } 19 | 20 | public Type PropertyType { get; } 21 | 22 | public Type DeclaringType => null; 23 | 24 | public bool CanWrite => true; 25 | 26 | public T GetCustomAttribute() where T : Attribute 27 | { 28 | return attributes.OfType().FirstOrDefault(); 29 | } 30 | 31 | public IEnumerable GetCustomAttributes() where T : Attribute 32 | { 33 | return attributes.OfType(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/IFieldBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MaterialForms.Wpf.Fields; 3 | 4 | namespace MaterialForms.Wpf.FormBuilding 5 | { 6 | /// 7 | /// Intercepts properties and builds form elements if conditions are met. 8 | /// 9 | public interface IFieldBuilder 10 | { 11 | FormElement TryBuild(IFormProperty property, Func deserializer); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/IFieldInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MaterialForms.Wpf.Fields; 3 | 4 | namespace MaterialForms.Wpf.FormBuilding 5 | { 6 | /// 7 | /// Initializes built form fields. 8 | /// 9 | public interface IFieldInitializer 10 | { 11 | void Initialize(FormElement element, IFormProperty property, Func deserializer); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/IFormProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaterialForms.Wpf.FormBuilding 5 | { 6 | public interface IFormProperty 7 | { 8 | string Name { get; } 9 | 10 | Type PropertyType { get; } 11 | 12 | Type DeclaringType { get; } 13 | 14 | bool CanWrite { get; } 15 | 16 | T GetCustomAttribute() where T : Attribute; 17 | 18 | IEnumerable GetCustomAttributes() where T : Attribute; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/PropertyInfoWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaterialForms.Wpf.FormBuilding 9 | { 10 | internal class PropertyInfoWrapper : IFormProperty 11 | { 12 | private readonly PropertyInfo property; 13 | 14 | public PropertyInfoWrapper(PropertyInfo property) 15 | { 16 | this.property = property; 17 | } 18 | 19 | public string Name => property.Name; 20 | 21 | public Type PropertyType => property.PropertyType; 22 | 23 | public Type DeclaringType => property.DeclaringType; 24 | 25 | public bool CanWrite => property.CanWrite && property.GetSetMethod(true).IsPublic; 26 | 27 | public T GetCustomAttribute() where T : Attribute 28 | { 29 | return property.GetCustomAttribute(); 30 | } 31 | 32 | public IEnumerable GetCustomAttributes() where T : Attribute 33 | { 34 | return property.GetCustomAttributes(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/FormBuilding/ValidatorProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MaterialForms.Wpf.Resources; 3 | using MaterialForms.Wpf.Validation; 4 | 5 | namespace MaterialForms.Wpf.FormBuilding 6 | { 7 | internal class ValidatorProvider : IValidatorProvider 8 | { 9 | private readonly Func func; 10 | 11 | public ValidatorProvider(Func func) 12 | { 13 | this.func = func; 14 | } 15 | 16 | public FieldValidator GetValidator(IResourceContext context, ValidationPipe pipe) 17 | { 18 | return func(context, pipe); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Forms/ActionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Forms 4 | { 5 | public class ActionEventArgs : EventArgs 6 | { 7 | public ActionEventArgs(string action) 8 | { 9 | Action = action; 10 | } 11 | 12 | public string Action { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Forms/Alert.cs: -------------------------------------------------------------------------------- 1 | using MaterialForms.Wpf.Annotations; 2 | using MaterialForms.Wpf.Forms.Base; 3 | 4 | namespace MaterialForms.Wpf.Forms 5 | { 6 | [Form(Mode = DefaultFields.None)] 7 | 8 | [Title("{Binding Title}", IsVisible = "{Binding Title|IsNotEmpty}")] 9 | [Text("{Binding Message}", IsVisible = "{Binding Message|IsNotEmpty}")] 10 | [Action("positive", "{Binding PositiveAction}", IsVisible = "{Binding PositiveAction|IsNotEmpty}")] 11 | public sealed class Alert : DialogBase 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Forms/Base/FormBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | using MaterialForms.Annotations; 5 | 6 | namespace MaterialForms.Wpf.Forms.Base 7 | { 8 | public abstract class FormBase : IActionHandler, INotifyPropertyChanged 9 | { 10 | public event EventHandler ActionPerformed; 11 | 12 | public void HandleAction(object model, string action, object parameter) 13 | { 14 | OnAction(action, parameter); 15 | ActionPerformed?.Invoke(this, new ActionEventArgs(action)); 16 | } 17 | 18 | protected virtual void OnAction(string action, object parameter) 19 | { 20 | } 21 | 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | 24 | [NotifyPropertyChangedInvocator] 25 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 26 | { 27 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return GetType().Name; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Forms/Confirm.cs: -------------------------------------------------------------------------------- 1 | using MaterialForms.Wpf.Annotations; 2 | using MaterialForms.Wpf.Forms.Base; 3 | 4 | namespace MaterialForms.Wpf.Forms 5 | { 6 | [Form(Mode = DefaultFields.None)] 7 | 8 | [Title("{Binding Title}", IsVisible = "{Binding Title|IsNotEmpty}")] 9 | [Text("{Binding Message}", IsVisible = "{Binding Message|IsNotEmpty}")] 10 | [Action("negative", "{Binding NegativeAction}", IsVisible = "{Binding NegativeAction|IsNotEmpty}")] 11 | [Action("positive", "{Binding PositiveAction}", IsVisible = "{Binding PositiveAction|IsNotEmpty}")] 12 | public sealed class Confirm : DialogBase 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/IActionHandler.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace MaterialForms.Wpf 3 | { 4 | public interface IActionHandler 5 | { 6 | void HandleAction(object model, string action, object parameter); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/BindingOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace MaterialForms.Wpf.Resources 5 | { 6 | public class BindingOptions 7 | { 8 | public CultureInfo ConverterCulture { get; set; } = CultureInfo.InvariantCulture; 9 | 10 | public string StringFormat { get; set; } 11 | 12 | public UpdateSourceTrigger UpdateSourceTrigger { get; set; } = UpdateSourceTrigger.Default; 13 | 14 | public int Delay { get; set; } 15 | 16 | public bool ValidatesOnDataErrors { get; set; } = true; 17 | 18 | public bool ValidatesOnExceptions { get; set; } = false; 19 | 20 | public bool ValidatesOnNotifyDataErrors { get; set; } = true; 21 | 22 | internal void Apply(Binding binding) 23 | { 24 | binding.ConverterCulture = ConverterCulture; 25 | binding.StringFormat = StringFormat; 26 | binding.UpdateSourceTrigger = UpdateSourceTrigger; 27 | binding.Delay = Delay; 28 | binding.ValidatesOnDataErrors = ValidatesOnDataErrors; 29 | binding.ValidatesOnExceptions = ValidatesOnExceptions; 30 | binding.ValidatesOnNotifyDataErrors = ValidatesOnNotifyDataErrors; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/BoolProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | 4 | namespace MaterialForms.Wpf.Resources 5 | { 6 | /// 7 | /// Encapsulates a string bound to a resource. 8 | /// 9 | public class BoolProxy : Freezable, IBoolProxy, IProxy 10 | { 11 | public static readonly DependencyProperty ValueProperty = 12 | DependencyProperty.Register( 13 | nameof(Value), 14 | typeof(bool), 15 | typeof(BoolProxy), 16 | new UIPropertyMetadata(PropertyChangedCallback)); 17 | 18 | private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 19 | { 20 | ((BoolProxy)dependencyObject).ValueChanged?.Invoke(); 21 | } 22 | 23 | public bool Value 24 | { 25 | get => (bool)GetValue(ValueProperty); 26 | set => SetValue(ValueProperty, value); 27 | } 28 | 29 | object IProxy.Value => Value; 30 | 31 | public Action ValueChanged { get; set; } 32 | 33 | protected override Freezable CreateInstanceCore() 34 | { 35 | return new BoolProxy(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/CoercedValueProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Data; 2 | 3 | namespace MaterialForms.Wpf.Resources 4 | { 5 | public class CoercedValueProvider : IValueProvider 6 | { 7 | private readonly IValueProvider innerProvider; 8 | private readonly object defaultValue; 9 | 10 | public CoercedValueProvider(IValueProvider innerProvider, object defaultValue) 11 | { 12 | this.innerProvider = innerProvider; 13 | this.defaultValue = defaultValue; 14 | } 15 | 16 | public BindingBase ProvideBinding(IResourceContext context) 17 | { 18 | var binding = innerProvider.ProvideBinding(context); 19 | binding.FallbackValue = defaultValue; 20 | return binding; 21 | } 22 | 23 | public object ProvideValue(IResourceContext context) 24 | { 25 | var value = innerProvider.ProvideValue(context); 26 | if (value is BindingBase binding) 27 | { 28 | binding.FallbackValue = defaultValue; 29 | return binding; 30 | } 31 | 32 | if (value is T) 33 | { 34 | return value; 35 | } 36 | 37 | return defaultValue; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/EnumerableStringValueProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.Wpf.Resources 7 | { 8 | public class EnumerableStringValueProvider : IValueProvider 9 | { 10 | private readonly IEnumerable elements; 11 | 12 | public EnumerableStringValueProvider(IEnumerable elements) 13 | { 14 | this.elements = elements ?? throw new ArgumentNullException(nameof(elements)); 15 | } 16 | 17 | public BindingBase ProvideBinding(IResourceContext context) 18 | { 19 | return new Binding 20 | { 21 | Source = ProvideValue(context), 22 | Mode = BindingMode.OneTime 23 | }; 24 | } 25 | 26 | public object ProvideValue(IResourceContext context) 27 | { 28 | return elements.Select(e => e.GetStringValue(context, true)).ToList(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/EnumerableValueProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.Wpf.Resources 7 | { 8 | public class EnumerableKeyValueProvider : IValueProvider 9 | { 10 | private readonly IEnumerable> elements; 11 | private readonly bool addNull; 12 | 13 | public EnumerableKeyValueProvider(IEnumerable> elements, bool addNull) 14 | { 15 | this.addNull = addNull; 16 | this.elements = elements ?? throw new ArgumentNullException(nameof(elements)); 17 | } 18 | 19 | public BindingBase ProvideBinding(IResourceContext context) 20 | { 21 | return new Binding 22 | { 23 | Source = ProvideValue(context), 24 | Mode = BindingMode.OneTime 25 | }; 26 | } 27 | 28 | public object ProvideValue(IResourceContext context) 29 | { 30 | var list = elements.Select(e => 31 | { 32 | var proxy = e.Value.GetStringValue(context); 33 | proxy.Key = e.Key; 34 | return proxy; 35 | }).ToList(); 36 | 37 | if (addNull) 38 | { 39 | list.Insert(0, new StringProxy { Key = null, Value = "" }); 40 | } 41 | 42 | return list; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/IProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaterialForms.Wpf.Resources 4 | { 5 | public interface IProxy 6 | { 7 | object Value { get; } 8 | 9 | Action ValueChanged { get; set; } 10 | } 11 | 12 | public interface IStringProxy 13 | { 14 | string Value { get; } 15 | } 16 | 17 | public interface IBoolProxy 18 | { 19 | bool Value { get; } 20 | } 21 | 22 | internal class PlainObject : IProxy 23 | { 24 | public PlainObject(object value) 25 | { 26 | Value = value; 27 | } 28 | 29 | public object Value { get; } 30 | 31 | public Action ValueChanged { get; set; } 32 | } 33 | 34 | internal class PlainBool : IBoolProxy 35 | { 36 | public PlainBool(bool value) 37 | { 38 | Value = value; 39 | } 40 | 41 | public bool Value { get; } 42 | } 43 | 44 | internal class PlainString : IStringProxy 45 | { 46 | public PlainString(string value) 47 | { 48 | Value = value; 49 | } 50 | 51 | public string Value { get; } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/StaticResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Data; 3 | 4 | namespace MaterialForms.Wpf.Resources 5 | { 6 | public sealed class StaticResource : Resource 7 | { 8 | public StaticResource(string resourceKey) 9 | : this(resourceKey, null) 10 | { 11 | } 12 | 13 | public StaticResource(string resourceKey, string valueConverter) 14 | : base(valueConverter) 15 | { 16 | ResourceKey = resourceKey ?? throw new ArgumentNullException(nameof(resourceKey)); 17 | } 18 | 19 | public string ResourceKey { get; } 20 | 21 | public override bool IsDynamic => false; 22 | 23 | public override BindingBase ProvideBinding(IResourceContext context) 24 | { 25 | return new Binding 26 | { 27 | Source = context.FindResource(ResourceKey), 28 | Converter = GetValueConverter(context), 29 | Mode = BindingMode.OneTime 30 | }; 31 | } 32 | 33 | public override bool Equals(Resource other) 34 | { 35 | if (other is StaticResource resource) 36 | { 37 | return ResourceKey == resource.ResourceKey 38 | && ValueConverter == resource.ValueConverter; 39 | } 40 | 41 | return false; 42 | } 43 | 44 | public override int GetHashCode() 45 | { 46 | return ResourceKey.GetHashCode(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/AsBoolConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Wpf.Resources.ValueConverters 6 | { 7 | public class AsBoolConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return value is true; 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return Binding.DoNothing; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/BoolOrVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace MaterialForms.Wpf.Resources.ValueConverters 7 | { 8 | internal class BoolOrVisibilityConverter : IValueConverter 9 | { 10 | private readonly IValueConverter innerConverter; 11 | 12 | public BoolOrVisibilityConverter(IValueConverter innerConverter) 13 | { 14 | this.innerConverter = innerConverter; 15 | } 16 | 17 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | if (innerConverter != null) 20 | { 21 | value = innerConverter.Convert(value, targetType, parameter, culture); 22 | } 23 | 24 | switch (value) 25 | { 26 | case bool b: 27 | return b ? Visibility.Visible : Visibility.Collapsed; 28 | case Visibility v: 29 | return v; 30 | default: 31 | return Visibility.Collapsed; 32 | } 33 | } 34 | 35 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 36 | { 37 | return Binding.DoNothing; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/ConverterWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Wpf.Resources.ValueConverters 6 | { 7 | internal class ConverterWrapper : IValueConverter 8 | { 9 | private readonly IValueConverter outerConverter; 10 | 11 | private readonly IValueConverter innerConverter; 12 | 13 | public ConverterWrapper(IValueConverter outerConverter, IValueConverter innerConverter) 14 | { 15 | this.outerConverter = outerConverter; 16 | this.innerConverter = innerConverter; 17 | } 18 | 19 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | var inner = innerConverter.Convert(value, targetType, parameter, culture); 22 | return outerConverter.Convert(inner, targetType, parameter, culture); 23 | } 24 | 25 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 26 | { 27 | return Binding.DoNothing; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/IsEmptyConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Windows.Data; 6 | 7 | namespace MaterialForms.Wpf.Resources.ValueConverters 8 | { 9 | public class IsEmptyConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | switch (value) 14 | { 15 | case string s: 16 | return string.IsNullOrEmpty(s); 17 | case IEnumerable e: 18 | return !e.Any(); 19 | default: 20 | return true; 21 | } 22 | } 23 | 24 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 25 | { 26 | return Binding.DoNothing; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/IsNotEmptyConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Windows.Data; 6 | 7 | namespace MaterialForms.Wpf.Resources.ValueConverters 8 | { 9 | public class IsNotEmptyConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | switch (value) 14 | { 15 | case string s: 16 | return !string.IsNullOrEmpty(s); 17 | case IEnumerable e: 18 | return e.Any(); 19 | default: 20 | return false; 21 | } 22 | } 23 | 24 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 25 | { 26 | return Binding.DoNothing; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/IsNotNullConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Wpf.Resources.ValueConverters 6 | { 7 | public class IsNotNullConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return value != null; 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return Binding.DoNothing; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/IsNullConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Wpf.Resources.ValueConverters 6 | { 7 | public class IsNullConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return value == null; 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return Binding.DoNothing; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/NegateConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Wpf.Resources.ValueConverters 6 | { 7 | public class NegateConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return value is false; 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return Binding.DoNothing; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/ToLowerConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Wpf.Resources.ValueConverters 6 | { 7 | public class ToLowerConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return (value as string)?.ToLower(culture); 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return Binding.DoNothing; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/ToStringConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Wpf.Resources.ValueConverters 6 | { 7 | public class ToStringConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return value?.ToString(); 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return Binding.DoNothing; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/ToUpperConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace MaterialForms.Wpf.Resources.ValueConverters 6 | { 7 | public class ToUpperConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return (value as string)?.ToUpper(culture); 12 | } 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return Binding.DoNothing; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Resources/ValueConverters/VisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | using MaterialDesignThemes.Wpf; 6 | 7 | namespace MaterialForms.Wpf.Resources.ValueConverters 8 | { 9 | internal class VisibilityConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | switch (value) 14 | { 15 | case bool b: 16 | return b ? Visibility.Visible : Visibility.Collapsed; 17 | case Visibility v: 18 | return v; 19 | case PackIconKind i: 20 | return i == (PackIconKind)(-2) 21 | ? Visibility.Collapsed 22 | : Visibility.Visible; 23 | default: 24 | return value == null 25 | ? Visibility.Collapsed 26 | : Visibility.Visible; 27 | } 28 | } 29 | 30 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 31 | { 32 | return Binding.DoNothing; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/ComparisonValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Data; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Validation 6 | { 7 | public abstract class ComparisonValidator : FieldValidator 8 | { 9 | protected ComparisonValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 10 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 11 | : base(pipe, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 12 | { 13 | Argument = argument ?? throw new ArgumentNullException(nameof(argument)); 14 | } 15 | 16 | public IProxy Argument { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/ConversionValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Controls; 4 | 5 | namespace MaterialForms.Wpf.Validation 6 | { 7 | public sealed class ConversionValidator : ValidationRule 8 | { 9 | private readonly Func deserializer; 10 | private readonly IErrorStringProvider errorProvider; 11 | private readonly CultureInfo overrideCulture; 12 | 13 | public ConversionValidator(Func deserializer, IErrorStringProvider errorProvider, CultureInfo overrideCulture) 14 | : base(ValidationStep.RawProposedValue, false) 15 | { 16 | this.deserializer = deserializer; 17 | this.errorProvider = errorProvider; 18 | this.overrideCulture = overrideCulture; 19 | } 20 | 21 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 22 | { 23 | try 24 | { 25 | deserializer(value as string, overrideCulture ?? cultureInfo); 26 | return new ValidationResult(true, null); 27 | } 28 | catch 29 | { 30 | return new ValidationResult(false, errorProvider.GetErrorMessage(value)); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/EmptyValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Windows.Data; 5 | using MaterialForms.Wpf.Resources; 6 | 7 | namespace MaterialForms.Wpf.Validation 8 | { 9 | public class EmptyValidator : FieldValidator 10 | { 11 | public EmptyValidator(ValidationPipe pipe, IErrorStringProvider errorProvider, IBoolProxy isEnforced, IValueConverter valueConverter, 12 | bool strictValidation, bool validatesOnTargetUpdated) 13 | : base(pipe, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 14 | { 15 | } 16 | 17 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 18 | { 19 | switch (value) 20 | { 21 | case null: 22 | return true; 23 | case string s: 24 | return s.Length == 0; 25 | case IEnumerable e: 26 | return !e.Any(); 27 | default: 28 | return true; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/EqualsValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | internal class EqualsValidator : ComparisonValidator 9 | { 10 | public EqualsValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 11 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 12 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 13 | { 14 | } 15 | 16 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 17 | { 18 | var comparand = Argument.Value; 19 | if (value != null && comparand is IConvertible && value.GetType() != comparand.GetType()) 20 | { 21 | comparand = Convert.ChangeType(comparand, value.GetType(), CultureInfo.InvariantCulture); 22 | } 23 | 24 | return Equals(comparand, value); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/ExistsInValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Windows.Data; 5 | using MaterialForms.Wpf.Resources; 6 | 7 | namespace MaterialForms.Wpf.Validation 8 | { 9 | public class ExistsInValidator : ComparisonValidator 10 | { 11 | public ExistsInValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 12 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 13 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 14 | { 15 | } 16 | 17 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 18 | { 19 | if (Argument.Value is IEnumerable e) 20 | { 21 | return e.Contains(value); 22 | } 23 | 24 | return true; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/FalseValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Validation 6 | { 7 | public class FalseValidator : FieldValidator 8 | { 9 | public FalseValidator(ValidationPipe pipe, IErrorStringProvider errorProvider, IBoolProxy isEnforced, IValueConverter valueConverter, 10 | bool strictValidation, bool validatesOnTargetUpdated) 11 | : base(pipe, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 12 | { 13 | } 14 | 15 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 16 | { 17 | return value is false; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/GreaterThanEqualValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | public class GreaterThanEqualValidator : ComparisonValidator 9 | { 10 | public GreaterThanEqualValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 11 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 12 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 13 | { 14 | } 15 | 16 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 17 | { 18 | var comparand = Argument.Value; 19 | if (comparand == null) 20 | { 21 | return true; 22 | } 23 | 24 | if (value == null) 25 | { 26 | return false; 27 | } 28 | 29 | if (/*value != null &&*/ comparand is IConvertible && value.GetType() != comparand.GetType()) 30 | { 31 | comparand = Convert.ChangeType(comparand, value.GetType(), CultureInfo.InvariantCulture); 32 | } 33 | 34 | if (value is IComparable c) 35 | { 36 | return c.CompareTo(comparand) >= 0; 37 | } 38 | 39 | return false; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/GreaterThanValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | public class GreaterThanValidator : ComparisonValidator 9 | { 10 | public GreaterThanValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 11 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 12 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 13 | { 14 | } 15 | 16 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 17 | { 18 | var comparand = Argument.Value; 19 | if (comparand == null) 20 | { 21 | return true; 22 | } 23 | 24 | if (value == null) 25 | { 26 | return false; 27 | } 28 | 29 | if (/*value != null &&*/ comparand is IConvertible && value.GetType() != comparand.GetType()) 30 | { 31 | comparand = Convert.ChangeType(comparand, value.GetType(), CultureInfo.InvariantCulture); 32 | } 33 | 34 | if (value is IComparable c) 35 | { 36 | return c.CompareTo(comparand) > 0; 37 | } 38 | 39 | return false; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/IValidatorProvider.cs: -------------------------------------------------------------------------------- 1 | using MaterialForms.Wpf.Resources; 2 | 3 | namespace MaterialForms.Wpf.Validation 4 | { 5 | public interface IValidatorProvider 6 | { 7 | FieldValidator GetValidator(IResourceContext context, ValidationPipe pipe); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/LessThanEqualValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | public class LessThanEqualValidator : ComparisonValidator 9 | { 10 | public LessThanEqualValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 11 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 12 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 13 | { 14 | } 15 | 16 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 17 | { 18 | var comparand = Argument.Value; 19 | if (comparand == null) 20 | { 21 | return true; 22 | } 23 | 24 | if (value == null) 25 | { 26 | return false; 27 | } 28 | 29 | if (/*value != null &&*/ comparand is IConvertible && value.GetType() != comparand.GetType()) 30 | { 31 | comparand = Convert.ChangeType(comparand, value.GetType(), CultureInfo.InvariantCulture); 32 | } 33 | 34 | if (value is IComparable c) 35 | { 36 | return c.CompareTo(comparand) <= 0; 37 | } 38 | 39 | return false; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/LessThanValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | public class LessThanValidator : ComparisonValidator 9 | { 10 | public LessThanValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 11 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 12 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 13 | { 14 | } 15 | 16 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 17 | { 18 | var comparand = Argument.Value; 19 | if (comparand == null) 20 | { 21 | return true; 22 | } 23 | 24 | if (value == null) 25 | { 26 | return false; 27 | } 28 | 29 | if (/*value != null &&*/ comparand is IConvertible && value.GetType() != comparand.GetType()) 30 | { 31 | comparand = Convert.ChangeType(comparand, value.GetType(), CultureInfo.InvariantCulture); 32 | } 33 | 34 | if (value is IComparable c) 35 | { 36 | return c.CompareTo(comparand) < 0; 37 | } 38 | 39 | return false; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/MatchPatternValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Text.RegularExpressions; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | public class MatchPatternValidator : ComparisonValidator 9 | { 10 | public MatchPatternValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 11 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 12 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 13 | { 14 | } 15 | 16 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 17 | { 18 | if (!(Argument.Value is string pattern)) 19 | { 20 | return true; 21 | } 22 | 23 | if (value is string s) 24 | { 25 | return Regex.IsMatch(s, pattern); 26 | } 27 | 28 | return false; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/MethodInvocationValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | public class MethodInvocationValidator : FieldValidator 9 | { 10 | private readonly Func method; 11 | 12 | public MethodInvocationValidator(ValidationPipe pipe, Func method, IErrorStringProvider errorProvider, 13 | IBoolProxy isEnforced, IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 14 | : base(pipe, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 15 | { 16 | this.method = method; 17 | } 18 | 19 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 20 | { 21 | return method(value, cultureInfo, StrictValidation); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/NotEmptyValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Windows.Data; 5 | using MaterialForms.Wpf.Resources; 6 | 7 | namespace MaterialForms.Wpf.Validation 8 | { 9 | public class NotEmptyValidator : FieldValidator 10 | { 11 | public NotEmptyValidator(ValidationPipe pipe, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 12 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 13 | : base(pipe, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 14 | { 15 | } 16 | 17 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 18 | { 19 | switch (value) 20 | { 21 | case null: 22 | return false; 23 | case string s: 24 | return s.Length != 0; 25 | case IEnumerable e: 26 | return e.Any(); 27 | default: 28 | return true; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/NotEqualsValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | public class NotEqualsValidator : ComparisonValidator 9 | { 10 | public NotEqualsValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 11 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 12 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 13 | { 14 | } 15 | 16 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 17 | { 18 | var comparand = Argument.Value; 19 | if (value != null && comparand is IConvertible && value.GetType() != comparand.GetType()) 20 | { 21 | comparand = Convert.ChangeType(comparand, value.GetType(), CultureInfo.InvariantCulture); 22 | } 23 | 24 | return !Equals(comparand, value); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/NotExistsInValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Windows.Data; 5 | using MaterialForms.Wpf.Resources; 6 | 7 | namespace MaterialForms.Wpf.Validation 8 | { 9 | public class NotExistsInValidator : ComparisonValidator 10 | { 11 | public NotExistsInValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 12 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 13 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 14 | { 15 | } 16 | 17 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 18 | { 19 | if (Argument.Value is IEnumerable e) 20 | { 21 | return !e.Contains(value); 22 | } 23 | 24 | return true; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/NotMatchPatternValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Text.RegularExpressions; 3 | using System.Windows.Data; 4 | using MaterialForms.Wpf.Resources; 5 | 6 | namespace MaterialForms.Wpf.Validation 7 | { 8 | public class NotMatchPatternValidator : ComparisonValidator 9 | { 10 | public NotMatchPatternValidator(ValidationPipe pipe, IProxy argument, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 11 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 12 | : base(pipe, argument, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 13 | { 14 | } 15 | 16 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 17 | { 18 | if (!(Argument.Value is string pattern)) 19 | { 20 | return true; 21 | } 22 | 23 | if (value is string s) 24 | { 25 | return !Regex.IsMatch(s, pattern); 26 | } 27 | 28 | return true; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/NotNullValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Validation 6 | { 7 | public class NotNullValidator : FieldValidator 8 | { 9 | public NotNullValidator(ValidationPipe pipe, IErrorStringProvider errorProvider, IBoolProxy isEnforced, 10 | IValueConverter valueConverter, bool strictValidation, bool validatesOnTargetUpdated) 11 | : base(pipe, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 12 | { 13 | } 14 | 15 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 16 | { 17 | return value != null; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/NullValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Validation 6 | { 7 | public class NullValidator : FieldValidator 8 | { 9 | public NullValidator(ValidationPipe pipe, IErrorStringProvider errorProvider, IBoolProxy isEnforced, IValueConverter valueConverter, 10 | bool strictValidation, bool validatesOnTargetUpdated) 11 | : base(pipe, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 12 | { 13 | } 14 | 15 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 16 | { 17 | return value == null; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/TrueValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | using MaterialForms.Wpf.Resources; 4 | 5 | namespace MaterialForms.Wpf.Validation 6 | { 7 | public class TrueValidator : FieldValidator 8 | { 9 | public TrueValidator(ValidationPipe pipe, IErrorStringProvider errorProvider, IBoolProxy isEnforced, IValueConverter valueConverter, 10 | bool strictValidation, bool validatesOnTargetUpdated) 11 | : base(pipe, errorProvider, isEnforced, valueConverter, strictValidation, validatesOnTargetUpdated) 12 | { 13 | } 14 | 15 | protected override bool ValidateValue(object value, CultureInfo cultureInfo) 16 | { 17 | return value is true; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MaterialForms/Wpf/Validation/ValidationPipe.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Controls; 3 | 4 | namespace MaterialForms.Wpf.Validation 5 | { 6 | public sealed class ValidationPipe : ValidationRule 7 | { 8 | public ValidationPipe() 9 | : base(ValidationStep.CommittedValue, true) 10 | { 11 | } 12 | 13 | public string Error { get; set; } 14 | 15 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 16 | { 17 | var error = Error; 18 | if (error != null) 19 | { 20 | Error = null; 21 | return new ValidationResult(false, error); 22 | } 23 | 24 | return ValidationResult.ValidResult; ; 25 | } 26 | } 27 | } 28 | --------------------------------------------------------------------------------