diff --git a/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj b/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj index f4e0039c..796f9876 100644 --- a/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj +++ b/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj @@ -7,6 +7,7 @@ HandyControlDemo 1.5.5 ..\..\Shared\HandyControlDemo_Shared\Resources\Img\icon.ico + Debug;Release TRACE;Core @@ -348,6 +349,9 @@ Resources\Img\LeftMainContent\MainMenuControl_16x.png + + Resources\Img\LeftMainContent\brackets_Square_16xLG.png + diff --git a/src/Core_30/HandyControl_Core_30/HandyControl_Core_30.csproj b/src/Core_30/HandyControl_Core_30/HandyControl_Core_30.csproj index 0afdeaa1..9d2421a4 100644 --- a/src/Core_30/HandyControl_Core_30/HandyControl_Core_30.csproj +++ b/src/Core_30/HandyControl_Core_30/HandyControl_Core_30.csproj @@ -10,6 +10,7 @@ false Copyright © HandyOrg 2018-2019 Contains some commonly used simple WPF controls + Debug;Release TRACE;Core diff --git a/src/HandyControl.sln b/src/HandyControl.sln new file mode 100644 index 00000000..e6c455be --- /dev/null +++ b/src/HandyControl.sln @@ -0,0 +1,183 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28729.10 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandyControl_Net_GE45", "Net_GE45\HandyControl_Net_GE45\HandyControl_Net_GE45.csproj", "{DC966E3D-BCFF-4652-98CF-070E5494749A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandyControlDemo_Net_GE45", "Net_GE45\HandyControlDemo_Net_GE45\HandyControlDemo_Net_GE45.csproj", "{9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Net_GE45", "Net_GE45", "{2F551C62-77F7-4FA5-8AD7-FCF53E92AE08}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{0938270D-E9F0-489B-AF9E-5C5AD7C69897}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "HandyControl_Shared", "Shared\HandyControl_Shared\HandyControl_Shared.shproj", "{AAC11083-FACA-405D-9197-5C1212D65656}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "HandyControlDemo_Shared", "Shared\HandyControlDemo_Shared\HandyControlDemo_Shared.shproj", "{C4694269-C9B8-45D5-87F8-D0088C532510}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Net_40", "Net_40", "{35E3F9C0-8924-4536-BE09-F3761FDBF066}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core_30", "Core_30", "{B838C973-06F0-48A1-B259-A357AAF2D8D4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HandyControl_Core_30", "Core_30\HandyControl_Core_30\HandyControl_Core_30.csproj", "{BE4A567D-B6E0-413E-8F64-E1A53B4F9366}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HandyControlDemo_Core30", "Core_30\HandyControlDemo_Core_30\HandyControlDemo_Core30.csproj", "{D7107690-8592-4F9F-9379-9B82C1C15D2A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandyControl_Net_40", "Net_40\HandyControl_Net_40\HandyControl_Net_40.csproj", "{32204503-2EF0-4681-AE13-AA1FEB6C658A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandyControlDemo_Net_40", "Net_40\HandyControlDemo_Net_40\HandyControlDemo_Net_40.csproj", "{D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Shared\HandyControl_Shared\HandyControl_Shared.projitems*{32204503-2ef0-4681-ae13-aa1feb6c658a}*SharedItemsImports = 4 + Shared\HandyControlDemo_Shared\HandyControlDemo_Shared.projitems*{9a7b52e6-94bb-4e7e-bb6a-7cf6761b79a7}*SharedItemsImports = 4 + Shared\HandyControl_Shared\HandyControl_Shared.projitems*{aac11083-faca-405d-9197-5c1212d65656}*SharedItemsImports = 13 + Shared\HandyControlDemo_Shared\HandyControlDemo_Shared.projitems*{c4694269-c9b8-45d5-87f8-d0088c532510}*SharedItemsImports = 13 + Shared\HandyControlDemo_Shared\HandyControlDemo_Shared.projitems*{d8ae88f8-c36b-4d10-a7f9-22ffcfba5231}*SharedItemsImports = 4 + Shared\HandyControl_Shared\HandyControl_Shared.projitems*{dc966e3d-bcff-4652-98cf-070e5494749a}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug-Core30|Any CPU = Debug-Core30|Any CPU + Debug-Net40|Any CPU = Debug-Net40|Any CPU + Debug-Net45|Any CPU = Debug-Net45|Any CPU + Debug-Net462|Any CPU = Debug-Net462|Any CPU + Debug-Net47|Any CPU = Debug-Net47|Any CPU + Debug-Net48|Any CPU = Debug-Net48|Any CPU + Release-Core30|Any CPU = Release-Core30|Any CPU + Release-Net40|Any CPU = Release-Net40|Any CPU + Release-Net45|Any CPU = Release-Net45|Any CPU + Release-Net462|Any CPU = Release-Net462|Any CPU + Release-Net47|Any CPU = Release-Net47|Any CPU + Release-Net48|Any CPU = Release-Net48|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Core30|Any CPU.ActiveCfg = Debug-Net45|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net40|Any CPU.ActiveCfg = Debug-Net45|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net45|Any CPU.ActiveCfg = Debug-Net45|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net45|Any CPU.Build.0 = Debug-Net45|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net462|Any CPU.ActiveCfg = Debug-Net462|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net462|Any CPU.Build.0 = Debug-Net462|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net47|Any CPU.ActiveCfg = Debug-Net47|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net47|Any CPU.Build.0 = Debug-Net47|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net48|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net48|Any CPU.Build.0 = Debug-Net48|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Core30|Any CPU.ActiveCfg = Release-Net48|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net40|Any CPU.ActiveCfg = Release-Net45|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net45|Any CPU.ActiveCfg = Release-Net45|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net45|Any CPU.Build.0 = Release-Net45|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net462|Any CPU.ActiveCfg = Release-Net462|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net462|Any CPU.Build.0 = Release-Net462|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net47|Any CPU.ActiveCfg = Release-Net47|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net47|Any CPU.Build.0 = Release-Net47|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net48|Any CPU.ActiveCfg = Release-Net48|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net48|Any CPU.Build.0 = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Core30|Any CPU.ActiveCfg = Debug-Net47|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net40|Any CPU.ActiveCfg = Debug-Net47|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net45|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net45|Any CPU.Build.0 = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net462|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net462|Any CPU.Build.0 = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net47|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net47|Any CPU.Build.0 = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net48|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net48|Any CPU.Build.0 = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Core30|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net40|Any CPU.ActiveCfg = Release-Net47|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net45|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net45|Any CPU.Build.0 = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net462|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net462|Any CPU.Build.0 = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net47|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net47|Any CPU.Build.0 = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net48|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net48|Any CPU.Build.0 = Release-Net48|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Debug-Core30|Any CPU.ActiveCfg = Debug|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Debug-Core30|Any CPU.Build.0 = Debug|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Debug-Net40|Any CPU.ActiveCfg = Debug|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Debug-Net45|Any CPU.ActiveCfg = Debug|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Debug-Net462|Any CPU.ActiveCfg = Debug|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Debug-Net47|Any CPU.ActiveCfg = Debug|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Debug-Net48|Any CPU.ActiveCfg = Debug|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Core30|Any CPU.ActiveCfg = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Core30|Any CPU.Build.0 = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net40|Any CPU.ActiveCfg = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net45|Any CPU.ActiveCfg = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net45|Any CPU.Build.0 = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net462|Any CPU.ActiveCfg = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net462|Any CPU.Build.0 = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net47|Any CPU.ActiveCfg = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net47|Any CPU.Build.0 = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net48|Any CPU.ActiveCfg = Release|Any CPU + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366}.Release-Net48|Any CPU.Build.0 = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Debug-Core30|Any CPU.ActiveCfg = Debug|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Debug-Core30|Any CPU.Build.0 = Debug|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Debug-Net40|Any CPU.ActiveCfg = Debug|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Debug-Net45|Any CPU.ActiveCfg = Debug|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Debug-Net462|Any CPU.ActiveCfg = Debug|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Debug-Net47|Any CPU.ActiveCfg = Debug|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Debug-Net48|Any CPU.ActiveCfg = Debug|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Core30|Any CPU.ActiveCfg = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Core30|Any CPU.Build.0 = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net40|Any CPU.ActiveCfg = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net45|Any CPU.ActiveCfg = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net45|Any CPU.Build.0 = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net462|Any CPU.ActiveCfg = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net462|Any CPU.Build.0 = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net47|Any CPU.ActiveCfg = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net47|Any CPU.Build.0 = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net48|Any CPU.ActiveCfg = Release|Any CPU + {D7107690-8592-4F9F-9379-9B82C1C15D2A}.Release-Net48|Any CPU.Build.0 = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Debug-Core30|Any CPU.ActiveCfg = Debug|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Debug-Net40|Any CPU.ActiveCfg = Debug|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Debug-Net40|Any CPU.Build.0 = Debug|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Debug-Net45|Any CPU.ActiveCfg = Debug|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Debug-Net462|Any CPU.ActiveCfg = Debug|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Debug-Net47|Any CPU.ActiveCfg = Debug|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Debug-Net48|Any CPU.ActiveCfg = Debug|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Core30|Any CPU.ActiveCfg = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net40|Any CPU.ActiveCfg = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net40|Any CPU.Build.0 = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net45|Any CPU.ActiveCfg = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net45|Any CPU.Build.0 = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net462|Any CPU.ActiveCfg = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net462|Any CPU.Build.0 = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net47|Any CPU.ActiveCfg = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net47|Any CPU.Build.0 = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net48|Any CPU.ActiveCfg = Release|Any CPU + {32204503-2EF0-4681-AE13-AA1FEB6C658A}.Release-Net48|Any CPU.Build.0 = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Debug-Core30|Any CPU.ActiveCfg = Debug|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Debug-Net40|Any CPU.ActiveCfg = Debug|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Debug-Net40|Any CPU.Build.0 = Debug|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Debug-Net45|Any CPU.ActiveCfg = Debug|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Debug-Net462|Any CPU.ActiveCfg = Debug|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Debug-Net47|Any CPU.ActiveCfg = Debug|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Debug-Net48|Any CPU.ActiveCfg = Debug|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Core30|Any CPU.ActiveCfg = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net40|Any CPU.ActiveCfg = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net40|Any CPU.Build.0 = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net45|Any CPU.ActiveCfg = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net45|Any CPU.Build.0 = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net462|Any CPU.ActiveCfg = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net462|Any CPU.Build.0 = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net47|Any CPU.ActiveCfg = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net47|Any CPU.Build.0 = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net48|Any CPU.ActiveCfg = Release|Any CPU + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231}.Release-Net48|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {DC966E3D-BCFF-4652-98CF-070E5494749A} = {2F551C62-77F7-4FA5-8AD7-FCF53E92AE08} + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7} = {2F551C62-77F7-4FA5-8AD7-FCF53E92AE08} + {AAC11083-FACA-405D-9197-5C1212D65656} = {0938270D-E9F0-489B-AF9E-5C5AD7C69897} + {C4694269-C9B8-45D5-87F8-D0088C532510} = {0938270D-E9F0-489B-AF9E-5C5AD7C69897} + {BE4A567D-B6E0-413E-8F64-E1A53B4F9366} = {B838C973-06F0-48A1-B259-A357AAF2D8D4} + {D7107690-8592-4F9F-9379-9B82C1C15D2A} = {B838C973-06F0-48A1-B259-A357AAF2D8D4} + {32204503-2EF0-4681-AE13-AA1FEB6C658A} = {35E3F9C0-8924-4536-BE09-F3761FDBF066} + {D8AE88F8-C36B-4D10-A7F9-22FFCFBA5231} = {35E3F9C0-8924-4536-BE09-F3761FDBF066} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D4636382-1A18-4079-A3E7-054DD970F179} + EndGlobalSection +EndGlobal diff --git a/src/HandyControl_Core30.sln b/src/HandyControl_Core_30.sln similarity index 100% rename from src/HandyControl_Core30.sln rename to src/HandyControl_Core_30.sln diff --git a/src/HandyControl_Net_40.sln b/src/HandyControl_Net_40.sln index adb9a4cc..60bcd427 100644 --- a/src/HandyControl_Net_40.sln +++ b/src/HandyControl_Net_40.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2035 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Net_40", "Net_40", "{763DABFC-950A-4965-97CB-15C59A928401}" EndProject diff --git a/src/HandyControl_Net_GE45.sln b/src/HandyControl_Net_GE45.sln index 4093e7bd..b321309b 100644 --- a/src/HandyControl_Net_GE45.sln +++ b/src/HandyControl_Net_GE45.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2035 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandyControl_Net_GE45", "Net_GE45\HandyControl_Net_GE45\HandyControl_Net_GE45.csproj", "{DC966E3D-BCFF-4652-98CF-070E5494749A}" EndProject @@ -26,9 +26,11 @@ Global Debug-Net45|Any CPU = Debug-Net45|Any CPU Debug-Net462|Any CPU = Debug-Net462|Any CPU Debug-Net47|Any CPU = Debug-Net47|Any CPU + Debug-Net48|Any CPU = Debug-Net48|Any CPU Release-Net45|Any CPU = Release-Net45|Any CPU Release-Net462|Any CPU = Release-Net462|Any CPU Release-Net47|Any CPU = Release-Net47|Any CPU + Release-Net48|Any CPU = Release-Net48|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net45|Any CPU.ActiveCfg = Debug-Net45|Any CPU @@ -37,24 +39,32 @@ Global {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net462|Any CPU.Build.0 = Debug-Net462|Any CPU {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net47|Any CPU.ActiveCfg = Debug-Net47|Any CPU {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net47|Any CPU.Build.0 = Debug-Net47|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net48|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Debug-Net48|Any CPU.Build.0 = Debug-Net48|Any CPU {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net45|Any CPU.ActiveCfg = Release-Net45|Any CPU {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net45|Any CPU.Build.0 = Release-Net45|Any CPU {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net462|Any CPU.ActiveCfg = Release-Net462|Any CPU {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net462|Any CPU.Build.0 = Release-Net462|Any CPU {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net47|Any CPU.ActiveCfg = Release-Net47|Any CPU {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net47|Any CPU.Build.0 = Release-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net45|Any CPU.ActiveCfg = Debug-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net45|Any CPU.Build.0 = Debug-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net462|Any CPU.ActiveCfg = Debug-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net462|Any CPU.Build.0 = Debug-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net47|Any CPU.ActiveCfg = Debug-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net47|Any CPU.Build.0 = Debug-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net45|Any CPU.ActiveCfg = Release-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net45|Any CPU.Build.0 = Release-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net462|Any CPU.ActiveCfg = Release-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net462|Any CPU.Build.0 = Release-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net47|Any CPU.ActiveCfg = Release-Net47|Any CPU - {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net47|Any CPU.Build.0 = Release-Net47|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net48|Any CPU.ActiveCfg = Release-Net48|Any CPU + {DC966E3D-BCFF-4652-98CF-070E5494749A}.Release-Net48|Any CPU.Build.0 = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net45|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net45|Any CPU.Build.0 = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net462|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net462|Any CPU.Build.0 = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net47|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net47|Any CPU.Build.0 = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net48|Any CPU.ActiveCfg = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Debug-Net48|Any CPU.Build.0 = Debug-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net45|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net45|Any CPU.Build.0 = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net462|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net462|Any CPU.Build.0 = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net47|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net47|Any CPU.Build.0 = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net48|Any CPU.ActiveCfg = Release-Net48|Any CPU + {9A7B52E6-94BB-4E7E-BB6A-7CF6761B79A7}.Release-Net48|Any CPU.Build.0 = Release-Net48|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/HandyControl_Net_GE45.sln.DotSettings b/src/HandyControl_Net_GE45.sln.DotSettings deleted file mode 100644 index df567fc2..00000000 --- a/src/HandyControl_Net_GE45.sln.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - True \ No newline at end of file diff --git a/src/Net_40/HandyControlDemo_Net_40/HandyControlDemo_Net_40.csproj b/src/Net_40/HandyControlDemo_Net_40/HandyControlDemo_Net_40.csproj index f6f98c80..61536a9e 100644 --- a/src/Net_40/HandyControlDemo_Net_40/HandyControlDemo_Net_40.csproj +++ b/src/Net_40/HandyControlDemo_Net_40/HandyControlDemo_Net_40.csproj @@ -395,6 +395,9 @@ TextTemplatingFileGenerator MessageToken.cs + + Resources\Img\LeftMainContent\brackets_Square_16xLG.png + Resources\Img\LeftMainContent\GridPane_16x.png diff --git a/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj b/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj index 37f8abfd..b301587b 100644 --- a/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj +++ b/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj @@ -16,17 +16,6 @@ - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - v4.6.2 - AnyCPU true @@ -38,15 +27,16 @@ 4 v4.7 - + AnyCPU - pdbonly - true - bin\Release\ - TRACE + true + full + false + bin\Debug\ + DEBUG;TRACE prompt 4 - v4.6.2 + v4.8 AnyCPU @@ -58,6 +48,16 @@ 4 v4.7 + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + v4.8 + ..\..\Shared\HandyControlDemo_Shared\Resources\Img\icon.ico @@ -414,6 +414,9 @@ TextTemplatingFileGenerator MessageToken.cs + + Resources\Img\LeftMainContent\brackets_Square_16xLG.png + Resources\Img\LeftMainContent\GridPane_16x.png diff --git a/src/Net_GE45/HandyControl_Net_GE45/HandyControl_Net_GE45.csproj b/src/Net_GE45/HandyControl_Net_GE45/HandyControl_Net_GE45.csproj index fa66936d..c1f090f3 100644 --- a/src/Net_GE45/HandyControl_Net_GE45/HandyControl_Net_GE45.csproj +++ b/src/Net_GE45/HandyControl_Net_GE45/HandyControl_Net_GE45.csproj @@ -14,6 +14,17 @@ + + true + full + false + bin\Debug\ + DEBUG;TRACE;netle45 + prompt + 4 + v4.5 + netgt40 + true full @@ -36,14 +47,25 @@ v4.7 netgt40 - + true full false bin\Debug\ - DEBUG;TRACE;netle45 + DEBUG;TRACE prompt 4 + v4.8 + netgt40 + + + pdbonly + true + bin\Release\ + TRACE;netle45 + prompt + 4 + bin\Release\HandyControl.xml v4.5 netgt40 @@ -69,15 +91,15 @@ v4.7 netgt40 - + pdbonly true bin\Release\ - TRACE;netle45 + TRACE prompt 4 bin\Release\HandyControl.xml - v4.5 + v4.8 netgt40 diff --git a/src/Shared/HandyControlDemo_Shared/Data/MessageToken.cs b/src/Shared/HandyControlDemo_Shared/Data/MessageToken.cs index 6c8afdee..10cb3212 100644 --- a/src/Shared/HandyControlDemo_Shared/Data/MessageToken.cs +++ b/src/Shared/HandyControlDemo_Shared/Data/MessageToken.cs @@ -96,6 +96,8 @@ public static readonly string GridDemoCtl = nameof(GridDemoCtl); + public static readonly string RangeSliderDemoCtl = nameof(RangeSliderDemoCtl); + public static readonly string ButtonDemoCtl = nameof(ButtonDemoCtl); public static readonly string RepeatButtonDemoCtl = nameof(RepeatButtonDemoCtl); diff --git a/src/Shared/HandyControlDemo_Shared/Data/MessageToken.tt b/src/Shared/HandyControlDemo_Shared/Data/MessageToken.tt index be30c7f5..23421817 100644 --- a/src/Shared/HandyControlDemo_Shared/Data/MessageToken.tt +++ b/src/Shared/HandyControlDemo_Shared/Data/MessageToken.tt @@ -50,7 +50,8 @@ var controlList = new List "GravatarDemoCtl", "DialogDemoCtl", "SideMenuDemoCtl", - "GridDemoCtl" + "GridDemoCtl", + "RangeSliderDemoCtl" }; var styleList = new List { diff --git a/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems b/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems index 0671a61b..421dc7aa 100644 --- a/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems +++ b/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems @@ -25,7 +25,6 @@ Code MainWindow.xaml - @@ -48,6 +47,9 @@ AnimationPathDemoCtl.xaml + + RangeSliderDemoCtl.xaml + BadgeDemoCtl.xaml @@ -396,6 +398,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -747,4 +753,9 @@ MSBuild:Compile + + + RangeSliderDemoCtl.xaml + + \ No newline at end of file diff --git a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.Designer.cs b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.Designer.cs index eebfd40f..84333b73 100644 --- a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.Designer.cs +++ b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.Designer.cs @@ -19,7 +19,7 @@ namespace HandyControlDemo.Properties.Langs { // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Lang { @@ -1077,6 +1077,15 @@ namespace HandyControlDemo.Properties.Langs { } } + /// + /// 查找类似 范围滑块 的本地化字符串。 + /// + public static string RangeSlider { + get { + return ResourceManager.GetString("RangeSlider", resourceCulture); + } + } + /// /// 查找类似 评分 的本地化字符串。 /// diff --git a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.en.resx b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.en.resx index e63fd4e1..fa60bc80 100644 --- a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.en.resx +++ b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.en.resx @@ -606,4 +606,7 @@ Project + + RangeSlider + \ No newline at end of file diff --git a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.resx b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.resx index aa50af7a..0869eed4 100644 --- a/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.resx +++ b/src/Shared/HandyControlDemo_Shared/Properties/Langs/Lang.resx @@ -606,4 +606,7 @@ 项目 + + 范围滑块 + \ No newline at end of file diff --git a/src/Shared/HandyControlDemo_Shared/Resources/Img/LeftMainContent/brackets_Square_16xLG.png b/src/Shared/HandyControlDemo_Shared/Resources/Img/LeftMainContent/brackets_Square_16xLG.png new file mode 100644 index 00000000..9d803920 Binary files /dev/null and b/src/Shared/HandyControlDemo_Shared/Resources/Img/LeftMainContent/brackets_Square_16xLG.png differ diff --git a/src/Shared/HandyControlDemo_Shared/Service/DataService.cs b/src/Shared/HandyControlDemo_Shared/Service/DataService.cs index 8587cd62..d48350b2 100644 --- a/src/Shared/HandyControlDemo_Shared/Service/DataService.cs +++ b/src/Shared/HandyControlDemo_Shared/Service/DataService.cs @@ -135,6 +135,12 @@ namespace HandyControlDemo.Service DisplayName = "AutumnBox", AvatarUri = "https://www.atmb.top/images/leaves.png", Link = "https://github.com/zsh2401/AutumnBox" + }, + new AvatarModel + { + DisplayName = "PandaX Studio", + AvatarUri = "https://raw.githubusercontent.com/aboutlong/pandaxstudio/master/pandax/pandax/source/image/logo.png", + Link = "https://github.com/aboutlong/pandaxstudio" } }; } diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RangeSliderDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RangeSliderDemoCtl.xaml new file mode 100644 index 00000000..0dd0f1b7 --- /dev/null +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RangeSliderDemoCtl.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RangeSliderDemoCtl.xaml.cs b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RangeSliderDemoCtl.xaml.cs new file mode 100644 index 00000000..afa112c1 --- /dev/null +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RangeSliderDemoCtl.xaml.cs @@ -0,0 +1,10 @@ +namespace HandyControlDemo.UserControl +{ + public partial class RangeSliderDemoCtl + { + public RangeSliderDemoCtl() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml index 68c9e290..be2ebe00 100644 --- a/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml @@ -335,7 +335,7 @@ - + @@ -380,6 +380,11 @@ + + + + + diff --git a/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverView.cs b/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverView.cs index 0e80402c..96c8bf46 100644 --- a/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverView.cs +++ b/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverView.cs @@ -135,7 +135,7 @@ namespace HandyControl.Controls public static readonly DependencyProperty ItemContentHeightProperty = DependencyProperty.Register( "ItemContentHeight", typeof(double), typeof(CoverView), new PropertyMetadata(ValueBoxes.Double300Box), - value => ValidateHelper.IsInRangeOfPosDouble(value, true)); + ValidateHelper.IsInRangeOfPosDoubleIncludeZero); public double ItemContentHeight { diff --git a/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverViewContent.cs b/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverViewContent.cs index eb7f3e8c..9cb74208 100644 --- a/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverViewContent.cs +++ b/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverViewContent.cs @@ -43,7 +43,7 @@ namespace HandyControl.Controls } internal static readonly DependencyProperty ManualHeightProperty = DependencyProperty.Register( - "ManualHeight", typeof(double), typeof(CoverViewContent), new PropertyMetadata(ValueBoxes.Double0Box), value => ValidateHelper.IsInRangeOfPosDouble(value, true)); + "ManualHeight", typeof(double), typeof(CoverViewContent), new PropertyMetadata(ValueBoxes.Double0Box), ValidateHelper.IsInRangeOfPosDoubleIncludeZero); internal double ManualHeight { @@ -53,7 +53,7 @@ namespace HandyControl.Controls public static readonly DependencyProperty ContentHeightProperty = DependencyProperty.Register( "ContentHeight", typeof(double), typeof(CoverViewContent), new PropertyMetadata(ValueBoxes.Double300Box), - value => ValidateHelper.IsInRangeOfPosDouble(value, true)); + ValidateHelper.IsInRangeOfPosDoubleIncludeZero); public double ContentHeight { diff --git a/src/Shared/HandyControl_Shared/Controls/Grid/Row.cs b/src/Shared/HandyControl_Shared/Controls/Grid/Row.cs index 155ed71b..e659178d 100644 --- a/src/Shared/HandyControl_Shared/Controls/Grid/Row.cs +++ b/src/Shared/HandyControl_Shared/Controls/Grid/Row.cs @@ -14,11 +14,9 @@ namespace HandyControl.Controls private double _maxChildDesiredHeight; public static readonly DependencyProperty GutterProperty = DependencyProperty.Register( - "Gutter", typeof(double), typeof(Row), new PropertyMetadata(ValueBoxes.Double0Box, null, OnGutterCoerce), OnGutterValidate); + "Gutter", typeof(double), typeof(Row), new PropertyMetadata(ValueBoxes.Double0Box, null, OnGutterCoerce), ValidateHelper.IsInRangeOfPosDoubleIncludeZero); - private static object OnGutterCoerce(DependencyObject d, object basevalue) => OnGutterValidate(basevalue) ? basevalue : .0; - - private static bool OnGutterValidate(object value) => ValidateHelper.IsInRangeOfPosDouble(value, true); + private static object OnGutterCoerce(DependencyObject d, object basevalue) => ValidateHelper.IsInRangeOfPosDoubleIncludeZero(basevalue) ? basevalue : .0; public double Gutter { @@ -44,8 +42,6 @@ namespace HandyControl.Controls } } - var itemWidth = constraint.Width / ColLayout.ColMaxCellCount; - var childBounds = new Rect(-gutterHalf, -gutterHalf, 0, _maxChildDesiredHeight); _layoutStatus = ColLayout.GetLayoutStatus(constraint.Width); foreach (var child in InternalChildren.OfType()) @@ -55,15 +51,9 @@ namespace HandyControl.Controls if (totalCellCount > ColLayout.ColMaxCellCount) { - childBounds.X = -gutterHalf; - childBounds.Y += _maxChildDesiredHeight; totalCellCount = cellCount; totalRowCount++; } - - var childWidth = cellCount * itemWidth; - childBounds.Width = childWidth; - childBounds.X += childWidth + child.Offset * itemWidth; } return new Size(0, _maxChildDesiredHeight * totalRowCount - Gutter); diff --git a/src/Shared/HandyControl_Shared/Controls/Input/NumericUpDown.cs b/src/Shared/HandyControl_Shared/Controls/Input/NumericUpDown.cs index fa59e270..df9f0c73 100644 --- a/src/Shared/HandyControl_Shared/Controls/Input/NumericUpDown.cs +++ b/src/Shared/HandyControl_Shared/Controls/Input/NumericUpDown.cs @@ -153,7 +153,7 @@ namespace HandyControl.Controls public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, - OnValueChanged, CoerceValue), ArithmeticHelper.IsValidDoubleValue); + OnValueChanged, CoerceValue), ValidateHelper.IsInRangeOfDouble); private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { @@ -208,7 +208,7 @@ namespace HandyControl.Controls /// 最大值 /// public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register( - "Maximum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(double.MaxValue, OnMaximumChanged, CoerceMaximum), ArithmeticHelper.IsValidDoubleValue); + "Maximum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(double.MaxValue, OnMaximumChanged, CoerceMaximum), ValidateHelper.IsInRangeOfDouble); private static void OnMaximumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { @@ -236,7 +236,7 @@ namespace HandyControl.Controls /// 最小值 /// public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register( - "Minimum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(ValueBoxes.Double0Box, OnMinimumChanged, CoerceMinimum), ArithmeticHelper.IsValidDoubleValue); + "Minimum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(ValueBoxes.Double0Box, OnMinimumChanged, CoerceMinimum), ValidateHelper.IsInRangeOfDouble); private static void OnMinimumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { diff --git a/src/Shared/HandyControl_Shared/Controls/Slider/CompareSlider.cs b/src/Shared/HandyControl_Shared/Controls/Slider/CompareSlider/CompareSlider.cs similarity index 99% rename from src/Shared/HandyControl_Shared/Controls/Slider/CompareSlider.cs rename to src/Shared/HandyControl_Shared/Controls/Slider/CompareSlider/CompareSlider.cs index 23ff9a43..dc2ac997 100644 --- a/src/Shared/HandyControl_Shared/Controls/Slider/CompareSlider.cs +++ b/src/Shared/HandyControl_Shared/Controls/Slider/CompareSlider/CompareSlider.cs @@ -1,7 +1,6 @@ using System.Windows; using System.Windows.Controls; - namespace HandyControl.Controls { public class CompareSlider : Slider diff --git a/src/Shared/HandyControl_Shared/Controls/Slider/CompareTrack.cs b/src/Shared/HandyControl_Shared/Controls/Slider/CompareSlider/CompareTrack.cs similarity index 100% rename from src/Shared/HandyControl_Shared/Controls/Slider/CompareTrack.cs rename to src/Shared/HandyControl_Shared/Controls/Slider/CompareSlider/CompareTrack.cs diff --git a/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeSlider.cs b/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeSlider.cs new file mode 100644 index 00000000..4250b29a --- /dev/null +++ b/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeSlider.cs @@ -0,0 +1,653 @@ +// Adapted from https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Slider.cs + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using HandyControl.Data; +using HandyControl.Expression.Drawing; +using HandyControl.Tools; + +namespace HandyControl.Controls +{ + [DefaultEvent("ValueChanged"), DefaultProperty("Value")] + [TemplatePart(Name = ElementTrack, Type = typeof(Track))] + public class RangeSlider : TwoWayRangeBase + { + private const string ElementTrack= "PART_Track"; + + private RangeTrack _track; + + private readonly ToolTip _autoToolTipStart = null; + + private readonly ToolTip _autoToolTipEnd = null; + + private RangeThumb _thumbCurrent; + + private object _thumbOriginalToolTip; + + private Point _originThumbPoint; + + private Point _previousScreenCoordPosition; + + static RangeSlider() + { + InitializeCommands(); + + MinimumProperty.OverrideMetadata(typeof(RangeSlider), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsMeasure)); + MaximumProperty.OverrideMetadata(typeof(RangeSlider), new FrameworkPropertyMetadata(ValueBoxes.Double10Box, FrameworkPropertyMetadataOptions.AffectsMeasure)); + ValueStartProperty.OverrideMetadata(typeof(RangeSlider), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsMeasure)); + ValueEndProperty.OverrideMetadata(typeof(RangeSlider), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsMeasure)); + + // Register Event Handler for the Thumb + EventManager.RegisterClassHandler(typeof(RangeSlider), Thumb.DragStartedEvent, new DragStartedEventHandler(OnThumbDragStarted)); + EventManager.RegisterClassHandler(typeof(RangeSlider), Thumb.DragDeltaEvent, new DragDeltaEventHandler(OnThumbDragDelta)); + EventManager.RegisterClassHandler(typeof(RangeSlider), Thumb.DragCompletedEvent, new DragCompletedEventHandler(OnThumbDragCompleted)); + + // Listen to MouseLeftButtonDown event to determine if slide should move focus to itself + EventManager.RegisterClassHandler(typeof(RangeSlider), Mouse.MouseDownEvent, new MouseButtonEventHandler(OnMouseLeftButtonDown), true); + } + + public RangeSlider() + { + CommandBindings.Add(new CommandBinding(IncreaseLarge, OnIncreaseLarge)); + CommandBindings.Add(new CommandBinding(IncreaseSmall, OnIncreaseSmall)); + + CommandBindings.Add(new CommandBinding(DecreaseLarge, OnDecreaseLarge)); + CommandBindings.Add(new CommandBinding(DecreaseSmall, OnDecreaseSmall)); + + CommandBindings.Add(new CommandBinding(CenterLarge, OnCenterLarge)); + CommandBindings.Add(new CommandBinding(CenterSmall, OnCenterSmall)); + } + + private void OnIncreaseLarge(object sender, ExecutedRoutedEventArgs e) => (sender as RangeSlider)?.OnIncreaseLarge(); + + private void OnIncreaseSmall(object sender, ExecutedRoutedEventArgs e) => (sender as RangeSlider)?.OnIncreaseSmall(); + + private void OnDecreaseLarge(object sender, ExecutedRoutedEventArgs e) => (sender as RangeSlider)?.OnDecreaseLarge(); + + private void OnDecreaseSmall(object sender, ExecutedRoutedEventArgs e) => (sender as RangeSlider)?.OnDecreaseSmall(); + + private void OnCenterLarge(object sender, ExecutedRoutedEventArgs e) => (sender as RangeSlider)?.OnCenterLarge(e.Parameter); + + private void OnCenterSmall(object sender, ExecutedRoutedEventArgs e) => (sender as RangeSlider)?.OnCenterSmall(e.Parameter); + + protected virtual void OnIncreaseLarge() => MoveToNextTick(LargeChange, false); + + protected virtual void OnIncreaseSmall() => MoveToNextTick(LargeChange, false); + + protected virtual void OnDecreaseLarge() => MoveToNextTick(-LargeChange, true); + + protected virtual void OnDecreaseSmall() => MoveToNextTick(-LargeChange, true); + + protected virtual void OnCenterLarge(object parameter) => MoveToNextTick(LargeChange, false, true); + + protected virtual void OnCenterSmall(object parameter) => MoveToNextTick(LargeChange, false, true); + + public static RoutedCommand IncreaseLarge { get; private set; } + + public static RoutedCommand IncreaseSmall { get; private set; } + + public static RoutedCommand DecreaseLarge { get; private set; } + + public static RoutedCommand DecreaseSmall { get; private set; } + + public static RoutedCommand CenterLarge { get; private set; } + + public static RoutedCommand CenterSmall { get; private set; } + + private static void InitializeCommands() + { + IncreaseLarge = new RoutedCommand(nameof(IncreaseLarge), typeof(RangeSlider)); + IncreaseSmall = new RoutedCommand(nameof(IncreaseSmall), typeof(RangeSlider)); + + DecreaseLarge = new RoutedCommand(nameof(DecreaseLarge), typeof(RangeSlider)); + DecreaseSmall = new RoutedCommand(nameof(DecreaseSmall), typeof(RangeSlider)); + + CenterLarge = new RoutedCommand(nameof(CenterLarge), typeof(RangeSlider)); + CenterSmall = new RoutedCommand(nameof(CenterSmall), typeof(RangeSlider)); + } + + public override void OnApplyTemplate() + { + _thumbCurrent = null; + + base.OnApplyTemplate(); + + _track = GetTemplateChild(ElementTrack) as RangeTrack; + + if (_autoToolTipStart != null) + { + _autoToolTipStart.PlacementTarget = _track?.ThumbStart; + } + + if (_autoToolTipEnd != null) + { + _autoToolTipEnd.PlacementTarget = _track?.ThumbEnd; + } + } + + public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register( + "Orientation", typeof(Orientation), typeof(RangeSlider), new PropertyMetadata(default(Orientation))); + + public Orientation Orientation + { + get => (Orientation)GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + + public static readonly DependencyProperty IsDirectionReversedProperty = DependencyProperty.Register( + "IsDirectionReversed", typeof(bool), typeof(RangeSlider), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool IsDirectionReversed + { + get => (bool)GetValue(IsDirectionReversedProperty); + set => SetValue(IsDirectionReversedProperty, value); + } + + public static readonly DependencyProperty DelayProperty = RepeatButton.DelayProperty.AddOwner(typeof(RangeSlider), new FrameworkPropertyMetadata(GetKeyboardDelay())); + + public int Delay + { + get => (int)GetValue(DelayProperty); + set => SetValue(DelayProperty, value); + } + + internal static int GetKeyboardDelay() + { + var delay = SystemParameters.KeyboardDelay; + if (delay < 0 || delay > 3) + delay = 0; + return (delay + 1) * 250; + } + + public static readonly DependencyProperty IntervalProperty = RepeatButton.IntervalProperty.AddOwner(typeof(RangeSlider), new FrameworkPropertyMetadata(GetKeyboardSpeed())); + + public int Interval + { + get => (int)GetValue(IntervalProperty); + set => SetValue(IntervalProperty, value); + } + + internal static int GetKeyboardSpeed() + { + var speed = SystemParameters.KeyboardSpeed; + if (speed < 0 || speed > 31) + speed = 31; + return (31 - speed) * (400 - 1000 / 30) / 31 + 1000 / 30; + } + + public static readonly DependencyProperty AutoToolTipPlacementProperty = DependencyProperty.Register( + "AutoToolTipPlacement", typeof(AutoToolTipPlacement), typeof(RangeSlider), new PropertyMetadata(default(AutoToolTipPlacement))); + + public AutoToolTipPlacement AutoToolTipPlacement + { + get => (AutoToolTipPlacement)GetValue(AutoToolTipPlacementProperty); + set => SetValue(AutoToolTipPlacementProperty, value); + } + + public static readonly DependencyProperty AutoToolTipPrecisionProperty = DependencyProperty.Register( + "AutoToolTipPrecision", typeof(int), typeof(RangeSlider), new PropertyMetadata(ValueBoxes.Int0Box), + ValidateHelper.IsInRangeOfPosIntIncludeZero); + + public int AutoToolTipPrecision + { + get => (int)GetValue(AutoToolTipPrecisionProperty); + set => SetValue(AutoToolTipPrecisionProperty, value); + } + + public static readonly DependencyProperty IsSnapToTickEnabledProperty = DependencyProperty.Register( + "IsSnapToTickEnabled", typeof(bool), typeof(RangeSlider), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool IsSnapToTickEnabled + { + get => (bool)GetValue(IsSnapToTickEnabledProperty); + set => SetValue(IsSnapToTickEnabledProperty, value); + } + + public static readonly DependencyProperty TickPlacementProperty = DependencyProperty.Register( + "TickPlacement", typeof(TickPlacement), typeof(RangeSlider), new PropertyMetadata(default(TickPlacement))); + + public TickPlacement TickPlacement + { + get => (TickPlacement)GetValue(TickPlacementProperty); + set => SetValue(TickPlacementProperty, value); + } + + public static readonly DependencyProperty TickFrequencyProperty = DependencyProperty.Register( + "TickFrequency", typeof(double), typeof(RangeSlider), new PropertyMetadata(ValueBoxes.Double1Box), + ValidateHelper.IsInRangeOfPosDoubleIncludeZero); + + public double TickFrequency + { + get => (double)GetValue(TickFrequencyProperty); + set => SetValue(TickFrequencyProperty, value); + } + + public static readonly DependencyProperty TicksProperty = DependencyProperty.Register( + "Ticks", typeof(DoubleCollection), typeof(RangeSlider), new PropertyMetadata(new DoubleCollection())); + + public DoubleCollection Ticks + { + get => (DoubleCollection)GetValue(TicksProperty); + set => SetValue(TicksProperty, value); + } + + public static readonly DependencyProperty IsMoveToPointEnabledProperty = DependencyProperty.Register( + "IsMoveToPointEnabled", typeof(bool), typeof(RangeSlider), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool IsMoveToPointEnabled + { + get => (bool)GetValue(IsMoveToPointEnabledProperty); + set => SetValue(IsMoveToPointEnabledProperty, value); + } + + protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) + { + if (IsMoveToPointEnabled && _track.ThumbStart != null && !_track.ThumbStart.IsMouseOver && _track.ThumbEnd != null && !_track.ThumbEnd.IsMouseOver) + { + // Here we need to determine whether it's closer to the starting point or the end point. + var pt = e.MouseDevice.GetPosition(_track); + UpdateValue(pt); + e.Handled = true; + } + + base.OnPreviewMouseLeftButtonDown(e); + } + + private void MoveToNextTick(double direction, bool isStart, bool isCenter = false, object parameter = null) + { + if (MathHelper.AreClose(direction, 0)) return; + + if (isCenter) + { + if (parameter == null) + { + var pt = Mouse.GetPosition(_track); + var newValue = _track.ValueFromPoint(pt); + if (ValidateHelper.IsInRangeOfDouble(newValue)) + { + var dir = (ValueStart + ValueEnd) / 2 > newValue; + if (!dir) + { + isStart = false; + direction = -Math.Abs(direction); + } + else + { + isStart = true; + } + } + } + + if (parameter is bool parameterValue) + { + isStart = parameterValue; + } + } + + var value = isStart ? ValueStart : ValueEnd; + var next = SnapToTick(Math.Max(Minimum, Math.Min(Maximum, value + direction))); + var greaterThan = direction > 0; + + // If the snapping brought us back to value, find the next tick point + if (MathHelper.AreClose(next, value) && + !(greaterThan && MathHelper.AreClose(value, Maximum)) && + !(!greaterThan && MathHelper.AreClose(value, Minimum))) + { + // If ticks collection is available, use it. + // Note that ticks may be unsorted. + if (Ticks != null && Ticks.Count > 0) + { + foreach (var tick in Ticks) + { + // Find the smallest tick greater than value or the largest tick less than value + if (greaterThan && MathHelper.GreaterThan(tick, value) && (MathHelper.LessThan(tick, next) || MathHelper.AreClose(next, value)) + || !greaterThan && MathHelper.LessThan(tick, value) && (MathHelper.GreaterThan(tick, next) || MathHelper.AreClose(next, value))) + { + next = tick; + } + } + } + else if (MathHelper.GreaterThan(TickFrequency, 0.0)) + { + // Find the current tick we are at + var tickNumber = Math.Round((value - Minimum) / TickFrequency); + + if (greaterThan) + tickNumber += 1.0; + else + tickNumber -= 1.0; + + next = Minimum + tickNumber * TickFrequency; + } + } + + // Update if we've found a better value + if (!MathHelper.AreClose(next, value)) + { + SetCurrentValue(isStart ? ValueStartProperty : ValueEndProperty, next); + } + } + + private double SnapToTick(double value) + { + if (!IsSnapToTickEnabled) return value; + + var previous = Minimum; + var next = Maximum; + + if (Ticks != null && Ticks.Count > 0) + { + foreach (var tick in Ticks) + { + if (MathHelper.AreClose(tick, value)) + { + return value; + } + + if (MathHelper.LessThan(tick, value) && MathHelper.GreaterThan(tick, previous)) + { + previous = tick; + } + else if (MathHelper.GreaterThan(tick, value) && MathHelper.LessThan(tick, next)) + { + next = tick; + } + } + } + else if (MathHelper.GreaterThan(TickFrequency, 0.0)) + { + previous = Minimum + Math.Round((value - Minimum) / TickFrequency) * TickFrequency; + next = Math.Min(Maximum, previous + TickFrequency); + } + + return MathHelper.GreaterThanOrClose(value, (previous + next) * 0.5) ? next : previous; + } + + private void UpdateValue(Point point) + { + var newValue = _track.ValueFromPoint(point); + if (ValidateHelper.IsInRangeOfDouble(newValue)) + { + var isStart = (ValueStart + ValueEnd) / 2 > newValue; + UpdateValue(newValue, isStart); + } + } + + private void UpdateValue(double value, bool isStart) + { + var snappedValue = SnapToTick(value); + + if (isStart) + { + if (!MathHelper.AreClose(snappedValue, ValueStart)) + { + var start = Math.Max(Minimum, Math.Min(Maximum, snappedValue)); + if (start > ValueEnd) + { + SetCurrentValue(ValueEndProperty, start); + _track.ThumbStart.CancelDrag(); + _track.ThumbEnd.StartDrag(); + _thumbCurrent = _track.ThumbEnd; + } + else + { + SetCurrentValue(ValueStartProperty, start); + } + } + } + else + { + if (!MathHelper.AreClose(snappedValue, ValueEnd)) + { + var end = Math.Max(Minimum, Math.Min(Maximum, snappedValue)); + if (end < ValueStart) + { + SetCurrentValue(ValueStartProperty, end); + _track.ThumbEnd.CancelDrag(); + _track.ThumbStart.StartDrag(); + _thumbCurrent = _track.ThumbStart; + } + else + { + SetCurrentValue(ValueEndProperty, end); + } + } + } + } + + private static void OnThumbDragStarted(object sender, DragStartedEventArgs e) => (sender as RangeSlider)?.OnThumbDragStarted(e); + + protected virtual void OnThumbDragStarted(DragStartedEventArgs e) + { + // Show AutoToolTip if needed. + + if (!(e.OriginalSource is RangeThumb thumb)) return; + _thumbCurrent = thumb; + _originThumbPoint = Mouse.GetPosition(_thumbCurrent); + _thumbCurrent.StartDrag(); + + if (AutoToolTipPlacement == AutoToolTipPlacement.None) + { + return; + } + + var isStart = thumb.Equals(_track.ThumbStart); + if (!isStart) + { + if (!thumb.Equals(_track.ThumbEnd)) return; + } + + // Save original tooltip + _thumbOriginalToolTip = thumb.ToolTip; + OnThumbDragStarted(isStart ? _autoToolTipStart : _autoToolTipEnd, isStart); + } + + private void OnThumbDragStarted(ToolTip toolTip, bool isStart) + { + if (toolTip == null) + { + toolTip = new ToolTip + { + Placement = PlacementMode.Custom, + PlacementTarget = isStart ? _track.ThumbStart : _track.ThumbEnd, + CustomPopupPlacementCallback = AutoToolTipCustomPlacementCallback + }; + } + + if (isStart) + { + _track.ThumbStart.ToolTip = toolTip; + } + else + { + _track.ThumbEnd.ToolTip = toolTip; + } + toolTip.Content = GetAutoToolTipNumber(isStart); + toolTip.IsOpen = true; + } + + private CustomPopupPlacement[] AutoToolTipCustomPlacementCallback(Size popupSize, Size targetSize, Point offset) + { + switch (AutoToolTipPlacement) + { + case AutoToolTipPlacement.TopLeft: + if (Orientation == Orientation.Horizontal) + { + // Place popup at top of thumb + return new[]{new CustomPopupPlacement( + new Point((targetSize.Width - popupSize.Width) * 0.5, -popupSize.Height), + PopupPrimaryAxis.Horizontal) + }; + } + else + { + // Place popup at left of thumb + return new[] { + new CustomPopupPlacement( + new Point(-popupSize.Width, (targetSize.Height - popupSize.Height) * 0.5), + PopupPrimaryAxis.Vertical) + }; + } + + case AutoToolTipPlacement.BottomRight: + if (Orientation == Orientation.Horizontal) + { + // Place popup at bottom of thumb + return new[] { + new CustomPopupPlacement( + new Point((targetSize.Width - popupSize.Width) * 0.5, targetSize.Height) , + PopupPrimaryAxis.Horizontal) + }; + + } + else + { + // Place popup at right of thumb + return new[] { + new CustomPopupPlacement( + new Point(targetSize.Width, (targetSize.Height - popupSize.Height) * 0.5), + PopupPrimaryAxis.Vertical) + }; + } + + default: + return new CustomPopupPlacement[] { }; + } + } + + private string GetAutoToolTipNumber(bool isStart) + { + var format = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone(); + format.NumberDecimalDigits = AutoToolTipPrecision; + return isStart ? ValueStart.ToString("N", format) : ValueEnd.ToString("N", format); + } + + private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e) => (sender as RangeSlider)?.OnThumbDragDelta(e); + + protected virtual void OnThumbDragDelta(DragDeltaEventArgs e) + { + if (!(e.OriginalSource is Thumb thumb)) return; + var isStart = thumb.Equals(_track.ThumbStart); + if (!isStart) + { + if (!thumb.Equals(_track.ThumbEnd)) return; + } + + // Convert to Track's co-ordinate + OnThumbDragDelta(_track, isStart, e); + } + + private void OnThumbDragDelta(RangeTrack track, bool isStart, DragDeltaEventArgs e) + { + if (track == null || track.ThumbStart == null | _track.ThumbEnd == null) return; + + var newValue = (isStart ? ValueStart : ValueEnd) + track.ValueFromDistance(e.HorizontalChange, e.VerticalChange); + if (ValidateHelper.IsInRangeOfDouble(newValue)) + { + UpdateValue(newValue, isStart); + } + + // Show AutoToolTip if needed + if (AutoToolTipPlacement != AutoToolTipPlacement.None) + { + var toolTip = (isStart ? _autoToolTipStart : _autoToolTipEnd) ?? new ToolTip(); + + toolTip.Content = GetAutoToolTipNumber(isStart); + + var thumb = isStart ? _track.ThumbStart : _track.ThumbEnd; + + if (!Equals(thumb.ToolTip, toolTip)) + { + thumb.ToolTip = toolTip; + } + + if (!toolTip.IsOpen) + { + toolTip.IsOpen = true; + } + } + } + + private static void OnThumbDragCompleted(object sender, DragCompletedEventArgs e) => (sender as RangeSlider)?.OnThumbDragCompleted(e); + + protected virtual void OnThumbDragCompleted(DragCompletedEventArgs e) + { + // Show AutoToolTip if needed. + + if (!(e.OriginalSource is Thumb thumb) || AutoToolTipPlacement == AutoToolTipPlacement.None) + { + return; + } + + var isStart = thumb.Equals(_track.ThumbStart); + if (!isStart) + { + if (!thumb.Equals(_track.ThumbEnd)) return; + } + + var toolTip = isStart ? _autoToolTipStart : _autoToolTipEnd; + if (toolTip != null) + { + toolTip.IsOpen = false; + } + + thumb.ToolTip = _thumbOriginalToolTip; + } + + private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + if (e.ChangedButton != MouseButton.Left) return; + + var slider = (RangeSlider)sender; + + // When someone click on the Slider's part, and it's not focusable + // Slider need to take the focus in order to process keyboard correctly + if (!slider.IsKeyboardFocusWithin) + { + e.Handled = slider.Focus() || e.Handled; + } + + if (slider._track.ThumbStart.IsMouseOver) + { + slider._track.ThumbStart.StartDrag(); + slider._thumbCurrent = slider._track.ThumbStart; + } + + if (slider._track.ThumbEnd.IsMouseOver) + { + slider._track.ThumbEnd.StartDrag(); + slider._thumbCurrent = slider._track.ThumbEnd; + } + } + + protected override void OnMouseMove(MouseEventArgs e) + { + if (_thumbCurrent == null) return; + if (e.MouseDevice.LeftButton != MouseButtonState.Pressed) return; + + if (!_thumbCurrent.IsDragging) return; + + var thumbCoordPosition = e.GetPosition(_thumbCurrent); + var screenCoordPosition = PointFromScreen(thumbCoordPosition); + if (screenCoordPosition != _previousScreenCoordPosition) + { + _previousScreenCoordPosition = screenCoordPosition; + _thumbCurrent.RaiseEvent(new DragDeltaEventArgs(thumbCoordPosition.X - _originThumbPoint.X, + thumbCoordPosition.Y - _originThumbPoint.Y)); + } + } + + protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnPreviewMouseLeftButtonUp(e); + + _thumbCurrent = null; + } + } +} \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeThumb.cs b/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeThumb.cs new file mode 100644 index 00000000..fee42007 --- /dev/null +++ b/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeThumb.cs @@ -0,0 +1,46 @@ +using System; +using System.Windows; +using System.Windows.Controls.Primitives; +using System.Windows.Input; + +namespace HandyControl.Controls +{ + public class RangeThumb : Thumb + { + public static readonly DependencyProperty ContentProperty = DependencyProperty.Register( + "Content", typeof(object), typeof(RangeThumb), new PropertyMetadata(default(object))); + + public object Content + { + get => GetValue(ContentProperty); + set => SetValue(ContentProperty, value); + } + + protected override void OnMouseMove(MouseEventArgs e) + { + + } + + public void StartDrag() + { + IsDragging = true; + Focus(); + CaptureMouse(); + RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left) + { + RoutedEvent = PreviewMouseLeftButtonDownEvent, + Source = this + }); + } + + public new void CancelDrag() + { + base.CancelDrag(); + + RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left) + { + RoutedEvent = PreviewMouseLeftButtonUpEvent + }); + } + } +} \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeTrack.cs b/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeTrack.cs new file mode 100644 index 00000000..99e4dfad --- /dev/null +++ b/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/RangeTrack.cs @@ -0,0 +1,444 @@ +// Adapted from https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Primitives/Track.cs + +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using HandyControl.Data; + +namespace HandyControl.Controls +{ + public class RangeTrack : FrameworkElement + { + private RepeatButton _increaseButton; + + private RepeatButton _centerButton; + + private RepeatButton _decreaseButton; + + private RangeThumb _thumbStart; + + private RangeThumb _thumbEnd; + + private Visual[] _visualChildren; + + private double Density { get; set; } = double.NaN; + + private double ThumbStartCenterOffset { get; set; } = double.NaN; + + public RepeatButton DecreaseRepeatButton + { + get => _decreaseButton; + set + { + if (Equals(_increaseButton, value) || Equals(_centerButton, value)) + { + throw new NotSupportedException("SameButtons"); + } + UpdateComponent(_decreaseButton, value); + _decreaseButton = value; + + if (_decreaseButton != null) + { + CommandManager.InvalidateRequerySuggested(); // Should post an idle queue item to update IsEnabled on button + } + } + } + + public RepeatButton CenterRepeatButton + { + get => _centerButton; + set + { + if (Equals(_increaseButton, value) || Equals(_decreaseButton, value)) + { + throw new NotSupportedException("SameButtons"); + } + UpdateComponent(_centerButton, value); + _centerButton = value; + + if (_centerButton != null) + { + CommandManager.InvalidateRequerySuggested(); // Should post an idle queue item to update IsEnabled on button + } + } + } + + public RepeatButton IncreaseRepeatButton + { + get => _increaseButton; + set + { + if (Equals(_decreaseButton, value) || Equals(_centerButton, value)) + { + throw new NotSupportedException("SameButtons"); + } + UpdateComponent(_increaseButton, value); + _increaseButton = value; + + if (_increaseButton != null) + { + CommandManager.InvalidateRequerySuggested(); // Should post an idle queue item to update IsEnabled on button + } + } + } + + public RangeThumb ThumbStart + { + get => _thumbStart; + set + { + UpdateComponent(_thumbStart, value); + _thumbStart = value; + } + } + + public RangeThumb ThumbEnd + { + get => _thumbEnd; + set + { + UpdateComponent(_thumbEnd, value); + _thumbEnd = value; + } + } + + static RangeTrack() + { + IsEnabledProperty.OverrideMetadata(typeof(RangeTrack), new UIPropertyMetadata(OnIsEnabledChanged)); + } + + public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register( + "Orientation", typeof(Orientation), typeof(RangeTrack), + new FrameworkPropertyMetadata(default(Orientation), FrameworkPropertyMetadataOptions.AffectsMeasure)); + + public Orientation Orientation + { + get => (Orientation) GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + + public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register( + "Minimum", typeof(double), typeof(RangeTrack), + new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsArrange)); + + public double Minimum + { + get => (double) GetValue(MinimumProperty); + set => SetValue(MinimumProperty, value); + } + + public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register( + "Maximum", typeof(double), typeof(RangeTrack), + new FrameworkPropertyMetadata(ValueBoxes.Double1Box, FrameworkPropertyMetadataOptions.AffectsArrange)); + + public double Maximum + { + get => (double) GetValue(MaximumProperty); + set => SetValue(MaximumProperty, value); + } + + public static readonly DependencyProperty ValueStartProperty = DependencyProperty.Register( + "ValueStart", typeof(double), typeof(RangeTrack), + new FrameworkPropertyMetadata(ValueBoxes.Double0Box, + FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | + FrameworkPropertyMetadataOptions.AffectsArrange)); + + public double ValueStart + { + get => (double) GetValue(ValueStartProperty); + set => SetValue(ValueStartProperty, value); + } + + public static readonly DependencyProperty ValueEndProperty = DependencyProperty.Register( + "ValueEnd", typeof(double), typeof(RangeTrack), + new FrameworkPropertyMetadata(ValueBoxes.Double0Box, + FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | + FrameworkPropertyMetadataOptions.AffectsArrange)); + + public double ValueEnd + { + get => (double) GetValue(ValueEndProperty); + set => SetValue(ValueEndProperty, value); + } + + public static readonly DependencyProperty IsDirectionReversedProperty = DependencyProperty.Register( + "IsDirectionReversed", typeof(bool), typeof(RangeTrack), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool IsDirectionReversed + { + get => (bool) GetValue(IsDirectionReversedProperty); + set => SetValue(IsDirectionReversedProperty, value); + } + + protected override Visual GetVisualChild(int index) + { + if (_visualChildren?[index] == null) + { + // ReSharper disable once UseNameofExpression + // ReSharper disable once LocalizableElement + throw new ArgumentOutOfRangeException("index", index, "ArgumentOutOfRange"); + } + return _visualChildren[index]; + } + + protected override Size MeasureOverride(Size availableSize) + { + var desiredSize = new Size(); + + // Only measure thumb + // Repeat buttons will be sized based on thumb + if (_thumbStart != null) + { + _thumbStart.Measure(availableSize); + desiredSize = _thumbStart.DesiredSize; + } + + if (_thumbEnd != null) + { + _thumbEnd.Measure(availableSize); + desiredSize = new Size(Math.Max(_thumbEnd.DesiredSize.Width, desiredSize.Width), + Math.Max(_thumbEnd.DesiredSize.Height, desiredSize.Height)); + } + + return desiredSize; + } + + private static void CoerceLength(ref double componentLength, double trackLength) + { + if (componentLength < 0) + { + componentLength = 0; + } + else if (componentLength > trackLength || double.IsNaN(componentLength)) + { + componentLength = trackLength; + } + } + + protected override Size ArrangeOverride(Size arrangeSize) + { + var isVertical = Orientation == Orientation.Vertical; + + ComputeLengths(arrangeSize, isVertical, out var decreaseButtonLength, out var centerButtonLength, + out var increaseButtonLength, out var thumbStartLength, out var thumbEndLength); + + var offset = new Point(); + var pieceSize = arrangeSize; + var isDirectionReversed = IsDirectionReversed; + + if (isVertical) + { + CoerceLength(ref decreaseButtonLength, arrangeSize.Height); + CoerceLength(ref centerButtonLength, arrangeSize.Height); + CoerceLength(ref increaseButtonLength, arrangeSize.Height); + CoerceLength(ref thumbStartLength, arrangeSize.Height); + CoerceLength(ref thumbEndLength, arrangeSize.Height); + + offset.Y = isDirectionReversed ? decreaseButtonLength + thumbEndLength + centerButtonLength + thumbStartLength : 0; + pieceSize.Height = increaseButtonLength; + + IncreaseRepeatButton?.Arrange(new Rect(offset, pieceSize)); + + offset.Y = isDirectionReversed ? decreaseButtonLength + thumbEndLength : increaseButtonLength + thumbStartLength; + pieceSize.Height = centerButtonLength; + + CenterRepeatButton?.Arrange(new Rect(offset, pieceSize)); + + offset.Y = isDirectionReversed ? 0 : increaseButtonLength + thumbStartLength + centerButtonLength + thumbEndLength; + pieceSize.Height = decreaseButtonLength; + + DecreaseRepeatButton?.Arrange(new Rect(offset, pieceSize)); + + offset.Y = isDirectionReversed + ? decreaseButtonLength + thumbEndLength + centerButtonLength + : increaseButtonLength + thumbStartLength + centerButtonLength; + pieceSize.Height = thumbStartLength; + + ThumbStart?.Arrange(new Rect(offset, pieceSize)); + ThumbStartCenterOffset = offset.Y + thumbStartLength * 0.5; + + offset.Y = isDirectionReversed ? decreaseButtonLength : increaseButtonLength; + pieceSize.Height = thumbEndLength; + + ThumbEnd?.Arrange(new Rect(offset, pieceSize)); + } + else + { + CoerceLength(ref decreaseButtonLength, arrangeSize.Width); + CoerceLength(ref centerButtonLength, arrangeSize.Width); + CoerceLength(ref increaseButtonLength, arrangeSize.Width); + CoerceLength(ref thumbStartLength, arrangeSize.Width); + CoerceLength(ref thumbEndLength, arrangeSize.Width); + + offset.X = isDirectionReversed ? 0 : decreaseButtonLength + thumbEndLength + centerButtonLength + thumbStartLength; + pieceSize.Width = increaseButtonLength; + + IncreaseRepeatButton?.Arrange(new Rect(offset, pieceSize)); + + offset.X = isDirectionReversed ? increaseButtonLength + thumbStartLength : decreaseButtonLength + thumbEndLength; + pieceSize.Width = centerButtonLength; + + CenterRepeatButton?.Arrange(new Rect(offset, pieceSize)); + + offset.X = isDirectionReversed ? increaseButtonLength + thumbStartLength + centerButtonLength + thumbEndLength : 0; + pieceSize.Width = decreaseButtonLength; + + DecreaseRepeatButton?.Arrange(new Rect(offset, pieceSize)); + + offset.X = isDirectionReversed ? increaseButtonLength : decreaseButtonLength; + pieceSize.Width = thumbStartLength; + + ThumbStart?.Arrange(new Rect(offset, pieceSize)); + ThumbStartCenterOffset = offset.X + thumbStartLength * 0.5; + + offset.X = isDirectionReversed + ? increaseButtonLength + thumbStartLength + centerButtonLength + : decreaseButtonLength + thumbEndLength + centerButtonLength; + pieceSize.Width = thumbEndLength; + + ThumbEnd?.Arrange(new Rect(offset, pieceSize)); + } + + return arrangeSize; + } + + private void ComputeLengths(Size arrangeSize, bool isVertical, out double decreaseButtonLength, + out double centerButtonLength, out double increaseButtonLength, out double thumbStartLength, + out double thumbEndLength) + { + var min = Minimum; + var range = Math.Max(0.0, Maximum - min); + var offsetStart = Math.Min(range, ValueStart - min); + var offsetEnd = Math.Min(range, ValueEnd - min); + + double trackLength; + + // Compute thumb size + if (isVertical) + { + trackLength = arrangeSize.Height; + thumbStartLength = _thumbStart?.DesiredSize.Height ?? 0; + thumbEndLength = _thumbEnd?.DesiredSize.Height ?? 0; + } + else + { + trackLength = arrangeSize.Width; + thumbStartLength = _thumbStart?.DesiredSize.Width ?? 0; + thumbEndLength = _thumbEnd?.DesiredSize.Width ?? 0; + } + + CoerceLength(ref thumbStartLength, trackLength); + CoerceLength(ref thumbEndLength, trackLength); + + var remainingTrackLength = trackLength - thumbStartLength - thumbEndLength; + + decreaseButtonLength = remainingTrackLength * offsetStart / range; + CoerceLength(ref decreaseButtonLength, remainingTrackLength); + + centerButtonLength = remainingTrackLength * offsetEnd / range - decreaseButtonLength; + CoerceLength(ref centerButtonLength, remainingTrackLength); + + increaseButtonLength = remainingTrackLength - decreaseButtonLength - centerButtonLength; + CoerceLength(ref increaseButtonLength, remainingTrackLength); + + Density = range / remainingTrackLength; + } + + protected override int VisualChildrenCount + { + get + { + if (_visualChildren == null) return 0; + + for (int i = 0; i < _visualChildren.Length; i++) + { + if (_visualChildren[i] == null) return i; + } + + return _visualChildren.Length; + } + } + + private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if ((bool)e.NewValue) + { + Mouse.Synchronize(); + } + } + + public virtual double ValueFromPoint(Point pt) + { + double val; + // Find distance from center of thumb to given point. + if (Orientation == Orientation.Horizontal) + { + val = ValueStart + ValueFromDistance(pt.X - ThumbStartCenterOffset, pt.Y - RenderSize.Height * 0.5); + } + else + { + val = ValueStart + ValueFromDistance(pt.X - RenderSize.Width * 0.5, pt.Y - ThumbStartCenterOffset); + } + return Math.Max(Minimum, Math.Min(Maximum, val)); + } + + public virtual double ValueFromDistance(double horizontal, double vertical) + { + double scale = IsDirectionReversed ? -1 : 1; + return Orientation == Orientation.Horizontal + ? scale * horizontal * Density + : -1 * scale * vertical * Density; + } + + private void UpdateComponent(Control oldValue, Control newValue) + { + if (oldValue != newValue) + { + if (_visualChildren == null) + { + _visualChildren = new Visual[5]; + } + + if (oldValue != null) + { + // notify the visual layer that the old component has been removed. + RemoveVisualChild(oldValue); + } + + // Remove the old value from our z index list and add new value to end + int i = 0; + while (i < 5) + { + // Array isn't full, break + if (_visualChildren[i] == null) + break; + + // found the old value + if (_visualChildren[i] == oldValue) + { + // Move values down until end of array or a null element + while (i < 4 && _visualChildren[i + 1] != null) + { + _visualChildren[i] = _visualChildren[i + 1]; + i++; + } + } + else + { + i++; + } + } + // Add newValue at end of z-order + _visualChildren[i] = newValue; + + AddVisualChild(newValue); + + InvalidateMeasure(); + InvalidateArrange(); + } + } + } +} \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/TwoWayRangeBase.cs b/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/TwoWayRangeBase.cs new file mode 100644 index 00000000..7c3b5b5f --- /dev/null +++ b/src/Shared/HandyControl_Shared/Controls/Slider/RangeSlider/TwoWayRangeBase.cs @@ -0,0 +1,181 @@ +// Adapted from https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Primitives/RangeBase.cs + +using HandyControl.Data; +using HandyControl.Tools; +using System.Windows; +using System.Windows.Controls; + +namespace HandyControl.Controls +{ + public class TwoWayRangeBase : Control + { + public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register( + "Minimum", typeof(double), typeof(TwoWayRangeBase), + new PropertyMetadata(ValueBoxes.Double0Box, OnMinimumChanged), ValidateHelper.IsInRangeOfDouble); + + private static void OnMinimumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctrl = (TwoWayRangeBase)d; + + ctrl.CoerceValue(MaximumProperty); + ctrl.CoerceValue(ValueStartProperty); + ctrl.CoerceValue(ValueEndProperty); + ctrl.OnMinimumChanged((double)e.OldValue, (double)e.NewValue); + } + + protected virtual void OnMinimumChanged(double oldMinimum, double newMinimum) + { + } + + public double Minimum + { + get => (double)GetValue(MinimumProperty); + set => SetValue(MinimumProperty, value); + } + + public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register( + "Maximum", typeof(double), typeof(TwoWayRangeBase), + new PropertyMetadata(ValueBoxes.Double10Box, OnMaximumChanged, CoerceMaximum), + ValidateHelper.IsInRangeOfDouble); + + private static object CoerceMaximum(DependencyObject d, object basevalue) + { + var ctrl = (TwoWayRangeBase)d; + var min = ctrl.Minimum; + if ((double)basevalue < min) + { + return min; + } + return basevalue; + } + + private static void OnMaximumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctrl = (TwoWayRangeBase)d; + + ctrl.CoerceValue(ValueStartProperty); + ctrl.CoerceValue(ValueEndProperty); + ctrl.OnMaximumChanged((double)e.OldValue, (double)e.NewValue); + } + + protected virtual void OnMaximumChanged(double oldMaximum, double newMaximum) + { + } + + public double Maximum + { + get => (double)GetValue(MaximumProperty); + set => SetValue(MaximumProperty, value); + } + + public static readonly DependencyProperty ValueStartProperty = DependencyProperty.Register( + "ValueStart", typeof(double), typeof(TwoWayRangeBase), + new FrameworkPropertyMetadata(ValueBoxes.Double0Box, + FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, + OnValueStartChanged, ConstrainToRange), ValidateHelper.IsInRangeOfDouble); + + private static void OnValueStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctrl = (TwoWayRangeBase)d; + ctrl.OnValueChanged(new TwoWayRange + { + ValueStart = (double)e.OldValue, + ValueEnd = ctrl.ValueEnd + }, new TwoWayRange + { + ValueStart = (double)e.NewValue, + ValueEnd = ctrl.ValueEnd + }); + } + + protected virtual void OnValueChanged(TwoWayRange oldValue, TwoWayRange newValue) => RaiseEvent( + new RoutedPropertyChangedEventArgs(oldValue, newValue) {RoutedEvent = ValueChangedEvent}); + + public double ValueStart + { + get => (double)GetValue(ValueStartProperty); + set => SetValue(ValueStartProperty, value); + } + + public static readonly DependencyProperty ValueEndProperty = DependencyProperty.Register( + "ValueEnd", typeof(double), typeof(TwoWayRangeBase), + new FrameworkPropertyMetadata(ValueBoxes.Double0Box, + FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, + OnValueEndChanged, ConstrainToRange), ValidateHelper.IsInRangeOfDouble); + + private static void OnValueEndChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctrl = (TwoWayRangeBase)d; + ctrl.OnValueChanged(new TwoWayRange + { + ValueStart = ctrl.ValueStart, + ValueEnd = (double)e.OldValue + }, new TwoWayRange + { + ValueStart = ctrl.ValueStart, + ValueEnd = (double)e.NewValue + }); + } + + public double ValueEnd + { + get => (double)GetValue(ValueEndProperty); + set => SetValue(ValueEndProperty, value); + } + + internal static object ConstrainToRange(DependencyObject d, object value) + { + var ctrl = (TwoWayRangeBase)d; + var min = ctrl.Minimum; + var v = (double)value; + if (v < min) + { + return min; + } + + var max = ctrl.Maximum; + if (v > max) + { + return max; + } + + return value; + } + + public static readonly DependencyProperty LargeChangeProperty = DependencyProperty.Register( + "LargeChange", typeof(double), typeof(TwoWayRangeBase), new PropertyMetadata(ValueBoxes.Double1Box), + ValidateHelper.IsInRangeOfPosDoubleIncludeZero); + + public double LargeChange + { + get => (double)GetValue(LargeChangeProperty); + set => SetValue(LargeChangeProperty, value); + } + + public static readonly DependencyProperty SmallChangeProperty = DependencyProperty.Register( + "SmallChange", typeof(double), typeof(TwoWayRangeBase), new PropertyMetadata(ValueBoxes.Double01Box), + ValidateHelper.IsInRangeOfPosDoubleIncludeZero); + + public double SmallChange + { + get => (double)GetValue(SmallChangeProperty); + set => SetValue(SmallChangeProperty, value); + } + + public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", + RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(TwoWayRangeBase)); + + public event RoutedPropertyChangedEventHandler ValueChanged + { + add => AddHandler(ValueChangedEvent, value); + remove => RemoveHandler(ValueChangedEvent, value); + } + } + + public struct TwoWayRange + { + public double ValueStart { get; set; } + + public double ValueEnd { get; set; } + } +} \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Data/ValueBoxes.cs b/src/Shared/HandyControl_Shared/Data/ValueBoxes.cs index d53cba75..dea64e0b 100644 --- a/src/Shared/HandyControl_Shared/Data/ValueBoxes.cs +++ b/src/Shared/HandyControl_Shared/Data/ValueBoxes.cs @@ -11,8 +11,12 @@ internal static object Double0Box = .0; + internal static object Double01Box = .1; + internal static object Double1Box = 1.0; + internal static object Double10Box = 10.0; + internal static object Double20Box = 20.0; internal static object Double100Box = 100.0; diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index fd5312df..4b26b7e4 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -18,7 +18,11 @@ + + + + @@ -84,9 +88,10 @@ - - + + + @@ -331,6 +336,14 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/ColorPickerBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/ColorPickerBaseStyle.xaml new file mode 100644 index 00000000..62f6a76b --- /dev/null +++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/ColorPickerBaseStyle.xaml @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/SliderBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/SliderBaseStyle.xaml new file mode 100644 index 00000000..aac15bce --- /dev/null +++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/SliderBaseStyle.xaml @@ -0,0 +1,925 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/TextBoxBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/TextBoxBaseStyle.xaml index fb0f8ac5..a8f0852d 100644 --- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/TextBoxBaseStyle.xaml +++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/TextBoxBaseStyle.xaml @@ -24,7 +24,7 @@ - + @@ -51,7 +51,7 @@ - + @@ -81,7 +81,7 @@ - + @@ -110,7 +110,7 @@ - + @@ -166,7 +166,7 @@ - +