diff --git a/README.md b/README.md index 9c1f6c7e..30ae34fe 100644 --- a/README.md +++ b/README.md @@ -14,19 +14,16 @@ This is a base libraries for building WPF application with the MVVM design patte - [Playground and Viewer for a Given Control or Functionality](#playground-and-viewer-for-a-given-control-or-functionality) - [Initial glimpse at the demonstration application](#initial-glimpse-at-the-demonstration-application) - [How to get started with atc-wpf](#how-to-get-started-with-atc-wpf) - - [MVVM](#mvvm) - - [Translation](#translation) - - [Media - ShaderEffects](#media---shadereffects) - - [ValueConverters in Atc.Wpf](#valueconverters-in-atcwpf) - - [ValueConverters - Bool to X](#valueconverters---bool-to-x) - - [ValueConverters - String to X](#valueconverters---string-to-x) - - [ValueConverters - ICollection to X](#valueconverters---icollection-to-x) - - [ValueConverters - Object to X](#valueconverters---object-to-x) - - [ValueConverters - Markup to X](#valueconverters---markup-to-x) - - [ValueConverters - Others to X](#valueconverters---others-to-x) - - [ValueConverters - Math](#valueconverters---math) - - [ValueConverters in Atc.Wpf.FontIcons](#valueconverters-in-atcwpffonticons) - - [ValueConverters in Atc.Wpf.Theming](#valueconverters-in-atcwpftheming) + - [Readme's for each NuGet Package area](#readmes-for-each-nuget-package-area) + - [Atc.Wpf](#atcwpf) + - [Controls](#controls) + - [Misc](#misc) + - [Atc.Wpf.Controls](#atcwpfcontrols) + - [Controls](#controls-1) + - [Misc](#misc-1) + - [Atc.Wpf.FontIcons](#atcwpffonticons) + - [Misc](#misc-2) + - [Atc.Wpf.Theming](#atcwpftheming) - [How to contribute](#how-to-contribute) ## Requirements @@ -56,6 +53,7 @@ The following example is taken from the ReplayCommandAsync which illustrates its - The `XAML` tab displays the corresponding XAML markup. - The `CodeBehind` tab reveals the underlying code-behind. - The `ViewModel` tab displays the associated ViewModel, if used. +- The `Readme` tab displays the associated [control]_Readme.md, if exist. | | | |-------------------------------------------------------------------------|-----------------------------------------------------------------------| @@ -106,159 +104,51 @@ Then update `App.xaml` like this: Now it is possible to use controls with theming and default WPF controls like TextBox, Button etc. with theme style. -## MVVM +## Readme's for each NuGet Package area -The Windows Presentation Framework (WPF) takes full advantage of the Model-View-ViewModel (MVVM) pattern. +***Note: Right now, it is a limit amount of controls and components there is documented with a `Readme.md` file. +Therefore run the `Atc.Wpf.Sample` application to explore all the controls and components.*** :-) -Therefore `Atc.Wpf` provide a good starting point for using MVVM. +### Atc.Wpf -| Tools set in the package | Description | -|--------------------------| | -| ViewModelBase | A base class for a the ViewModels | -| MainWindowViewModelBase | A base class for a the MainWindow-ViewModel | -| ViewModelDialogBase | A base class for a the Dialog-ViewModel | -| ObservableObject | A base class for a observable class that implement a PropertyChangedEventHandler | -| RelayCommand | Command with `CanExecute` | -| RelayCommand{T} | Command with `CanExecute` | -| RelayCommandAsync | Command with `CanExecute` as async | -| RelayCommandAsync{T} | Command with `CanExecute` as async | +#### Controls -## Translation +- [GridEx](src/Atc.Wpf/Controls/Layouts/GridEx_Readme.md) +- [StaggeredPanel](src/Atc.Wpf/Controls/Layouts/StaggeredPanel_Readme.md) +- [UniformSpacingPanel](src/Atc.Wpf/Controls/Layouts/UniformSpacingPanel_Readme.md) +- [SvgImage](src/Atc.Wpf/Controls/Media/SvgImage_Readme.md) +- Control Helpers + - [PanelHelper](src/Atc.Wpf/Helpers/PanelHelper_Readme.md) +- [SampleViewer](src/Atc.Wpf/SampleControls/SampleViewerView_Readme.md) -It is very easy to localize an application by binding text to a resource assembly that contains the text. -This is a standard .NET Globalization and localization way, -but just with a xaml-markup extension to lookup the value by key. +#### Misc -```xml - - +- [MVVM framework](src/Atc.Wpf/Mvvm/@Readme.md) + - [RelayCommand's](src/Atc.Wpf/Command/@Readme.md) +- [ShaderEffects](src/Atc.Wpf/Media/ShaderEffects/@Readme.md) + - [How to use HLSL Shader Compiler](src/Atc.Wpf/Media/ShaderEffects/Shaders/@Readme.md) +- [Tranlation & localizaion](src/Atc.Wpf/Translation/@Readme.md) +- [ValueConverters](src/Atc.Wpf/ValueConverters/@Readme.md) - - +### Atc.Wpf.Controls - - -``` +#### Controls + +- [WellKnownColorPicker](src/Atc.Wpf.Controls/ColorControls/WellKnownColorPicker_Readme.md) + +#### Misc + +- [ValueConverters](src/Atc.Wpf.Controls/ValueConverters/@Readme.md) + +### Atc.Wpf.FontIcons + +#### Misc + +- [ValueConverters](src/Atc.Wpf.FontIcons/ValueConverters/@Readme.md) + +### Atc.Wpf.Theming -## Media - ShaderEffects - -| Type | Parameters and range values | -| ----------------------------- | --------------------------------------------------------------------------- | -| ContrastAdjustShaderEffect | Brightness (-1.0 to 1.0 default 0.0) and Contrast (-1.0 to 1.0 default 0.0) | -| DesaturateShaderEffect | Strength (0.0 to 1.0 default 0.0) | -| FadeShaderEffect | Strength (0.0 to 1.0 default 0.0) and Color (color) | -| InvertColorsShaderEffect | None | -| MonochromeShaderEffect | Color (color) | -| SaturateShaderEffect | Progress | - -## ValueConverters in Atc.Wpf - -### ValueConverters - Bool to X - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| Bool -> Bool | BoolToInverseBoolValueConverter | True -> False and False -> True | False -> True and False -> False | -| Bool -> Visibility | BoolToVisibilityCollapsedValueConverter | True -> Collapsed and False -> Visible | Collapsed -> True and Visible -> False | -| Bool -> Visibility | BoolToVisibilityVisibleValueConverter | True -> Visible and False -> Collapsed | Visible -> True and Collapsed -> False | -| Bool -> With | BoolToWidthValueConverter | true, 10 -> 10 and true, "Auto" -> * | Not supported | -| Bool[] -> Bool | MultiBoolToBoolValueConverter | All-True -> True | Not supported | -| Bool[] -> Visibility | MultiBoolToVisibilityVisibleValueConverter | All-True -> Visible | Not supported | - -### ValueConverters - String to X - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| String -> Brush | ColorNameToBrushValueConverter | "Green" -> Brushs.Green | Brushs.Green -> "Green" | -| String -> Color | ColorNameToColorValueConverter | "Green" -> Colors.Green | Colors.Green -> "Green" | -| String -> "NumericFormat" | StandardNumericFormatTypeToFormatStringValueConverter | StandardNumericFormatType -> String | Not supported | -| String -> Bool | StringNullOrEmptyToBoolValueConverter | NULL or empty -> True | Not supported | -| String -> Bool | StringNullOrEmptyToInverseBoolValueConverter | NULL or empty -> False | Not supported | -| String -> Visibility | StringNullOrEmptyToVisibilityCollapsedValueConverter | NULL or empty -> Collapsed | Not supported | -| String -> Visibility | StringNullOrEmptyToVisibilityVisibleValueConverter | NULL or empty -> Visible | Not supported | -| String -> String | ToLowerValueConverter | String -> String | Binding.DoNothing | -| String -> String | ToUpperValueConverter | String -> String | Binding.DoNothing | - -### ValueConverters - ICollection to X - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| ICollection -> Bool | CollectionNullOrEmptyToBoolValueConverter | NULL or empty -> True | Not supported | -| ICollection -> Bool | CollectionNullOrEmptyToInverseBoolValueConverter | NULL or empty -> False | Not supported | -| ICollection -> Visibility | CollectionNullOrEmptyToVisibilityCollapsedValueConverter | NULL or empty -> Collapsed | Not supported | -| ICollection -> Visibility | CollectionNullOrEmptyToVisibilityVisibleValueConverter | NULL or empty -> Visible | Not supported | - -### ValueConverters - Object to X - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| Object -> Bool | IsNotNullValueConverter | <>Null -> True and Null -> False | Not supported | -| Object -> Bool | IsNullValueConverter | Null -> True and <>Null -> False | Not supported | -| Null -> X | NullCheckValueConverter | NULL -> Parameter if set | Not supported | -| Null -> UnsetValue | NullToUnsetValueConverter | NULL -> DependencyProperty.UnsetValue | Object -> DependencyProperty.UnsetValue | -| Object -> Bool | ObjectNotNullToBoolValueConverter | NotNULL -> True | Not supported | -| Object -> Visibility | ObjectNotNullToVisibilityVisibleValueConverter | NotNULL -> Visible | Not supported | -| Object -> Visibility | ObjectNullToVisibilityCollapsedValueConverter | NULL -> Collapsed | Not supported | -| Object[] -> Visibility | MultiObjectNullToVisibilityCollapsedValueConverter | All-NULL -> Collapsed | Not supported | -| Object -> Bool | ObjectNullToBoolValueConverter | NULL => True | Not supported | - - -### ValueConverters - Markup to X - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| Base converter | MarkupMultiValueConverterBase | Base converter - no examples | Base converter - no examples | -| | MarkupValueConverter | | | -| | MarkupValueConverterBase | | | - -### ValueConverters - Others to X - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| | BackgroundToForegroundValueConverter | | | -| Brush -> Color | BrushToColorValueConverter | Brushs.Green -> Colors.Green | Colors.Green -> Brushs.Green | -| Color -> Brush | ColorToBrushValueConverter | Colors.Green -> Brushs.Green | Brushs.Green -> Colors.Green | -| Color -> SolidColor | ColorToSolidColorValueConverter | Colors.Green -> Colors.Green | Not supported | -| Color -> String | ColorHexToColorValueConverter | "#FF00FF00" -> "Green" | "Green" -> "#FF00FF00" | -| Hex-Color -> Color-Key | HexColorToColorKeyValueConverter | "#FF00FF00" -> "Green" | "Green" -> Brushs.Green | -| Enum -> String | EnumDescriptionToStringValueConverter | DayOfWeek.Monday -> Monday | Not supported | -| Int -> Visibility | IntegerGreaterThenZeroToVisibilityVisibleValueConverter | 0 -> Collapsed and 1 -> Visible | Not supported | -| Int -> TimeSpan | IntegerToTimeSpanValueConverter | 100 -> TimeSpan.FromMilliseconds(100) | Not supported | -| LogCategoryType -> Brush | LogCategoryTypeToBrushValueConverter | Information -> DodgerBlue | Not supported | -| LogCategoryType -> Color | LogCategoryTypeToColorValueConverter | Information -> DodgerBlue | Not supported | -| LogLevel -> Brush | LogLevelToBrushValueConverter | Information -> DodgerBlue | Not supported | -| LogLevel -> Color | LogLevelToColorValueConverter | Information -> DodgerBlue | Not supported | -| | ObservableDictionaryToDictionaryOfStringsValueConverter | | | -| | ThicknessBindingValueConverter | | DependencyProperty.UnsetValue | -| | ThicknessFilterValueConverter | | DependencyProperty.UnsetValue | -| | ThicknessToDoubleValueConverter | | DependencyProperty.UnsetValue | -| Errors -> String | ValidationErrorsToStringValueConverter | | Not supported | -| | WindowResizeModeMinMaxButtonVisibilityMultiValueConverter| | | - -### ValueConverters - Math - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| | MathAddValueConverter | | | -| | MathDivideValueConverter | | | -| | MathMultiplyValueConverter | | | -| | MathSubtractValueConverter | | | -| | MathValueConverter | | | - -## ValueConverters in Atc.Wpf.FontIcons - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| FontIcon -> DrawingImage | FontIconDrawingImageValueConverter | | | -| FontIcon -> ImageSource | FontIconImageSourceValueConverter | | | - -## ValueConverters in Atc.Wpf.Theming - -| Category | Type | Convert Examples | ConvertBack Examples | -| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | -| | ColorToNameValueConverter | | Not supported | -| | CornerRadiusBindingValueConverter | | DependencyProperty.UnsetValue | -| | CornerRadiusFilterValueConverter | | DependencyProperty.UnsetValue | -| | TreeViewMarginValueConverter | | DependencyProperty.UnsetValue | +- [ValueConverters](src/Atc.Wpf.Theming/ValueConverters/@Readme.md) ## How to contribute diff --git a/sample/Atc.Wpf.Sample/App.xaml b/sample/Atc.Wpf.Sample/App.xaml index c95ce57a..792b2f0d 100644 --- a/sample/Atc.Wpf.Sample/App.xaml +++ b/sample/Atc.Wpf.Sample/App.xaml @@ -14,11 +14,22 @@ + + + + + + + + + - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + - - - - - - + + + + + + + + + + + - - - - - - + + + + + + + + + + + - - - - - - + + + + + + + + + + + - + + + + diff --git a/sample/Atc.Wpf.Sample/SamplesWpf/Controls/Layouts/UniformSpacingPanelView.xaml b/sample/Atc.Wpf.Sample/SamplesWpf/Controls/Layouts/UniformSpacingPanelView.xaml index b35053c8..5ee58f51 100644 --- a/sample/Atc.Wpf.Sample/SamplesWpf/Controls/Layouts/UniformSpacingPanelView.xaml +++ b/sample/Atc.Wpf.Sample/SamplesWpf/Controls/Layouts/UniformSpacingPanelView.xaml @@ -9,128 +9,176 @@ d:DesignWidth="800" mc:Ignorable="d"> + + + + + + + + + + + + + - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + - + diff --git a/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView.xaml b/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView.xaml new file mode 100644 index 00000000..bb902564 --- /dev/null +++ b/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView.xaml.cs b/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView.xaml.cs new file mode 100644 index 00000000..98bba4b6 --- /dev/null +++ b/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView.xaml.cs @@ -0,0 +1,12 @@ +namespace Atc.Wpf.Sample.SamplesWpf.Markup; + +/// +/// Interaction logic for MarkupStyleView. +/// +public partial class MarkupStyleView +{ + public MarkupStyleView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView_Readme.md b/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView_Readme.md new file mode 100644 index 00000000..6f4e0318 --- /dev/null +++ b/sample/Atc.Wpf.Sample/SamplesWpf/Markup/MarkupStyleView_Readme.md @@ -0,0 +1,150 @@ +# Header 1 + +## Header 2 + +### Header 3 + +#### Header 4 + +#### Text styles + +*italicized text* + +**bold text** + +***bold italicized text*** + +~~strikethrough text~~ + +__underline text__ + +%{color:red}color text% + +%{color:blue}***~~__color bold italicized text__~~***% + +> blockquote text line + +`code text` + +#### Blockquote multi lines + +> blockquote text line 1 +> blockquote text line 2 +> +> blockquote text line 3 +> * blockquote text line 4 +> * blockquote text line 5 + +#### Horizontal single line + +--- + +#### Horizontal double line + +=== + +#### Horizontal bold line + +*** + +#### Horizontal bold with single +___ + +#### Link + +[title](https://www.example.com) + +#### Image + +![alt text](../../Assets/error.png) + +#### Unordered list - ul + +* First item +* Second item +* Third item + +- First item +- Second item +- Third item + +#### Ordered list - ol + +1. First item +2. Second item +3. Third item + +#### Table + +| Header | Description | +| ----------- | ----------- | +| Row 1 | Row 1.... | +| Row 2 | Row 2.... | +| Row 3 | Row 3.... | + +#### Fenced Code Block - default + +``` +{ + "firstName": "John", + "lastName": "Smith", + "age": 25 +} +``` + +#### Fenced Code Block - json + +```json +{ + "firstName": "John", + "lastName": "Smith", + "age": 25 +} +``` + +#### Fenced Code Block - xml + +```xml + + John + Smith + 25 + +``` + +#### Fenced Code Block - c# + +```c# +/// +/// Interaction logic for MarkupStyleView. +/// +public partial class MarkupStyleView +{ + public MarkupStyleView() + { + InitializeComponent(); + } +} +``` + +#### Fenced Code Block - c + +```c +#include +int main() +{ + // printf() displays the string inside quotation + printf("Hello, World!"); + return 0; +} +``` + +#### Task List + +- [x] Write the press release +- [ ] Update the website +- [ ] Contact the media + +### Emoji + +That is so funny! :joy: \ No newline at end of file diff --git a/sample/Atc.Wpf.Sample/SamplesWpf/SampleControls/SampleViewerView.xaml b/sample/Atc.Wpf.Sample/SamplesWpf/SampleControls/SampleViewerView.xaml new file mode 100644 index 00000000..3f76c44e --- /dev/null +++ b/sample/Atc.Wpf.Sample/SamplesWpf/SampleControls/SampleViewerView.xaml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/sample/Atc.Wpf.Sample/SamplesWpf/SampleControls/SampleViewerView.xaml.cs b/sample/Atc.Wpf.Sample/SamplesWpf/SampleControls/SampleViewerView.xaml.cs new file mode 100644 index 00000000..631d5145 --- /dev/null +++ b/sample/Atc.Wpf.Sample/SamplesWpf/SampleControls/SampleViewerView.xaml.cs @@ -0,0 +1,12 @@ +namespace Atc.Wpf.Sample.SamplesWpf.SampleControls; + +/// +/// Interaction logic for SampleViewerView. +/// +public partial class SampleViewerView +{ + public SampleViewerView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/sample/Atc.Wpf.Sample/SamplesWpfControlsTreeView.xaml b/sample/Atc.Wpf.Sample/SamplesWpfControlsTreeView.xaml index 4559fe6e..7a2cfb2c 100644 --- a/sample/Atc.Wpf.Sample/SamplesWpfControlsTreeView.xaml +++ b/sample/Atc.Wpf.Sample/SamplesWpfControlsTreeView.xaml @@ -9,13 +9,13 @@ d:DesignWidth="230" mc:Ignorable="d"> - + - + - + - - + + - + - + - + - + - + - + diff --git a/sample/Atc.Wpf.Sample/SamplesWpfThemingTreeView.xaml b/sample/Atc.Wpf.Sample/SamplesWpfThemingTreeView.xaml index e4f7558b..78c777c0 100644 --- a/sample/Atc.Wpf.Sample/SamplesWpfThemingTreeView.xaml +++ b/sample/Atc.Wpf.Sample/SamplesWpfThemingTreeView.xaml @@ -9,7 +9,7 @@ d:DesignWidth="230" mc:Ignorable="d"> - + - + - + - + - + - + - + - + - + @@ -28,21 +28,26 @@ - + - - + + - - + + + + + + + @@ -52,15 +57,15 @@ - - + + - + - + diff --git a/schemas/README.md b/schemas/README.md index d3b8203e..ab8a4f4d 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -1,3 +1,3 @@ # ATC.WPF - Schemas -XmlnsDefinition will be added in the near feature... \ No newline at end of file +XmlnsDefinition will be added in the near feature... diff --git a/schemas/translations/README.md b/schemas/translations/README.md new file mode 100644 index 00000000..44ebf8ba --- /dev/null +++ b/schemas/translations/README.md @@ -0,0 +1,3 @@ +# ATC.WPF - Schemas for Translation and localization + +XmlnsDefinition will be added in the near feature... diff --git a/schemas/value-converters/README.md b/schemas/value-converters/README.md index f66b084a..9b022219 100644 --- a/schemas/value-converters/README.md +++ b/schemas/value-converters/README.md @@ -1,3 +1,3 @@ # ATC.WPF - Schemas for ValueConverters -XmlnsDefinition will be added in the near feature... \ No newline at end of file +XmlnsDefinition will be added in the near feature... diff --git a/docs/ColorCodes.md b/src/Atc.Wpf.Controls/ColorControls/WellKnownColorPicker_Readme.md similarity index 81% rename from docs/ColorCodes.md rename to src/Atc.Wpf.Controls/ColorControls/WellKnownColorPicker_Readme.md index 05968e53..3c24d5a5 100644 --- a/docs/ColorCodes.md +++ b/src/Atc.Wpf.Controls/ColorControls/WellKnownColorPicker_Readme.md @@ -1,4 +1,41 @@ -# Color Codes +# WellKnownColorPicker + +The `WellKnownColorPicker` control can render a list of color defined as `well known` by a alias name. + +## Example for WellKnownColorPicker usages + +```xml + +``` + +## Properties + +| Property | Type | Description | +|---------------------|-------------|----------------------------------| +| ShowOnlyBasicColors | bool | If `true`, limit to basic color | + +## Basic Color Codes + +| Color-Key | Hex code | +|-|-| +| White | 0xFFFFFFFF | +| Silver | 0xFFC0C0C0 | +| Gray | 0xFF808080 | +| Black | 0xFF000000 | +| Red | 0xFFFF0000 | +| Maroon | 0xFF800000 | +| Yellow | 0xFFFFFF00 | +| Olive | 0xFF808000 | +| Lime | 0xFF00FF00 | +| Green | 0xFF008000 | +| Aqua | 0xFF00FFFF | +| Teal | 0xFF008080 | +| Blue | 0xFF0000FF | +| Navy | 0xFF000080 | +| Fuchsia | 0xFFFF00FF | +| Purple | 0xFF800080 | + +## Color Codes | Color-Key | Hex code | |-|-| diff --git a/src/Atc.Wpf.Controls/ValueConverters/@Readme.md b/src/Atc.Wpf.Controls/ValueConverters/@Readme.md new file mode 100644 index 00000000..30ed9198 --- /dev/null +++ b/src/Atc.Wpf.Controls/ValueConverters/@Readme.md @@ -0,0 +1,10 @@ +# ValueConverters in Atc.Wpf.Controls + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| | ComplexPropertyMethodToValueConverter | | | +| | JArrayLengthValueConverter | | | +| | JPropertyTypeToColorValueConverter | | | +| | JValueConverter | | | +| | JValueTypeToColorValueConverter | | | +| | MethodToValueConverter | | | diff --git a/src/Atc.Wpf.FontIcons/ValueConverters/@Readme.md b/src/Atc.Wpf.FontIcons/ValueConverters/@Readme.md new file mode 100644 index 00000000..19c958a1 --- /dev/null +++ b/src/Atc.Wpf.FontIcons/ValueConverters/@Readme.md @@ -0,0 +1,6 @@ +# ValueConverters in Atc.Wpf.FontIcons + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| FontIcon -> DrawingImage | FontIconDrawingImageValueConverter | | | +| FontIcon -> ImageSource | FontIconImageSourceValueConverter | | | diff --git a/src/Atc.Wpf.Theming/Styles/BaseControls/TabControl.xaml b/src/Atc.Wpf.Theming/Styles/BaseControls/TabControl.xaml index 3b47a2c6..d172e3d1 100644 --- a/src/Atc.Wpf.Theming/Styles/BaseControls/TabControl.xaml +++ b/src/Atc.Wpf.Theming/Styles/BaseControls/TabControl.xaml @@ -179,6 +179,10 @@ + + + + diff --git a/src/Atc.Wpf.Theming/ValueConverters/@Readme.md b/src/Atc.Wpf.Theming/ValueConverters/@Readme.md new file mode 100644 index 00000000..fc636fee --- /dev/null +++ b/src/Atc.Wpf.Theming/ValueConverters/@Readme.md @@ -0,0 +1,8 @@ +# ValueConverters in Atc.Wpf.Theming + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| | ColorToNameValueConverter | | Not supported | +| | CornerRadiusBindingValueConverter | | DependencyProperty.UnsetValue | +| | CornerRadiusFilterValueConverter | | DependencyProperty.UnsetValue | +| | TreeViewMarginValueConverter | | DependencyProperty.UnsetValue | diff --git a/src/Atc.Wpf/Atc.Wpf.csproj b/src/Atc.Wpf/Atc.Wpf.csproj index 7d52498f..47a59bfb 100644 --- a/src/Atc.Wpf/Atc.Wpf.csproj +++ b/src/Atc.Wpf/Atc.Wpf.csproj @@ -1008,6 +1008,7 @@ + diff --git a/src/Atc.Wpf/Command/@Readme.md b/src/Atc.Wpf/Command/@Readme.md new file mode 100644 index 00000000..8498ce00 --- /dev/null +++ b/src/Atc.Wpf/Command/@Readme.md @@ -0,0 +1,108 @@ +# RelayCommand's Component + +The Atc `RelayCommand's` is a powerful tool designed for the Model-View-ViewModel (MVVM) pattern in .NET applications, +especially within the context of WPF or similar XAML-based technologies. + +MVVM facilitates a clean separation of concerns between the application's user interface and its business logic. +One of the key features of MVVM is the ability to bind commands, +rather than events, to user actions like button clicks. +This approach offers several advantages: + +- **Decoupling of View and ViewModel:** + Commands allow for a decoupling of the UI elements from their actions, making your code more modular and testable. +- **Enablement Logic:** + Easily control the enablement of UI elements based on the command's ability to execute. +- **Asynchronous Support:** + Execute long-running operations without blocking the UI, enhancing application responsiveness. + +## Why Use RelayCommand's Over Events? + +`RelayCommand's` provides a more robust, testable, and maintainable way of handling user interactions +compared to traditional event handlers. + +By leveraging asynchronous operations, +`RelayCommand's` ensures that your application remains responsive, even during intensive tasks. +This is especially crucial in modern applications where user experience is paramount. + +The variants of `RelayCommand's`: + +| Interface | Concrete Implementation | Description | +|--------------------------|-------------------------|-------------| +| IRelayCommand | RelayCommand | A basic command implementation that executes synchronous actions. Useful for binding UI elements to actions that do not require asynchronous execution. | +| IRelayCommand < T > | RelayCommand < T > | A generic version of RelayCommand that allows for parameterized execution. This variant supports passing a parameter of type T to the command's execute and can-execute methods, facilitating more dynamic command operations. | +| IRelayCommandAsync | RelayCommandAsync | A asynchronous command implementation designed for executing tasks that return a Task. It enhances UI responsiveness by running operations in the background, without blocking the UI thread. | +| IRelayCommandAsync < T > | RelayCommandAsync < T > | A generic, asynchronous command variant that accepts a parameter of type T. This version is suitable for operations that require both asynchrony and parameterization, allowing the command to perform background operations with input data. | + +## Implementation + +The `RelayCommand's` extends the ICommand interface with asynchronous capabilities, enabling +it to work seamlessly within an async/await programming model. It supports conditional execution +through a can-execute function and integrates an error handling mechanism. + +## Example Usage + +Below is an example demonstrating how to implement and utilize `RelayCommand's` within a ViewModel, +showcasing the creation of commands and the binding of enablement logic: + +```csharp +public class TestViewModel : ViewModelBase +{ + private bool isTestEnabled; + + public IRelayCommandAsync Test1Command => new RelayCommandAsync(Test1CommandHandler); + + public IRelayCommandAsync Test2Command => new RelayCommandAsync(Test2CommandHandler, () => IsTestEnabled); + + public IRelayCommandAsync Test3Command => new RelayCommandAsync(Test3CommandHandler); + + public IRelayCommandAsync Test4Command => new RelayCommandAsync(Test4CommandHandler, CanTest4CommandHandler); + + public bool IsTestEnabled + { + get => isTestEnabled; + set + { + isTestEnabled = value; + RaisePropertyChanged(); + + // Ensure the command's CanExecute state is evaluated whenever this property changes. + Test2Command.RaiseCanExecuteChanged(); + } + } + + private async Task Test1CommandHandler() + { + // Simulate a long-running task + await Task.Delay(1000); + MessageBox.Show("Test1-command is executed", "Information", MessageBoxButton.OK); + } + + private async Task Test2CommandHandler() + { + // Simulate a long-running task + await Task.Delay(1000); + MessageBox.Show("Test2-command is executed", "Information", MessageBoxButton.OK); + } + + private async Task Test3CommandHandler(string parameter) + { + // Simulate a long-running task + await Task.Delay(1000); + MessageBox.Show($"Test3-command is executed with parameter: {parameter}", "Information", MessageBoxButton.OK); + } + + private bool CanTest4CommandHandler(string obj) + { + return IsTestEnabled; + } + + private async Task Test4CommandHandler(string obj) + { + // Simulate a long-running task + await Task.Delay(1000, CancellationToken.None).ConfigureAwait(false); + _ = MessageBox.Show("Test4-command is hit", $"CommandParameter: {obj}", MessageBoxButton.OK); + } +} +``` + +> Note: All test command in the example can also be performed as without async/await by using RelayCommand's with the suffix Async. diff --git a/src/Atc.Wpf/Controls/Layouts/GridEx.cs b/src/Atc.Wpf/Controls/Layouts/GridEx.cs index f85d71d6..b1f73272 100644 --- a/src/Atc.Wpf/Controls/Layouts/GridEx.cs +++ b/src/Atc.Wpf/Controls/Layouts/GridEx.cs @@ -17,9 +17,9 @@ namespace Atc.Wpf.Controls.Layouts; /// - pixels /// - auto (size to column content) /// - * (star - size proportional to grid) --> -/// +/// /// -/// +/// /// ]]> /// [SuppressMessage("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "OK.")] diff --git a/src/Atc.Wpf/Controls/Layouts/GridEx_Readme.md b/src/Atc.Wpf/Controls/Layouts/GridEx_Readme.md new file mode 100644 index 00000000..cbb8254e --- /dev/null +++ b/src/Atc.Wpf/Controls/Layouts/GridEx_Readme.md @@ -0,0 +1,58 @@ +# GridEx + +The `GridEx` control is a extensions of the `Grid` control. + +## Example for GridEx usages + +```xml + + + + + + + + + + + + + +``` + +## The equvalent example with Grid usages + +```xml + + + + + + + + + + + + + + + + + + + + + + + +``` + +> Note: ColumnDefinitions and RowDefinitions is reduced to Columns and Rows in GridEx :heart_eyes: + +## Properties + +| Property | Type | Description | +|----------|-------------|----------------------------------------------------------------------| +| Rows | string | Comma seperated **Height** and allow `Auto`, `pixel`, `*`, `number*` | +| Columns | string | Comma seperated **Width** and allow `Auto`, `pixel`, `*`, `number*` | diff --git a/src/Atc.Wpf/Controls/Layouts/StaggeredPanel_Readme.md b/src/Atc.Wpf/Controls/Layouts/StaggeredPanel_Readme.md new file mode 100644 index 00000000..e591173e --- /dev/null +++ b/src/Atc.Wpf/Controls/Layouts/StaggeredPanel_Readme.md @@ -0,0 +1,15 @@ +# StaggeredPanel + +The `StaggeredPanel` control is a extensions of the `Panel` control. + +The `StaggeredPanel` allows for layout of items in a column approach where an item will be +added to whichever column has used the least amount of space. + +## Properties + +| Property | Type | Description | +|-------------------|-------------|-----------------------------------------------------------------------| +| DesiredItemWidth | double | The desired width of each column. The width of columns can exceed the DesiredColumnWidth if the HorizontalAlignment is set to Stretch. | +| Padding | Thickness | The dimensions of the space between the edge and its child as a Thickness value. | +| HorizontalSpacing | double | Set the horizontal spacing between the panel's items | +| VerticalSpacing | double | Set the vertical spacing between the panel's items | \ No newline at end of file diff --git a/src/Atc.Wpf/Controls/Layouts/UniformSpacingPanel.cs b/src/Atc.Wpf/Controls/Layouts/UniformSpacingPanel.cs index a8494602..37031d33 100644 --- a/src/Atc.Wpf/Controls/Layouts/UniformSpacingPanel.cs +++ b/src/Atc.Wpf/Controls/Layouts/UniformSpacingPanel.cs @@ -154,7 +154,7 @@ private static bool IsWidthHeightValid( private static bool IsSpacingValid( object value) - => value is double spacing && (double.IsNaN(spacing) || spacing > 0); + => value is double spacing && (double.IsNaN(spacing) || spacing >= 0); private void ArrangeWrapLine( double v, diff --git a/src/Atc.Wpf/Controls/Layouts/UniformSpacingPanel_Readme.md b/src/Atc.Wpf/Controls/Layouts/UniformSpacingPanel_Readme.md new file mode 100644 index 00000000..dd7c4276 --- /dev/null +++ b/src/Atc.Wpf/Controls/Layouts/UniformSpacingPanel_Readme.md @@ -0,0 +1,52 @@ +# UniformSpacingPanel + +The `UniformSpacingPanel` control is a extensions of the `Panel` control. + +## Example for UniformSpacingPanel usages + +```xml + + + + + + +``` + +```xml + + + + + + +``` + +## The equvalent example with PanelHelper usages + +```xml + + + + + + +``` + + +## Properties + +| Property | Type | Description | +|-------------------|-------------|-----------------------------------------------------------------------| +| HorizontalSpacing | double | Set the horizontal spacing between the panel's items | +| VerticalSpacing | double | Set the vertical spacing between the panel's items | +| Spacing | double | Set both the horizontal & vertical spacing between the panel's items | +| Orientation | Orientation | Set the orientation for rendering order | diff --git a/src/Atc.Wpf/Controls/Media/SvgImage.cs b/src/Atc.Wpf/Controls/Media/SvgImage.cs index 5eecabb3..fe2f0bec 100644 --- a/src/Atc.Wpf/Controls/Media/SvgImage.cs +++ b/src/Atc.Wpf/Controls/Media/SvgImage.cs @@ -2,9 +2,6 @@ // ReSharper disable InvertIf // ReSharper disable SwitchStatementHandlesSomeKnownEnumValuesWithDefault // ReSharper disable SwitchStatementMissingSomeEnumCasesNoDefault - -using Atc.Wpf.Controls.Media.W3cSvg; - namespace Atc.Wpf.Controls.Media; /// diff --git a/src/Atc.Wpf/Controls/Media/SvgImage_Readme.md b/src/Atc.Wpf/Controls/Media/SvgImage_Readme.md new file mode 100644 index 00000000..6d7bb775 --- /dev/null +++ b/src/Atc.Wpf/Controls/Media/SvgImage_Readme.md @@ -0,0 +1,69 @@ +# SvgImage + +The `SvgImage` control is a control that can render a SVG drawing as image. + +## Example for SvgImage usages + +```xml + +``` + +| Enum ControlSizeType | Description | +|------------------------|-------------| +| None | The image is not scaled. The image location is translated so the top left corner of the image bounding box is moved to the top left corner of the image control. | +| ContentToSizeNoStretch | The image is scaled to fit the control without any stretching. Either X or Y direction will be scaled to fill the entire width or height. | +| ContentToSizeStretch | The image will be stretched to fill the entire width and height. | +| SizeToContent | The control will be resized to fit the un-scaled image. If the image is larger than the maximum size for the control, the control is set to maximum size and the image is scaled. | + +## Properties + +| Property | Type | Description | +|---------------------|-------------------------------------------------------------------------------------------------| +| Background | Brush | Background brush | +| ControlSizeType | ControlSizeType | How to stretched/resize/scale the drawing | +| Source | string | The relative URL - For assembly component, rember to set "Build action=Resource" | +| FileSource | [TODO] | [TODO] | +| ImageSource | [TODO] | [TODO] | +| UseAnimations | [TODO] | [TODO] | +| OverrideColor | [TODO] | [TODO] | +| OverrideStrokeColor | [TODO] | [TODO] | +| OverrideStrokeWidth | [TODO] | [TODO] | +| CustomBrushes | [TODO] | [TODO] | +| ExternalFileLoader | [TODO] | [TODO] | + +## Methods + +| Method | Description | +|---------------------|-------------------------------------------------------------------------------------------| +| SetImage | Alternativ to `Source`, a method that by `string`, `Stream`, `Drawing` render the content | + +## Abbreviations + +SVG - Scalable Vector Graphics + +### W3C Specification for SVG + +[W3C - Scalable Vector Graphics (SVG) Tiny 1.2 Specification](https://www.w3.org/TR/SVGTiny12) + +| Section | Table of Contents | +| ------- | ----------------- | +| 1 | [Introduction](https://www.w3.org/TR/SVGTiny12/intro.html) +| 2 | [Concepts](https://www.w3.org/TR/SVGTiny12/concepts.html) +| 3 | [Rendering Model](https://www.w3.org/TR/SVGTiny12/render.html) +| 4 | [Basic Data Types](https://www.w3.org/TR/SVGTiny12/types.html) +| 5 | [Document Structure](https://www.w3.org/TR/SVGTiny12/struct.html) +| 6 | [Styling](https://www.w3.org/TR/SVGTiny12/styling.html) +| 7 | [Coordinate Systems, Transformations and Units](https://www.w3.org/TR/SVGTiny12/coords.html) +| 8 | [Paths](http://www.w3.org/TR/SVGTiny12/paths.html) +| 9 | [Basic Shapes](http://www.w3.org/TR/SVGTiny12/shapes.html) +| 10 | [Text](https://www.w3.org/TR/SVGTiny12/text.html) +| 11 | [Painting: Filling, Stroking, Colors and Paint Servers](https://www.w3.org/TR/SVGTiny12/painting.html) +| 12 | [Multimedia](https://www.w3.org/TR/SVGTiny12/multimedia.html) +| 13 | [Interactivity](https://www.w3.org/TR/SVGTiny12/interact.html) +| 14 | [Linking](https://www.w3.org/TR/SVGTiny12/linking.html) +| 15 | [Scripting](https://www.w3.org/TR/SVGTiny12/script.html) +| 16 | [Animation](https://www.w3.org/TR/SVGTiny12/animate.html) +| 17 | [Fonts](https://www.w3.org/TR/SVGTiny12/fonts.html) +| 18 | [Metadata](https://www.w3.org/TR/SVGTiny12/metadata.html) diff --git a/src/Atc.Wpf/Controls/Media/W3cSvg/SvgNotes.md b/src/Atc.Wpf/Controls/Media/W3cSvg/SvgNotes.md deleted file mode 100644 index e1a1054a..00000000 --- a/src/Atc.Wpf/Controls/Media/W3cSvg/SvgNotes.md +++ /dev/null @@ -1,25 +0,0 @@ -# SVG - Scalable Vector Graphics - - -### [W3C - Scalable Vector Graphics (SVG) Tiny 1.2 Specification](https://www.w3.org/TR/SVGTiny12) - -| Section | Table of Contents | -| ------- | ----------------- | -| 1 | [Introduction](https://www.w3.org/TR/SVGTiny12/intro.html) -| 2 | [Concepts](https://www.w3.org/TR/SVGTiny12/concepts.html) -| 3 | [Rendering Model](https://www.w3.org/TR/SVGTiny12/render.html) -| 4 | [Basic Data Types](https://www.w3.org/TR/SVGTiny12/types.html) -| 5 | [Document Structure](https://www.w3.org/TR/SVGTiny12/struct.html) -| 6 | [Styling](https://www.w3.org/TR/SVGTiny12/styling.html) -| 7 | [Coordinate Systems, Transformations and Units](https://www.w3.org/TR/SVGTiny12/coords.html) -| 8 | [Paths](http://www.w3.org/TR/SVGTiny12/paths.html) -| 9 | [Basic Shapes](http://www.w3.org/TR/SVGTiny12/shapes.html) -| 10 | [Text](https://www.w3.org/TR/SVGTiny12/text.html) -| 11 | [Painting: Filling, Stroking, Colors and Paint Servers](https://www.w3.org/TR/SVGTiny12/painting.html) -| 12 | [Multimedia](https://www.w3.org/TR/SVGTiny12/multimedia.html) -| 13 | [Interactivity](https://www.w3.org/TR/SVGTiny12/interact.html) -| 14 | [Linking](https://www.w3.org/TR/SVGTiny12/linking.html) -| 15 | [Scripting](https://www.w3.org/TR/SVGTiny12/script.html) -| 16 | [Animation](https://www.w3.org/TR/SVGTiny12/animate.html) -| 17 | [Fonts](https://www.w3.org/TR/SVGTiny12/fonts.html) -| 18 | [Metadata](https://www.w3.org/TR/SVGTiny12/metadata.html) diff --git a/src/Atc.Wpf/GlobalUsings.cs b/src/Atc.Wpf/GlobalUsings.cs index c9edecae..ab1e8318 100644 --- a/src/Atc.Wpf/GlobalUsings.cs +++ b/src/Atc.Wpf/GlobalUsings.cs @@ -44,6 +44,7 @@ global using Atc.Wpf.Controls.Documents.TextFormatters; global using Atc.Wpf.Controls.Documents.TextFormatters.SourceCode.Format; global using Atc.Wpf.Controls.Media; +global using Atc.Wpf.Controls.Media.W3cSvg; global using Atc.Wpf.Controls.Media.W3cSvg.Animation; global using Atc.Wpf.Controls.Media.W3cSvg.FileLoaders; global using Atc.Wpf.Controls.Media.W3cSvg.PaintServers; diff --git a/src/Atc.Wpf/Helpers/ColorHelper.cs b/src/Atc.Wpf/Helpers/ColorHelper.cs index 36164ac1..a954d274 100644 --- a/src/Atc.Wpf/Helpers/ColorHelper.cs +++ b/src/Atc.Wpf/Helpers/ColorHelper.cs @@ -396,7 +396,7 @@ private static void EnsureColorNamesForCulture( { if (ColorConverter.ConvertFromString(entryKey) is Color color) { - dictionary.Add(color, entry.Value!.ToString()!); + dictionary.TryAdd(color, entry.Value!.ToString()!); } } catch diff --git a/src/Atc.Wpf/Helpers/PanelHelper.cs b/src/Atc.Wpf/Helpers/PanelHelper.cs index 08c837a3..0c498af1 100644 --- a/src/Atc.Wpf/Helpers/PanelHelper.cs +++ b/src/Atc.Wpf/Helpers/PanelHelper.cs @@ -30,13 +30,32 @@ namespace Atc.Wpf.Helpers; [SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "OK.")] public static class PanelHelper { + private static readonly Thickness ZeroThickness = new(0); + + public static readonly DependencyProperty SpacingProperty = DependencyProperty.RegisterAttached( + "Spacing", + typeof(double), + typeof(PanelHelper), + new UIPropertyMetadata( + defaultValue: 0d, + OnSpacingChanged)); + + public static double GetSpacing( + DependencyObject obj) + => (double)obj.GetValue(SpacingProperty); + + public static void SetSpacing( + DependencyObject obj, + double space) + => obj.SetValue(SpacingProperty, space); + public static readonly DependencyProperty HorizontalSpacingProperty = DependencyProperty.RegisterAttached( "HorizontalSpacing", typeof(double), typeof(PanelHelper), new UIPropertyMetadata( defaultValue: 0d, - HorizontalSpacingChanged)); + OnHorizontalSpacingChanged)); public static double GetHorizontalSpacing( DependencyObject obj) @@ -53,7 +72,7 @@ public static void SetHorizontalSpacing( typeof(PanelHelper), new UIPropertyMetadata( defaultValue: 0d, - VerticalSpacingChanged)); + OnVerticalSpacingChanged)); public static double GetVerticalSpacing( DependencyObject obj) @@ -70,13 +89,13 @@ public static void SetVerticalSpacing( typeof(PanelHelper), new UIPropertyMetadata( new Thickness(0), - ItemMarginChanged)); + OnItemMarginChanged)); public static Thickness GetItemMargin( DependencyObject obj) => (Thickness)obj.GetValue(ItemMarginProperty); - public static void SetItemMargin( + private static void SetItemMargin( DependencyObject obj, Thickness value) => obj.SetValue(ItemMarginProperty, value); @@ -87,40 +106,76 @@ public static void SetItemMargin( typeof(PanelHelper), new UIPropertyMetadata( new Thickness(0), - ItemMarginChanged)); + OnItemMarginChanged)); public static Thickness GetLastItemMargin( DependencyObject obj) => (Thickness)obj.GetValue(LastItemMarginProperty); - public static void SetLastItemMargin( + private static void SetLastItemMargin( DependencyObject obj, Thickness value) => obj.SetValue(LastItemMarginProperty, value); - private static void HorizontalSpacingChanged( + private static void OnSpacingChanged( object sender, DependencyPropertyChangedEventArgs e) { + if (sender is not Panel panel) + { + return; + } + var space = (double)e.NewValue; var obj = (DependencyObject)sender; - SetItemMargin(obj, new Thickness(0, 0, space, 0)); - SetLastItemMargin(obj, new Thickness(0)); + var itemThickness = GetItemMargin(panel); + itemThickness.Right = space; + itemThickness.Bottom = space; + + SetItemMargin(obj, itemThickness); + SetLastItemMargin(obj, ZeroThickness); } - private static void VerticalSpacingChanged( + private static void OnHorizontalSpacingChanged( object sender, DependencyPropertyChangedEventArgs e) { + if (sender is not Panel panel) + { + return; + } + + var space = (double)e.NewValue; + var obj = (DependencyObject)sender; + + var itemThickness = GetItemMargin(panel); + itemThickness.Right = space; + + SetItemMargin(obj, itemThickness); + SetLastItemMargin(obj, ZeroThickness); + } + + private static void OnVerticalSpacingChanged( + object sender, + DependencyPropertyChangedEventArgs e) + { + if (sender is not Panel panel) + { + return; + } + var space = (double)e.NewValue; var obj = (DependencyObject)sender; - SetItemMargin(obj, new Thickness(0, 0, 0, space)); - SetLastItemMargin(obj, new Thickness(0)); + var itemThickness = GetItemMargin(panel); + itemThickness.Bottom = space; + + SetItemMargin(obj, itemThickness); + SetLastItemMargin(obj, ZeroThickness); } - private static void ItemMarginChanged( + private static void OnItemMarginChanged( object sender, DependencyPropertyChangedEventArgs e) { @@ -155,10 +210,7 @@ private static void OnPanelLoaded( continue; } - var isLastItem = i == panel.Children.Count - 1; - fe.Margin = isLastItem - ? GetLastItemMargin(panel) - : GetItemMargin(panel); + fe.Margin = GetItemMargin(panel); } } } \ No newline at end of file diff --git a/src/Atc.Wpf/Helpers/PanelHelper_Readme.md b/src/Atc.Wpf/Helpers/PanelHelper_Readme.md new file mode 100644 index 00000000..025b15df --- /dev/null +++ b/src/Atc.Wpf/Helpers/PanelHelper_Readme.md @@ -0,0 +1,65 @@ +# PanelHelper + +The `PanelHelper` enhances the functionality of WPF Panel controls and any controls +derived from the `Panel` class. It serves as a versatile extension, offering additional +capabilities and utilities to streamline the management and manipulation of panel layouts +within your applications. + +## Supported Controls + +`PanelHelper` seamlessly integrates with a variety of panel controls in +the WPF framework, including but not limited to: + +- Grid +- GridEx +- DockPanel +- PanelEx +- StackPanel +- StaggeredPanel +- TabPanel +- UniformSpacingPanel +- WrapPanel + +## Example for PanelHelper usages + +```xml + + + + + + +``` + +```xml + + + + + + +``` + +## The equvalent example with UniformSpacingPanel usages + +```xml + + + + + + +``` + +## Properties + +| Property | Type | Description | +|-------------------|-------------|-----------------------------------------------------------------------| +| HorizontalSpacing | double | Set the horizontal spacing between the panel's items | +| VerticalSpacing | double | Set the vertical spacing between the panel's items | +| Spacing | double | Set both the horizontal & vertical spacing between the panel's items | diff --git a/src/Atc.Wpf/Helpers/SolidColorBrushHelper.cs b/src/Atc.Wpf/Helpers/SolidColorBrushHelper.cs index 076175ec..3c0b03a2 100644 --- a/src/Atc.Wpf/Helpers/SolidColorBrushHelper.cs +++ b/src/Atc.Wpf/Helpers/SolidColorBrushHelper.cs @@ -330,7 +330,7 @@ private static void EnsureBrushNamesForCulture( var brush = new SolidColorBrush(color); brush.Freeze(); - dictionary.Add(brush, entry.Value!.ToString()!); + dictionary.TryAdd(brush, entry.Value!.ToString()!); } } catch (FormatException) diff --git a/src/Atc.Wpf/Media/ShaderEffects/@Readme.md b/src/Atc.Wpf/Media/ShaderEffects/@Readme.md new file mode 100644 index 00000000..e4f673f1 --- /dev/null +++ b/src/Atc.Wpf/Media/ShaderEffects/@Readme.md @@ -0,0 +1,10 @@ +# Media - ShaderEffects + +| Type | Parameters and range values | +| ----------------------------- | --------------------------------------------------------------------------- | +| ContrastAdjustShaderEffect | Brightness (-1.0 to 1.0 default 0.0) and Contrast (-1.0 to 1.0 default 0.0) | +| DesaturateShaderEffect | Strength (0.0 to 1.0 default 0.0) | +| FadeShaderEffect | Strength (0.0 to 1.0 default 0.0) and Color (color) | +| InvertColorsShaderEffect | None | +| MonochromeShaderEffect | Color (color) | +| SaturateShaderEffect | Progress | diff --git a/src/Atc.Wpf/Media/ShaderEffects/Shaders/@Notes.md b/src/Atc.Wpf/Media/ShaderEffects/Shaders/@Readme.md similarity index 97% rename from src/Atc.Wpf/Media/ShaderEffects/Shaders/@Notes.md rename to src/Atc.Wpf/Media/ShaderEffects/Shaders/@Readme.md index cbd5b09a..03a60a22 100644 --- a/src/Atc.Wpf/Media/ShaderEffects/Shaders/@Notes.md +++ b/src/Atc.Wpf/Media/ShaderEffects/Shaders/@Readme.md @@ -1,4 +1,4 @@ -# How to use HLSL Shader Compiler: +# How to use HLSL Shader Compiler 1. Create fx file 2. Write fx code @@ -10,17 +10,20 @@ HLSL Shader Compiler is called `fxc.exe` (Direct3D Shader Compiler) and it can be located in `C:\Program Files (x86)\Windows Kits\10\bin\x86\fxc.exe` Example on compile command with "/Fc -> output assembly code listing file" => cod file: -``` + +```c fxc.exe /T ps_2_0 /E main /WX /O0 /Fc /Zi /Fo ContrastAdjust.ps ContrastAdjust.fx ``` Example on compile: -``` + +```c fxc.exe /T ps_2_0 /E main /WX /O0 /Fo ContrastAdjust.ps ContrastAdjust.fx ``` Code example for ContrastAdjust: -``` + +```c sampler2D Input : register(s0); float Brightness : register(c0); float Contrast : register(c1); @@ -37,7 +40,8 @@ float4 main(float2 uv : TEXCOORD) : COLOR ``` Output assembly code listing file "cod file" for ContrastAdjust: -``` + +```c // // Generated by Microsoft (R) HLSL Shader Compiler 10.1 // @@ -79,11 +83,12 @@ Output assembly code listing file "cod file" for ContrastAdjust: ``` Actual script: -``` + +```c fxc.exe /T ps_2_0 /E main /WX /O0 /Fo ContrastAdjust.ps ContrastAdjust.fx fxc.exe /T ps_2_0 /E main /WX /O0 /Fo Desaturate.ps Desaturate.fx fxc.exe /T ps_2_0 /E main /WX /O0 /Fo Fade.ps Fade.fx fxc.exe /T ps_2_0 /E main /WX /O0 /Fo InvertColors.ps InvertColors.fx fxc.exe /T ps_2_0 /E main /WX /O0 /Fo Monochrome.ps Monochrome.fx fxc.exe /T ps_2_0 /E main /WX /O0 /Fo Saturate.ps Saturate.fx -``` \ No newline at end of file +``` diff --git a/src/Atc.Wpf/Mvvm/@Readme.md b/src/Atc.Wpf/Mvvm/@Readme.md new file mode 100644 index 00000000..c702edf4 --- /dev/null +++ b/src/Atc.Wpf/Mvvm/@Readme.md @@ -0,0 +1,18 @@ +# MVVM + +The Windows Presentation Framework (WPF) takes full advantage of the Model-View-ViewModel (MVVM) pattern. + +Therefore `Atc.Wpf` provide a good starting point for using MVVM. + +| Tools set in the package | Description | +|--------------------------| ---------------------------------------------------------------------------------| +| ViewModelBase | A base class for a the ViewModels | +| MainWindowViewModelBase | A base class for a the MainWindow-ViewModel | +| ViewModelDialogBase | A base class for a the Dialog-ViewModel | +| ObservableObject | A base class for a observable class that implement a PropertyChangedEventHandler | +| RelayCommand | Command with `CanExecute` | +| RelayCommand{T} | Command with `CanExecute` | +| RelayCommandAsync | Command with `CanExecute` as async | +| RelayCommandAsync{T} | Command with `CanExecute` as async | + +See more about [RelayCommand's](../Command/@Readme.md) and how to use them. diff --git a/src/Atc.Wpf/SampleControls/SampleViewerView.xaml b/src/Atc.Wpf/SampleControls/SampleViewerView.xaml index 1f181fa0..69f7628c 100644 --- a/src/Atc.Wpf/SampleControls/SampleViewerView.xaml +++ b/src/Atc.Wpf/SampleControls/SampleViewerView.xaml @@ -3,9 +3,11 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:helpers="clr-namespace:Atc.Wpf.Helpers" xmlns:inputs="clr-namespace:Atc.Wpf.Controls.Inputs" xmlns:layouts="clr-namespace:Atc.Wpf.Controls.Layouts" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:mdXaml="https://github.com/whistyun/MdXaml" xmlns:sampleControls="clr-namespace:Atc.Wpf.SampleControls" xmlns:sourceCode="clr-namespace:Atc.Wpf.Controls.Documents.TextFormatters.SourceCode" x:Name="UcSampleViewerView" @@ -14,18 +16,26 @@ d:DesignWidth="800" mc:Ignorable="d"> - - - + + + + + + + - + + + + diff --git a/src/Atc.Wpf/SampleControls/SampleViewerView.xaml.cs b/src/Atc.Wpf/SampleControls/SampleViewerView.xaml.cs index ad0b5341..dd04e5ea 100644 --- a/src/Atc.Wpf/SampleControls/SampleViewerView.xaml.cs +++ b/src/Atc.Wpf/SampleControls/SampleViewerView.xaml.cs @@ -20,5 +20,7 @@ public SolidColorBrush HeaderForeground public SampleViewerView() { InitializeComponent(); + + DataContext = new SampleViewerViewModel(); } } \ No newline at end of file diff --git a/src/Atc.Wpf/SampleControls/SampleViewerViewModel.cs b/src/Atc.Wpf/SampleControls/SampleViewerViewModel.cs index 58ddd4d9..609a5b75 100644 --- a/src/Atc.Wpf/SampleControls/SampleViewerViewModel.cs +++ b/src/Atc.Wpf/SampleControls/SampleViewerViewModel.cs @@ -1,7 +1,6 @@ // ReSharper disable LoopCanBeConvertedToQuery namespace Atc.Wpf.SampleControls; -[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "OK.")] public class SampleViewerViewModel : ViewModelBase { public SampleViewerViewModel() @@ -9,12 +8,14 @@ public SampleViewerViewModel() Messenger.Default.Register(this, SampleItemMessageHandler); } + private FileInfo[]? readmeMarkdownFiles; private int tabSelectedIndex; private string? header; private UserControl? sampleContent; private string? xamlCode; private string? codeBehindCode; private string? viewModelCode; + private string? readmeMarkdown; public int TabSelectedIndex { @@ -34,6 +35,8 @@ public int TabSelectedIndex public bool HasViewModelCode => ViewModelCode is not null; + public bool HasReadmeMarkdown => ReadmeMarkdown is not null; + public string? Header { get => header; @@ -88,6 +91,17 @@ public string? ViewModelCode } } + public string? ReadmeMarkdown + { + get => readmeMarkdown; + set + { + readmeMarkdown = value; + RaisePropertyChanged(); + RaisePropertyChanged(nameof(HasReadmeMarkdown)); + } + } + private void SampleItemMessageHandler( SampleItemMessage obj) { @@ -165,6 +179,103 @@ private void SetSelectedViewData( var classViewModelName = ExtractClassName(instance.DataContext.ToString()!); ViewModelCode = ReadFileText(Path.Combine(sampleLocation.FullName, classViewModelName + ".cs")); } + + LoadAndRenderReadmeMarkdownIfPossible(classViewName); + } + + private void LoadAndRenderReadmeMarkdownIfPossible( + string classViewName) + { + ReadmeMarkdown = null; + if (readmeMarkdownFiles is null) + { + PrepareReadmeReferences(); + } + + if (readmeMarkdownFiles is null) + { + return; + } + + var readmeMarkdownFile = readmeMarkdownFiles.SingleOrDefault(x => x.Name.StartsWith(classViewName + "_Readme", StringComparison.OrdinalIgnoreCase)); + if (readmeMarkdownFile is null && + classViewName.EndsWith("View", StringComparison.Ordinal)) + { + var className = classViewName.Replace("View", string.Empty, StringComparison.Ordinal); + readmeMarkdownFile = readmeMarkdownFiles.SingleOrDefault(x => x.Name.StartsWith(className + "_Readme", StringComparison.OrdinalIgnoreCase)); + + if (readmeMarkdownFile is null) + { + var type = FindCustomTypeByName(className); + if (type?.FullName is not null) + { + var sa = type.FullName.Split('.', StringSplitOptions.RemoveEmptyEntries); + if (sa.Length > 2) + { + var classFolder = sa[^2]; + readmeMarkdownFile = readmeMarkdownFiles.SingleOrDefault(x => x.FullName.EndsWith($"\\{classFolder}\\@Readme.md", StringComparison.OrdinalIgnoreCase)); + } + } + } + } + + if (readmeMarkdownFile is null) + { + return; + } + + var readmeMarkdownTxt = FileHelper.ReadAllText(readmeMarkdownFile); + ReadmeMarkdown = readmeMarkdownTxt; + } + + private static Type? FindCustomTypeByName(string className) + { + var type = Type.GetType(className); + if (type is not null) + { + return type; + } + + var customAssemblies = AppDomain + .CurrentDomain + .GetCustomAssemblies() + .OrderBy(x => x.FullName, StringComparer.Ordinal); + + foreach (var customAssembly in customAssemblies) + { + var exportedTypes = customAssembly.GetExportedTypes(); + + type = exportedTypes.FirstOrDefault(x => x.Name.Equals(className, StringComparison.Ordinal)); + + if (type is not null) + { + break; + } + } + + return type; + } + + private static string GetBasePath() + { + var entryAssembly = Assembly.GetEntryAssembly()!; + var assemblyLocation = entryAssembly.Location; + + var indexOf = assemblyLocation.IndexOf("\\sample", StringComparison.OrdinalIgnoreCase); + var baseLocation = indexOf == -1 + ? assemblyLocation + : assemblyLocation[..indexOf]; + + return baseLocation; + } + + public void PrepareReadmeReferences() + { + var basePath = GetBasePath(); + + readmeMarkdownFiles = FileHelper.GetFiles(basePath, "*.md") + .Where(x => x.Name.Contains("readme", StringComparison.OrdinalIgnoreCase)) + .ToArray(); } private static Type? GetTypeBySamplePath( diff --git a/src/Atc.Wpf/SampleControls/SampleViewerView_Readme.md b/src/Atc.Wpf/SampleControls/SampleViewerView_Readme.md new file mode 100644 index 00000000..da49073d --- /dev/null +++ b/src/Atc.Wpf/SampleControls/SampleViewerView_Readme.md @@ -0,0 +1,3 @@ +# SampleViewerView + +TODO: Comming soon... diff --git a/src/Atc.Wpf/SampleControls/Styles/ReadmeMarkdownStyle.xaml b/src/Atc.Wpf/SampleControls/Styles/ReadmeMarkdownStyle.xaml new file mode 100644 index 00000000..dd98bdcb --- /dev/null +++ b/src/Atc.Wpf/SampleControls/Styles/ReadmeMarkdownStyle.xaml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Atc.Wpf/System/Windows/Markup/ManagedMarkupExtension.cs b/src/Atc.Wpf/System/Windows/Markup/ManagedMarkupExtension.cs index 67e31589..f50f2c85 100644 --- a/src/Atc.Wpf/System/Windows/Markup/ManagedMarkupExtension.cs +++ b/src/Atc.Wpf/System/Windows/Markup/ManagedMarkupExtension.cs @@ -111,7 +111,6 @@ protected Type? TargetPropertyType /// /// Update the associated target. /// - [SuppressMessage("Major Code Smell", "S3267:Loops should be simplified with \"LINQ\" expressions", Justification = "OK.")] public void UpdateTarget() { if (targetProperty is null) diff --git a/src/Atc.Wpf/System/Windows/Markup/MarkupExtensionManager.cs b/src/Atc.Wpf/System/Windows/Markup/MarkupExtensionManager.cs index 385090f2..3dbdb86c 100644 --- a/src/Atc.Wpf/System/Windows/Markup/MarkupExtensionManager.cs +++ b/src/Atc.Wpf/System/Windows/Markup/MarkupExtensionManager.cs @@ -11,7 +11,7 @@ namespace System.Windows.Markup; public sealed class MarkupExtensionManager { /// - /// The interval at which to cleanup and remove extensions. + /// The interval at which to clean up and remove extensions. /// private readonly int cleanupInterval; @@ -24,7 +24,7 @@ public sealed class MarkupExtensionManager /// Initializes a new instance of the class. /// /// - /// The interval at which to cleanup and remove extensions associated with garbage + /// The interval at which to clean up and remove extensions associated with garbage /// collected targets. This specifies the number of new Markup Extensions that are /// created before a cleanup is triggered. /// diff --git a/src/Atc.Wpf/Translation/@Readme.md b/src/Atc.Wpf/Translation/@Readme.md new file mode 100644 index 00000000..096f314f --- /dev/null +++ b/src/Atc.Wpf/Translation/@Readme.md @@ -0,0 +1,74 @@ +# Translation Component / Extension + +Localizing your application in .NET involves adapting it to different languages and regions. This process is streamlined by leveraging the CurrentUICulture property of the Thread class, which determines the UI culture for any thread. The .NET framework uses this setting to select the appropriate resources for that culture. Resources are typically stored in .resx files, which contain translations for various strings used within your application. When you build your application, these .resx files are compiled into satellite assemblies - separate assemblies that are specific to each culture. + +## Satellite Assemblies and .resx Files + +Satellite assemblies are essential for managing localized resources. They allow you to deploy applications with support for multiple languages by simply including the appropriate satellite assemblies, without modifying the main application assembly. Each satellite assembly contains resources for a specific culture, identified by its locale (e.g., "en-US", "fr-FR"). This approach keeps your application modular and simplifies the addition of new languages. + +## CurrentUICulture in Localization + +The CurrentUICulture property plays a pivotal role in resource selection. By setting this property, you direct the .NET runtime to retrieve the correct localized resources. This property should match the user's preferred language, which can be determined automatically or allowed to be selected manually in the application's settings. + +```csharp +Thread.CurrentThread.CurrentUICulture = new CultureInfo("es-ES"); +``` + +This code snippet sets the current UI culture to Spanish (Spain), instructing the .NET runtime to use resources from the satellite assembly associated with this culture. + +## XAML and C# Localization Usage + +Effortlessly localize your application by binding text to a resource assembly containing the necessary translations, adhering to the standard .NET Globalization and Localization approach. This process is enhanced by a XAML markup extension for efficient key-based resource retrieval. + +## XAML Usage + +To be able to use resource translation lookups in XAML, +Atc has a `ResxExtension`, which is a markup extension. + +### Setup + +First, declare the namespace in your root element: + +```xml + +``` + +### Basic Binding + +Bind directly to a resource key in a .resx file, specifying its full namespace: + +```xml + +``` + +### Advanced Binding + +Enhance the basic binding by adding prefixes and suffixes to the translated text: + +```xml + +``` + +## C# Usage + +### Retrieve Translated Value + +Access a translated value by key from a `.resx` file, using its full namespace: + +```csharp +var value = Wpf.Sample.Resource.Word.About +``` + +### Apply Prefix and Suffix + +Concatenate a prefix and suffix to the translated value for dynamic text manipulation: + +```csharp +var value = $"foo {Wpf.Sample.Resource.Word.About} bar"; +``` + +By understanding and utilizing CurrentUICulture, satellite assemblies, and .resx files, +developers can create highly adaptable .NET applications that cater to a global audience. diff --git a/src/Atc.Wpf/ValueConverters/@Readme.md b/src/Atc.Wpf/ValueConverters/@Readme.md new file mode 100644 index 00000000..67c0c228 --- /dev/null +++ b/src/Atc.Wpf/ValueConverters/@Readme.md @@ -0,0 +1,92 @@ +# ValueConverters in Atc.Wpf + +## ValueConverters - Bool to X + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| Bool -> Bool | BoolToInverseBoolValueConverter | True -> False and False -> True | False -> True and False -> False | +| Bool -> Visibility | BoolToVisibilityCollapsedValueConverter | True -> Collapsed and False -> Visible | Collapsed -> True and Visible -> False | +| Bool -> Visibility | BoolToVisibilityVisibleValueConverter | True -> Visible and False -> Collapsed | Visible -> True and Collapsed -> False | +| Bool -> With | BoolToWidthValueConverter | true, 10 -> 10 and true, "Auto" -> * | Not supported | +| Bool[] -> Bool | MultiBoolToBoolValueConverter | All-True -> True | Not supported | +| Bool[] -> Visibility | MultiBoolToVisibilityVisibleValueConverter | All-True -> Visible | Not supported | + +## ValueConverters - String to X + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| String -> Brush | ColorNameToBrushValueConverter | "Green" -> Brushs.Green | Brushs.Green -> "Green" | +| String -> Color | ColorNameToColorValueConverter | "Green" -> Colors.Green | Colors.Green -> "Green" | +| String -> "NumericFormat" | StandardNumericFormatTypeToFormatStringValueConverter | StandardNumericFormatType -> String | Not supported | +| String -> Bool | StringNullOrEmptyToBoolValueConverter | NULL or empty -> True | Not supported | +| String -> Bool | StringNullOrEmptyToInverseBoolValueConverter | NULL or empty -> False | Not supported | +| String -> Visibility | StringNullOrEmptyToVisibilityCollapsedValueConverter | NULL or empty -> Collapsed | Not supported | +| String -> Visibility | StringNullOrEmptyToVisibilityVisibleValueConverter | NULL or empty -> Visible | Not supported | +| String -> String | ToLowerValueConverter | String -> String | Binding.DoNothing | +| String -> String | ToUpperValueConverter | String -> String | Binding.DoNothing | + +## ValueConverters - ICollection to X + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| ICollection -> Bool | CollectionNullOrEmptyToBoolValueConverter | NULL or empty -> True | Not supported | +| ICollection -> Bool | CollectionNullOrEmptyToInverseBoolValueConverter | NULL or empty -> False | Not supported | +| ICollection -> Visibility | CollectionNullOrEmptyToVisibilityCollapsedValueConverter | NULL or empty -> Collapsed | Not supported | +| ICollection -> Visibility | CollectionNullOrEmptyToVisibilityVisibleValueConverter | NULL or empty -> Visible | Not supported | + +## ValueConverters - Object to X + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| Object -> Bool | IsNotNullValueConverter | <>Null -> True and Null -> False | Not supported | +| Object -> Bool | IsNullValueConverter | Null -> True and <>Null -> False | Not supported | +| Null -> X | NullCheckValueConverter | NULL -> Parameter if set | Not supported | +| Null -> UnsetValue | NullToUnsetValueConverter | NULL -> DependencyProperty.UnsetValue | Object -> DependencyProperty.UnsetValue | +| Object -> Bool | ObjectNotNullToBoolValueConverter | NotNULL -> True | Not supported | +| Object -> Visibility | ObjectNotNullToVisibilityVisibleValueConverter | NotNULL -> Visible | Not supported | +| Object -> Visibility | ObjectNullToVisibilityCollapsedValueConverter | NULL -> Collapsed | Not supported | +| Object[] -> Visibility | MultiObjectNullToVisibilityCollapsedValueConverter | All-NULL -> Collapsed | Not supported | +| Object -> Bool | ObjectNullToBoolValueConverter | NULL => True | Not supported | + + +### ValueConverters - Markup to X + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| Base converter | MarkupMultiValueConverterBase | Base converter - no examples | Base converter - no examples | +| | MarkupValueConverter | | | +| | MarkupValueConverterBase | | | + +### ValueConverters - Others to X + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| | BackgroundToForegroundValueConverter | | | +| Brush -> Color | BrushToColorValueConverter | Brushs.Green -> Colors.Green | Colors.Green -> Brushs.Green | +| Color -> Brush | ColorToBrushValueConverter | Colors.Green -> Brushs.Green | Brushs.Green -> Colors.Green | +| Color -> SolidColor | ColorToSolidColorValueConverter | Colors.Green -> Colors.Green | Not supported | +| Color -> String | ColorHexToColorValueConverter | "#FF00FF00" -> "Green" | "Green" -> "#FF00FF00" | +| Hex-Color -> Color-Key | HexColorToColorKeyValueConverter | "#FF00FF00" -> "Green" | "Green" -> Brushs.Green | +| Enum -> String | EnumDescriptionToStringValueConverter | DayOfWeek.Monday -> Monday | Not supported | +| Int -> Visibility | IntegerGreaterThenZeroToVisibilityVisibleValueConverter | 0 -> Collapsed and 1 -> Visible | Not supported | +| Int -> TimeSpan | IntegerToTimeSpanValueConverter | 100 -> TimeSpan.FromMilliseconds(100) | Not supported | +| LogCategoryType -> Brush | LogCategoryTypeToBrushValueConverter | Information -> DodgerBlue | Not supported | +| LogCategoryType -> Color | LogCategoryTypeToColorValueConverter | Information -> DodgerBlue | Not supported | +| LogLevel -> Brush | LogLevelToBrushValueConverter | Information -> DodgerBlue | Not supported | +| LogLevel -> Color | LogLevelToColorValueConverter | Information -> DodgerBlue | Not supported | +| | ObservableDictionaryToDictionaryOfStringsValueConverter | | | +| | ThicknessBindingValueConverter | | DependencyProperty.UnsetValue | +| | ThicknessFilterValueConverter | | DependencyProperty.UnsetValue | +| | ThicknessToDoubleValueConverter | | DependencyProperty.UnsetValue | +| Errors -> String | ValidationErrorsToStringValueConverter | | Not supported | +| | WindowResizeModeMinMaxButtonVisibilityMultiValueConverter| | | + +## ValueConverters - Math + +| Category | Type | Convert Examples | ConvertBack Examples | +| ------------------------- | -------------------------------------------------------- | --------------------------------------- | --------------------------------------- | +| | MathAddValueConverter | | | +| | MathDivideValueConverter | | | +| | MathMultiplyValueConverter | | | +| | MathSubtractValueConverter | | | +| | MathValueConverter | | |