HyperGraph
Changes
ConsoleTest/App.config 0(+0 -0)
ConsoleTest/ConsoleTest.csproj 58(+58 -0)
ConsoleTest/Program.cs 158(+139 -19)
ConsoleTest/Properties/AssemblyInfo.cs 36(+36 -0)
HyperGraph.sln 46(+43 -3)
HyperGraphModel/App.config 6(+6 -0)
HyperGraphModel/Combinatorics.cs 8(+4 -4)
HyperGraphModel/HyperGraph.cs 8(+4 -4)
HyperGraphModel/HyperGraphModel.csproj 10(+6 -4)
HyperGraphModel/Matrix.cs 35(+20 -15)
HyperGraphModel/Theorem.cs 14(+7 -7)
WPF/App.config 6(+6 -0)
WPF/App.xaml 9(+9 -0)
WPF/App.xaml.cs 25(+25 -0)
WPF/Common/Helpers/AppPaths.cs 15(+15 -0)
WPF/Common/Helpers/BringToFront.cs 74(+74 -0)
WPF/Common/Helpers/IniFile.cs 91(+91 -0)
WPF/Common/Helpers/MyExtensions.cs 28(+28 -0)
WPF/Common/Helpers/ProgressBar.cs 78(+78 -0)
WPF/Common/Helpers/QSort.cs 54(+54 -0)
WPF/Common/Helpers/SelfDiagnose.cs 19(+19 -0)
WPF/Common/Helpers/StatusBar.cs 74(+74 -0)
WPF/Common/Parameters/Parameter.cs 143(+143 -0)
WPF/Common/Parameters/ParameterBool.cs 34(+34 -0)
WPF/Common/Parameters/ParameterDouble.cs 70(+70 -0)
WPF/Common/Parameters/ParameterInt.cs 69(+69 -0)
WPF/Common/Parameters/ParameterRange.cs 62(+62 -0)
WPF/Common/Parameters/ParameterString.cs 38(+38 -0)
WPF/Common/Parameters/Status.cs 14(+14 -0)
WPF/Common/WPF/BaseViewModel.cs 47(+47 -0)
WPF/Common/WPF/Controls/CaptionButtons.xaml 199(+199 -0)
WPF/Common/WPF/Controls/CaptionButtons.xaml.cs 136(+136 -0)
WPF/Common/WPF/Controls/EditorPresenter.cs 177(+177 -0)
WPF/Common/WPF/Controls/TreeGridViewRowPresenter.cs 183(+183 -0)
WPF/Common/WPF/Controls/TreeList/SortBehavior.cs 150(+150 -0)
WPF/Common/WPF/Controls/TreeList/TreeList.cs 139(+139 -0)
WPF/Common/WPF/Controls/TreeList/TreeListItem.cs 106(+106 -0)
WPF/Common/WPF/Converters/ValueConverter.cs 24(+24 -0)
WPF/Common/WPF/Dictionary.xaml 52(+52 -0)
WPF/Common/WPF/Icons/Add.xaml 11(+11 -0)
WPF/Common/WPF/Icons/AddSub.xaml 11(+11 -0)
WPF/Common/WPF/Icons/Copy.xaml 7(+7 -0)
WPF/Common/WPF/Icons/Delete.xaml 9(+9 -0)
WPF/Common/WPF/Icons/DeleteItem.xaml 11(+11 -0)
WPF/Common/WPF/Icons/DeviceDeviceIcon.xaml 11(+11 -0)
WPF/Common/WPF/Icons/Down.xaml 11(+11 -0)
WPF/Common/WPF/Icons/Help.xaml 23(+23 -0)
WPF/Common/WPF/Icons/Open.xaml 9(+9 -0)
WPF/Common/WPF/Icons/Pointer.xaml 11(+11 -0)
WPF/Common/WPF/Icons/Read.xaml 10(+10 -0)
WPF/Common/WPF/Icons/Search.xaml 8(+8 -0)
WPF/Common/WPF/Icons/Settings.xaml 20(+20 -0)
WPF/Common/WPF/Icons/StartEndIcon.xaml 11(+11 -0)
WPF/Common/WPF/Icons/Substract.xaml 11(+11 -0)
WPF/Common/WPF/Icons/TreeListExpander.xaml 12(+12 -0)
WPF/Common/WPF/Icons/Up.xaml 11(+11 -0)
WPF/Common/WPF/Icons/VisibleOn.xaml 7(+7 -0)
WPF/Common/WPF/Icons/Warning.xaml 11(+11 -0)
WPF/Common/WPF/ModifyViewModel.cs 49(+49 -0)
WPF/Common/WPF/ObservableCollectionAdv.cs 57(+57 -0)
WPF/Common/WPF/RelayCommand.cs 152(+152 -0)
WPF/Common/WPF/Style/ButtonStyle.xaml 334(+334 -0)
WPF/Common/WPF/Style/Colors.xaml 29(+29 -0)
WPF/Common/WPF/Style/ComboBoxStyle.xaml 160(+160 -0)
WPF/Common/WPF/Style/ExpanderStyle.xaml 89(+89 -0)
WPF/Common/WPF/Style/GroupBoxStyle.xaml 29(+29 -0)
WPF/Common/WPF/Style/ListBoxStyle.xaml 12(+12 -0)
WPF/Common/WPF/Style/ProgressbarStyle.xaml 99(+99 -0)
WPF/Common/WPF/Style/ScrollBarStyle.xaml 89(+89 -0)
WPF/Common/WPF/Style/TabControlStyle.xaml 93(+93 -0)
WPF/Common/WPF/Style/TextBlockStyle.xaml 72(+72 -0)
WPF/Common/WPF/Style/TextBoxStyle.xaml 30(+30 -0)
WPF/Common/WPF/Style/WindowStyle.xaml 138(+138 -0)
WPF/FodyWeavers.xml 3(+3 -0)
WPF/FodyWeavers.xsd 111(+111 -0)
WPF/Model/EnumTheorem.cs 16(+16 -0)
WPF/packages.config 5(+5 -0)
WPF/Properties/AssemblyInfo.cs 55(+55 -0)
WPF/Properties/Resources.Designer.cs 71(+71 -0)
WPF/Properties/Resources.resx 117(+117 -0)
WPF/Properties/Settings.Designer.cs 30(+30 -0)
WPF/Properties/Settings.settings 7(+7 -0)
WPF/View/MainWindow.xaml 88(+88 -0)
WPF/View/MainWindow.xaml.cs 94(+94 -0)
WPF/ViewModel/MainViewModel.cs 62(+62 -0)
WPF/WPF.csproj 321(+321 -0)
Details
ConsoleTest/ConsoleTest.csproj 58(+58 -0)
diff --git a/ConsoleTest/ConsoleTest.csproj b/ConsoleTest/ConsoleTest.csproj
new file mode 100644
index 0000000..755c131
--- /dev/null
+++ b/ConsoleTest/ConsoleTest.csproj
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{DC20CE22-B876-4BEC-8E6E-1687AD4B5305}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>ConsoleTest</RootNamespace>
+ <AssemblyName>ConsoleTest</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <Deterministic>true</Deterministic>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\HyperGraphModel\HyperGraphModel.csproj">
+ <Project>{09fecaa7-0025-45b4-a633-9f07edb28c5a}</Project>
+ <Name>HyperGraphModel</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file
ConsoleTest/Properties/AssemblyInfo.cs 36(+36 -0)
diff --git a/ConsoleTest/Properties/AssemblyInfo.cs b/ConsoleTest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..06fb4da
--- /dev/null
+++ b/ConsoleTest/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Общие сведения об этой сборке предоставляются следующим набором
+// набора атрибутов. Измените значения этих атрибутов для изменения сведений,
+// связанные с этой сборкой.
+[assembly: AssemblyTitle("ConsoleTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ConsoleTest")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми
+// для компонентов COM. Если необходимо обратиться к типу в этой сборке через
+// из модели COM задайте для атрибута ComVisible этого типа значение true.
+[assembly: ComVisible(false)]
+
+// Следующий GUID представляет идентификатор typelib, если этот проект доступен из модели COM
+[assembly: Guid("dc20ce22-b876-4bec-8e6e-1687ad4b5305")]
+
+// Сведения о версии сборки состоят из указанных ниже четырех значений:
+//
+// Основной номер версии
+// Дополнительный номер версии
+// Номер сборки
+// Номер редакции
+//
+// Можно задать все значения или принять номера сборки и редакции по умолчанию
+// используя "*", как показано ниже:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
HyperGraph.sln 46(+43 -3)
diff --git a/HyperGraph.sln b/HyperGraph.sln
index 463bbe9..4c3cf45 100644
--- a/HyperGraph.sln
+++ b/HyperGraph.sln
@@ -1,20 +1,60 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27703.2047
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30611.23
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HyperGraph", "HyperGraph\HyperGraph.csproj", "{09FECAA7-0025-45B4-A633-9F07EDB28C5A}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPF", "WPF\WPF.csproj", "{6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTest", "ConsoleTest\ConsoleTest.csproj", "{DC20CE22-B876-4BEC-8E6E-1687AD4B5305}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HyperGraphModel", "HyperGraphModel\HyperGraphModel.csproj", "{09FECAA7-0025-45B4-A633-9F07EDB28C5A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Debug|x64.Build.0 = Debug|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Debug|x86.Build.0 = Debug|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Release|x64.ActiveCfg = Release|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Release|x64.Build.0 = Release|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Release|x86.ActiveCfg = Release|Any CPU
+ {6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}.Release|x86.Build.0 = Release|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Debug|x64.Build.0 = Debug|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Debug|x86.Build.0 = Debug|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Release|x64.ActiveCfg = Release|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Release|x64.Build.0 = Release|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Release|x86.ActiveCfg = Release|Any CPU
+ {DC20CE22-B876-4BEC-8E6E-1687AD4B5305}.Release|x86.Build.0 = Release|Any CPU
{09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Debug|x64.Build.0 = Debug|Any CPU
+ {09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Debug|x86.Build.0 = Debug|Any CPU
{09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Release|x64.ActiveCfg = Release|Any CPU
+ {09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Release|x64.Build.0 = Release|Any CPU
+ {09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Release|x86.ActiveCfg = Release|Any CPU
+ {09FECAA7-0025-45B4-A633-9F07EDB28C5A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
HyperGraphModel/App.config 6(+6 -0)
diff --git a/HyperGraphModel/App.config b/HyperGraphModel/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/HyperGraphModel/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+ </startup>
+</configuration>
\ No newline at end of file
WPF/App.config 6(+6 -0)
diff --git a/WPF/App.config b/WPF/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/WPF/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+ </startup>
+</configuration>
\ No newline at end of file
WPF/App.xaml 9(+9 -0)
diff --git a/WPF/App.xaml b/WPF/App.xaml
new file mode 100644
index 0000000..06ada7f
--- /dev/null
+++ b/WPF/App.xaml
@@ -0,0 +1,9 @@
+<Application x:Class="WPF.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="clr-namespace:WPF"
+ Startup="Application_Startup">
+ <Application.Resources>
+ <ResourceDictionary Source="Common/WPF/Dictionary.xaml"/>
+ </Application.Resources>
+</Application>
WPF/App.xaml.cs 25(+25 -0)
diff --git a/WPF/App.xaml.cs b/WPF/App.xaml.cs
new file mode 100644
index 0000000..3a730d1
--- /dev/null
+++ b/WPF/App.xaml.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace WPF
+{
+ /// <summary>
+ /// Логика взаимодействия для App.xaml
+ /// </summary>
+ public partial class App : Application
+ {
+ //public static string BackupDirPath { get { return System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Passwords"); } }
+ //public static int BackupMaxCount { get { return 10; } }
+ //public static string DataFilePath { get { return System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Uri.UnescapeDataString(new System.UriBuilder(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).Path)), "data.pw"); } }
+
+ void Application_Startup(object sender, StartupEventArgs e)
+ {
+ StartupUri = new Uri("View/MainWindow.xaml", UriKind.Relative);
+ }
+ }
+}
WPF/Common/Helpers/AppPaths.cs 15(+15 -0)
diff --git a/WPF/Common/Helpers/AppPaths.cs b/WPF/Common/Helpers/AppPaths.cs
new file mode 100644
index 0000000..0dc7f18
--- /dev/null
+++ b/WPF/Common/Helpers/AppPaths.cs
@@ -0,0 +1,15 @@
+using System;
+using System.IO;
+using System.Xml.Linq;
+
+namespace Common.Helpers
+{
+ public static class AppPaths
+ {
+ public static string ExeFolder { get; } = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
+ public static string ExeName { get; } = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().GetName().CodeBase);
+ public static string RCPath { get; } = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "RubezhCad"), "RC.xml");
+ public static string ParentDirectory { get; } = Directory.GetParent(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location)).ToString();
+
+ }
+}
WPF/Common/Helpers/BringToFront.cs 74(+74 -0)
diff --git a/WPF/Common/Helpers/BringToFront.cs b/WPF/Common/Helpers/BringToFront.cs
new file mode 100644
index 0000000..f465227
--- /dev/null
+++ b/WPF/Common/Helpers/BringToFront.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Common.Helpers
+{
+ public static class BringToFront
+ {
+ [DllImport("USER32.DLL")]
+ public static extern bool SetForegroundWindow(IntPtr hWnd);
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+ static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+ static extern int GetWindowTextLength(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
+
+ // Delegate to filter which windows to include
+ public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
+
+ /// <summary> Get the text for the window pointed to by hWnd </summary>
+ public static string GetWindowText(IntPtr hWnd)
+ {
+ int size = GetWindowTextLength(hWnd);
+ if (size > 0)
+ {
+ var builder = new StringBuilder(size + 1);
+ GetWindowText(hWnd, builder, builder.Capacity);
+ return builder.ToString();
+ }
+ return string.Empty;
+ }
+
+ /// <summary> Find all windows that match the given filter </summary>
+ /// <param name="filter"> A delegate that returns true for windows
+ /// that should be returned and false for windows that should
+ /// not be returned </param>
+ public static IEnumerable<IntPtr> FindWindows(EnumWindowsProc filter)
+ {
+ List<IntPtr> windows = new List<IntPtr>();
+
+ EnumWindows(delegate (IntPtr wnd, IntPtr param)
+ {
+ if (filter(wnd, param))
+ {
+ // only add the windows that pass the filter
+ windows.Add(wnd);
+ }
+ // but return true here so that we iterate all windows
+ return true;
+ }, IntPtr.Zero);
+ return windows;
+ }
+
+ /// <summary> Find all windows that contain the given title text </summary>
+ /// <param name="titleText"> The text that the window title must contain. </param>
+ public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
+ {
+ return FindWindows((wnd, param) => GetWindowText(wnd).Contains(titleText));
+ }
+ public static void ToFront(string title)
+ {
+ var windowIds = FindWindowsWithText(title);
+ foreach (IntPtr windowId in windowIds)
+ {
+ SetForegroundWindow(windowId);
+
+ }
+ }
+ }
+}
WPF/Common/Helpers/IniFile.cs 91(+91 -0)
diff --git a/WPF/Common/Helpers/IniFile.cs b/WPF/Common/Helpers/IniFile.cs
new file mode 100644
index 0000000..e376ada
--- /dev/null
+++ b/WPF/Common/Helpers/IniFile.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Common.Helpers
+{
+ public class IniFile
+ {
+ string _path;
+ readonly string _exe = Path.Combine(AppPaths.ExeFolder, AppPaths.ExeName);
+
+ [DllImport("kernel32")]
+ static extern long WritePrivateProfileString(string section, string key, string value, string filePath);
+
+ [DllImport("kernel32")]
+ static extern int GetPrivateProfileString(string section, string key, string Default, StringBuilder retVal, int size, string filePath);
+
+ [DllImport("kernel32")]
+ static extern int GetPrivateProfileString(string section, int key, string value, [MarshalAs(UnmanagedType.LPArray)] byte[] result, int size, string fileName);
+
+ public IniFile(string iniPath = null)
+ {
+ _path = new FileInfo(iniPath ?? _exe + ".ini").FullName;
+ }
+
+ public string Read(string key, string section = null)
+ {
+ var retVal = new StringBuilder(255);
+ GetPrivateProfileString(section ?? _exe, key, "", retVal, 255, _path);
+ return retVal.ToString();
+ }
+
+ public void Write(string key, string value, string section = null)
+ {
+ WritePrivateProfileString(section ?? _exe, key, value, _path);
+ }
+
+ public bool KeyExists(string key, string section = null)
+ {
+ return Read(key, section).Length > 0;
+ }
+
+ public Dictionary<string, string> GetValueDictionary(int position, string section, bool isNumber)
+ {
+ var rezult = new Dictionary<string, string>();
+ var keys = GetSectionKeys(section);
+ double doubVal;
+ int intVal;
+ foreach (var key in keys)
+ {
+ var value = Read(key, section).Split(new[] {"###"}, StringSplitOptions.None);
+ if (value.Length >= position &&
+ (!isNumber || (Double.TryParse(value[position], NumberStyles.Any, CultureInfo.InvariantCulture, out doubVal) || (int.TryParse(value[position], out intVal)))))
+ rezult.Add(key, value[position]);
+ }
+ return rezult;
+ }
+
+ public string[] GetSectionKeys(string section)
+ {
+ // Sets the maxsize buffer to 500, if the more
+ // is required then doubles the size each time.
+ for (int maxsize = 500;; maxsize *= 2)
+ {
+ // Obtains the EntryKey information in bytes
+ // and stores them in the maxsize buffer (Bytes array).
+ // Note that the SectionHeader value has been passed.
+ byte[] bytes = new byte[maxsize];
+ int size = GetPrivateProfileString(section, 0, "", bytes, maxsize, _path);
+
+ // Check the information obtained is not bigger
+ // than the allocated maxsize buffer - 2 bytes.
+ // if it is, then skip over the next section
+ // so that the maxsize buffer can be doubled.
+ if (size < maxsize - 2)
+ {
+ // Converts the bytes value into an ASCII char.
+ // This is one long string.
+ string entries = Encoding.GetEncoding("Windows-1251").GetString(bytes, 0,
+ size - (size > 0 ? 1 : 0));
+ // Splits the Long string into an array based on the "\0"
+ // or null (Newline) value and returns the value(s) in an array
+ return entries.Split('\0');
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
WPF/Common/Helpers/MyExtensions.cs 28(+28 -0)
diff --git a/WPF/Common/Helpers/MyExtensions.cs b/WPF/Common/Helpers/MyExtensions.cs
new file mode 100644
index 0000000..1536c79
--- /dev/null
+++ b/WPF/Common/Helpers/MyExtensions.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.Data;
+using System.Drawing.Text;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace Common.Helpers
+{
+ public static class MyExtensions
+ {
+ public static string ValidateDouble(this string text)
+ {
+ Regex regex = new Regex(@"\s*[a-z]*[A-Z]*");
+ text = regex.Replace(text, "");
+ text = text.Replace(",", ".");
+ return text;
+ }
+
+ public static string ValidateInt(this string text)
+ {
+ Regex regex = new Regex(@"\s*[a-z]*[A-Z]*");
+ text = regex.Replace(text, "");
+ text = text.Replace(",", "");
+ text = text.Replace(".", "");
+ return text;
+ }
+ }
+}
WPF/Common/Helpers/ProgressBar.cs 78(+78 -0)
diff --git a/WPF/Common/Helpers/ProgressBar.cs b/WPF/Common/Helpers/ProgressBar.cs
new file mode 100644
index 0000000..7ef95ba
--- /dev/null
+++ b/WPF/Common/Helpers/ProgressBar.cs
@@ -0,0 +1,78 @@
+using System.ComponentModel;
+
+namespace Common.Helpers
+{
+ public class ProgressBar : INotifyPropertyChanged
+ {
+
+ public ProgressBar(int max, bool isVisible = true)
+ {
+ Value = 0;
+ Maximum = max;
+ IsVisible = isVisible;
+ }
+
+ public void Incr()
+ {
+ Value++;
+ }
+
+ public ProgressBar()
+ {
+ Reset();
+ }
+
+ public void Reset()
+ {
+ Value = 0;
+ Maximum = 0;
+ IsVisible = false;
+ }
+
+ private int _value;
+
+ public int Value
+ {
+ get { return _value; }
+ set
+ {
+ if (_value != value)
+ {
+ _value = value;
+ OnPropertyChanged(nameof(Value));
+ }
+ }
+ }
+
+ private int _maximum;
+ public int Maximum
+ {
+ get { return _maximum; }
+ set
+ {
+ _maximum = value;
+ OnPropertyChanged(nameof(Maximum));
+ }
+ }
+
+ private bool _isVisible;
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set
+ {
+ _isVisible = value;
+ OnPropertyChanged(nameof(IsVisible));
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ //[NotifyPropertyChangedInvocator]
+ // for Resharper
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
WPF/Common/Helpers/QSort.cs 54(+54 -0)
diff --git a/WPF/Common/Helpers/QSort.cs b/WPF/Common/Helpers/QSort.cs
new file mode 100644
index 0000000..b6599c6
--- /dev/null
+++ b/WPF/Common/Helpers/QSort.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+
+namespace Common.Helpers
+{
+ public delegate int ItemComparer<in T>(T a, T b);
+ public delegate void Swap<T>(IList<T> elements, int index1, int index2);
+ public static class QSort
+ {
+
+ public static void Sort<T>(IList<T> elements, ItemComparer<T> comparer, bool reverse = false)
+ {
+ Sort(elements, CollectionSwap, comparer, reverse);
+ }
+ public static void Sort<T>(IList<T> elements, Swap<T> swap, ItemComparer<T> comparer, bool reverse = false)
+ {
+ Sort(elements, 0, elements.Count - 1, swap, comparer);
+ if (reverse)
+ for (int i = 0; i < elements.Count / 2; i++)
+ swap(elements, i, elements.Count - 1 - i);
+ }
+
+ static void Sort<T>(IList<T> elements, int left, int right, Swap<T> swap, ItemComparer<T> comparer)
+ {
+ if (elements.Count == 0)
+ return;
+ int i = left;
+ int j = right;
+ T pivot = elements[(left + right) / 2];
+ while (i <= j)
+ {
+ while (comparer(elements[i], pivot) < 0)
+ i++;
+ while (comparer(elements[j], pivot) > 0)
+ j--;
+ if (i <= j)
+ {
+ swap(elements, i, j);
+ i++;
+ j--;
+ }
+ }
+ if (left < j)
+ Sort(elements, left, j, swap, comparer);
+ if (i < right)
+ Sort(elements, i, right, swap, comparer);
+ }
+ static void CollectionSwap<T>(IList<T> elements, int index1, int index2)
+ {
+ T tmp = elements[index1];
+ elements[index1] = elements[index2];
+ elements[index2] = tmp;
+ }
+ }
+}
WPF/Common/Helpers/SelfDiagnose.cs 19(+19 -0)
diff --git a/WPF/Common/Helpers/SelfDiagnose.cs b/WPF/Common/Helpers/SelfDiagnose.cs
new file mode 100644
index 0000000..06d3938
--- /dev/null
+++ b/WPF/Common/Helpers/SelfDiagnose.cs
@@ -0,0 +1,19 @@
+using System.IO;
+using System.Windows.Forms;
+
+namespace Common.Helpers
+{
+ public static class SelfDiagnose
+ {
+ public static bool Exec()
+ {
+ if (File.Exists(Path.Combine(Path.Combine(AppPaths.ExeFolder, "Assets"), "Empty.dwg")) &&
+ File.Exists(Path.Combine(Path.Combine(AppPaths.ExeFolder, "Assets"), "isocpeui.ttf")) &&
+ File.Exists(Path.Combine(Path.Combine(AppPaths.ExeFolder, "Assets"), "isocpeur.ttf")) &&
+ File.Exists(Path.Combine(Path.Combine(AppPaths.ExeFolder, "Assets"), "SpecificationTemplate.dotx")))
+ return true;
+ MessageBox.Show("Missing file(s) in folder 'Assets'.");
+ return false;
+ }
+ }
+}
WPF/Common/Helpers/StatusBar.cs 74(+74 -0)
diff --git a/WPF/Common/Helpers/StatusBar.cs b/WPF/Common/Helpers/StatusBar.cs
new file mode 100644
index 0000000..fcb1160
--- /dev/null
+++ b/WPF/Common/Helpers/StatusBar.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+
+namespace Common.Helpers
+{
+ public class StatusBar : INotifyPropertyChanged
+ {
+
+ public StatusBar()
+ {
+ Reset();
+ }
+
+ public StatusBar(Status status, string message = "", bool isVisible = true)
+ {
+ IsVisible = isVisible;
+ Status = status;
+ Message = message;
+ }
+
+ public void Reset()
+ {
+ IsVisible = false;
+ Status = Status.Default;
+ Message = String.Empty;
+ }
+
+ private Status _status;
+ public Status Status
+ {
+ get { return _status; }
+ set
+ {
+ _status = value;
+ OnPropertyChanged(nameof(Status));
+ }
+ }
+
+ private string _message;
+
+ public string Message
+ {
+ get { return _message; }
+ set
+ {
+ _message = value;
+ OnPropertyChanged(nameof(Message));
+ }
+ }
+
+ private bool _isVisible;
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set
+ {
+ _isVisible = value;
+ OnPropertyChanged(nameof(IsVisible));
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ //[NotifyPropertyChangedInvocator]
+ // for Resharper
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
diff --git a/WPF/Common/Microsoft.Windows.Shell.dll b/WPF/Common/Microsoft.Windows.Shell.dll
new file mode 100644
index 0000000..8e44665
Binary files /dev/null and b/WPF/Common/Microsoft.Windows.Shell.dll differ
WPF/Common/Parameters/Parameter.cs 143(+143 -0)
diff --git a/WPF/Common/Parameters/Parameter.cs b/WPF/Common/Parameters/Parameter.cs
new file mode 100644
index 0000000..f7f7317
--- /dev/null
+++ b/WPF/Common/Parameters/Parameter.cs
@@ -0,0 +1,143 @@
+using System;
+using System.ComponentModel;
+
+namespace Common.Parameters
+{
+
+ public abstract class Parameter : INotifyPropertyChanged
+ {
+ public event EventHandler ValidateDelegate;
+
+ protected Parameter(string name) : this()
+ {
+ Name = name;
+ }
+ protected Parameter()
+ {
+ Status = Status.Normal;
+ ErrorShortDescr = String.Empty;
+ IsVisible = true;
+ IsEnabled = true;
+ }
+
+ public void Validate()
+ {
+ EventHandler handler = ValidateDelegate;
+ handler?.Invoke(this, new EventArgs());
+ }
+
+ public abstract void Update();
+
+ public double ErrorWarningCount { get; set; }
+
+ private int _errorCount;
+ public int ErrorCount
+ {
+ get { return _errorCount; }
+ set
+ {
+ _errorCount = value;
+ OnPropertyChanged("ErrorCount");
+ OnPropertyChanged("HasErrors");
+ }
+ }
+
+ public string ErrorShortDescr { get; set; }
+ public void ResetValidation()
+ {
+ ErrorShortDescr = String.Empty;
+ ErrorCount = 0;
+ ErrorWarningCount = 0;
+ ErrorMessage = null;
+ Status = Status.Normal;
+ }
+
+
+ private string _name;
+
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ _name = value;
+ OnPropertyChanged("Name");
+ }
+ }
+
+ private Status _status;
+
+ public Status Status
+ {
+ get { return _status; }
+ set
+ {
+ _status = value;
+ OnPropertyChanged("Status");
+ }
+ }
+
+ private string _errorMessage;
+
+ public string ErrorMessage
+ {
+ get { return _errorMessage; }
+ set
+ {
+ _errorMessage = value;
+ OnPropertyChanged("ErrorMessage");
+ }
+ }
+
+
+ public bool HasErrors
+ {
+ get { return (ErrorCount != 0); }
+ }
+
+ private bool _isVisible;
+ public bool IsVisible
+ {
+ get { return _isVisible; }
+ set
+ {
+ _isVisible = value;
+ OnPropertyChanged("IsVisible");
+ }
+ }
+
+ private bool _isEnabled;
+ public bool IsEnabled
+ {
+ get { return _isEnabled; }
+ set
+ {
+ _isEnabled = value;
+ OnPropertyChanged("IsEnabled");
+ }
+ }
+
+ public void SetErrInfo(string errorMessage, Status status, string errorShortDescr = "", bool isAppend = false)
+ {
+ ErrorShortDescr = errorShortDescr;
+ if (isAppend)
+ ErrorMessage += "\n\n" + errorMessage;
+ else
+ ErrorMessage = errorMessage;
+ Status = status;
+ ErrorWarningCount++;
+ if (status == Status.Error)
+ ErrorCount++;
+ }
+
+
+ public void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ [field: NonSerialized]
+ public event PropertyChangedEventHandler PropertyChanged;
+ }
+
+}
WPF/Common/Parameters/ParameterBool.cs 34(+34 -0)
diff --git a/WPF/Common/Parameters/ParameterBool.cs b/WPF/Common/Parameters/ParameterBool.cs
new file mode 100644
index 0000000..cf4e024
--- /dev/null
+++ b/WPF/Common/Parameters/ParameterBool.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Common.Parameters
+{
+ [Serializable]
+ public class ParameterBool : Parameter
+ {
+ public ParameterBool(string name, bool value)
+ : base(name)
+ {
+ Value = value;
+ }
+
+
+ private bool _value;
+ public bool Value
+ {
+ get { return _value; }
+ set
+ {
+ _value = value;
+ Validate();
+ OnPropertyChanged("Value");
+ }
+ }
+
+
+
+ public override void Update()
+ {
+ Value = _value;
+ }
+ }
+}
WPF/Common/Parameters/ParameterDouble.cs 70(+70 -0)
diff --git a/WPF/Common/Parameters/ParameterDouble.cs b/WPF/Common/Parameters/ParameterDouble.cs
new file mode 100644
index 0000000..96b407c
--- /dev/null
+++ b/WPF/Common/Parameters/ParameterDouble.cs
@@ -0,0 +1,70 @@
+using System;
+
+namespace Common.Parameters
+{
+ [Serializable]
+ public class ParameterDouble : Parameter
+ {
+ public ParameterDouble(string name, double value)
+ :base(name)
+ {
+ Value = value;
+ }
+
+ public ParameterDouble(string name)
+ : base(name)
+ {
+ }
+
+ private double _value;
+ public double Value
+ {
+ get { return _value; }
+ set
+ {
+ _value = value;
+ Validate();
+ OnPropertyChanged("Value");
+ }
+ }
+
+ public bool CheckMinCondition(double minValue, Status errType, string errorShortDescr = "")
+ {
+ bool isOk = true;
+ if (Value < minValue)
+ {
+ SetErrInfo("Значение " + Name + " должно быть не менее " + minValue, errType, errorShortDescr);
+ isOk = false;
+ }
+ return isOk;
+ }
+
+ public override void Update()
+ {
+ Value = _value;
+ }
+
+
+ public void CheckRangeCondition(double beginValue, double endValue, bool isInsideRange, Status errType, string errorMessage, string errorShortDescr = "", bool isAppend = false)
+ {
+ if (isInsideRange) //Если число должно лежать внутри диапазона
+ {
+ // Но не лежит
+ if (beginValue > Value || Value > endValue)
+ {
+ SetErrInfo(errorMessage, errType, errorShortDescr, isAppend);
+ }
+ }
+ else
+ {
+ if (beginValue <= Value && Value <= endValue)
+ {
+ SetErrInfo(errorMessage, errType, errorShortDescr, isAppend);
+ }
+ }
+ }
+ }
+}
+
+
+
WPF/Common/Parameters/ParameterInt.cs 69(+69 -0)
diff --git a/WPF/Common/Parameters/ParameterInt.cs b/WPF/Common/Parameters/ParameterInt.cs
new file mode 100644
index 0000000..7758f3d
--- /dev/null
+++ b/WPF/Common/Parameters/ParameterInt.cs
@@ -0,0 +1,69 @@
+using System;
+
+namespace Common.Parameters
+{
+ [Serializable]
+ public class ParameterInt: Parameter
+ {
+ public ParameterInt(string name, int value)
+ : base(name)
+ {
+ Value = value;
+ }
+
+
+ private int _value;
+ public int Value
+ {
+ get { return _value; }
+ set
+ {
+ _value = value;
+ Validate();
+ OnPropertyChanged("Value");
+ }
+ }
+
+ public bool CheckMinCondition(int minValue, Status errType, string errorShortDescr = "")
+ {
+ bool isOk = true;
+ if (Value < minValue)
+ {
+ SetErrInfo("Значение " + Name + " должно быть не менее " + minValue, errType, errorShortDescr);
+ isOk = false;
+ }
+ return isOk;
+ }
+
+ public override void Update()
+ {
+ Value = _value;
+ }
+
+ //public void CallSelectionChange()
+ //{
+ // Value = _value + 1;
+ // Value = _value - 1;
+ //}
+
+
+ //public void CheckRangeCondition(double beginValue, double endValue, bool isInsideRange, StateType errType)
+ //{
+ // if (isInsideRange) //Если число должно лежать внутри диапазона
+ // {
+ // // Но не лежит
+ // if (beginValue > Value || Value > endValue)
+ // {
+ // SetErrInfo("Значение " + Name + " должно лежать в диапазоне [" + beginValue + ";" + endValue + "]", errType);
+ // }
+ // }
+ // else
+ // {
+ // if (beginValue <= Value && Value <= endValue)
+ // {
+ // SetErrInfo("Значение " + Name + " должно лежать вне диапазона [" + beginValue + ";" + endValue +"]", errType);
+ // }
+ // }
+ //}
+ }
+}
WPF/Common/Parameters/ParameterRange.cs 62(+62 -0)
diff --git a/WPF/Common/Parameters/ParameterRange.cs b/WPF/Common/Parameters/ParameterRange.cs
new file mode 100644
index 0000000..10f0467
--- /dev/null
+++ b/WPF/Common/Parameters/ParameterRange.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Common.Parameters
+{
+ public class ParameterRange : Parameter
+ {
+
+
+
+ public ParameterRange(string name, string value)
+ : base(name)
+ {
+ Value = value;
+ }
+
+
+ private string _value;
+ public string Value
+ {
+ get { return _value; }
+ set
+ {
+ _value = value;
+ Validate();
+ OnPropertyChanged("Value");
+ }
+ }
+
+ public override void Update()
+ {
+ Value = _value;
+ }
+
+ public bool IsFormatRange(out bool isNotInRange, int min, int max)
+ {
+ isNotInRange = false;
+ var numbers = Value.Replace(" ", "").Split(new []{ ",","-"}, StringSplitOptions.None);
+ //регулярное выражение для числа от 1-250
+ foreach (var numStr in numbers)
+ {
+ int num;
+ if (int.TryParse(numStr, out num))
+ {
+ if (num < min || num > max)
+ {
+ isNotInRange = true;
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
WPF/Common/Parameters/ParameterString.cs 38(+38 -0)
diff --git a/WPF/Common/Parameters/ParameterString.cs b/WPF/Common/Parameters/ParameterString.cs
new file mode 100644
index 0000000..7a8e012
--- /dev/null
+++ b/WPF/Common/Parameters/ParameterString.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace Common.Parameters
+{
+ [Serializable]
+ public class ParameterString : Parameter
+ {
+
+ public ParameterString(string name, string value)
+ : base(name)
+ {
+ Value = value;
+ }
+
+ public ParameterString(string name)
+ : base(name)
+ {
+ }
+
+
+ private string _value;
+ public string Value
+ {
+ get { return _value; }
+ set
+ {
+ _value = value;
+ Validate();
+ OnPropertyChanged("Value");
+ }
+ }
+
+ public override void Update()
+ {
+ Value = _value;
+ }
+ }
+}
WPF/Common/Parameters/Status.cs 14(+14 -0)
diff --git a/WPF/Common/Parameters/Status.cs b/WPF/Common/Parameters/Status.cs
new file mode 100644
index 0000000..e0c7d74
--- /dev/null
+++ b/WPF/Common/Parameters/Status.cs
@@ -0,0 +1,14 @@
+namespace Common
+{
+ public enum Status
+ {
+ Default,
+ Normal,
+ Error,
+ Warning,
+ SpecialWarning,
+ ExportInProgress,
+ OperationFailed,
+ OperationSuccess,
+ }
+}
WPF/Common/WPF/BaseViewModel.cs 47(+47 -0)
diff --git a/WPF/Common/WPF/BaseViewModel.cs b/WPF/Common/WPF/BaseViewModel.cs
new file mode 100644
index 0000000..900de8e
--- /dev/null
+++ b/WPF/Common/WPF/BaseViewModel.cs
@@ -0,0 +1,47 @@
+using System;
+using System.ComponentModel;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Windows;
+using System.Windows.Input;
+
+namespace Common.WPF
+{
+ public abstract class BaseViewModel : INotifyPropertyChanged
+ {
+ #region INotifyPropertyChanged Members and helper
+
+ readonly NotifyPropertyChangedHelper _propertyChangeHelper = new NotifyPropertyChangedHelper();
+
+ public event PropertyChangedEventHandler PropertyChanged
+ {
+ add { _propertyChangeHelper.Add(value); }
+ remove { _propertyChangeHelper.Remove(value); }
+ }
+
+ protected void OnPropertyChanged(string propertyName)
+ {
+ _propertyChangeHelper.NotifyPropertyChanged(this, propertyName);
+ }
+
+ protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
+ {
+ OnPropertyChanged(ExtractPropertyName(propertyExpression));
+ }
+
+ static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
+ {
+ if (propertyExpression == null)
+ throw new ArgumentNullException(nameof(propertyExpression));
+ var memberExpression = propertyExpression.Body as MemberExpression;
+ if (memberExpression == null)
+ throw new ArgumentException("The expression is not a member access expression.", nameof(propertyExpression));
+ var property = memberExpression.Member as PropertyInfo;
+ if (property == null)
+ throw new ArgumentException("The member access expression does not access a property.", nameof(propertyExpression));
+ return property.Name;
+ }
+ #endregion
+ }
+}
\ No newline at end of file
WPF/Common/WPF/Controls/CaptionButtons.xaml 199(+199 -0)
diff --git a/WPF/Common/WPF/Controls/CaptionButtons.xaml b/WPF/Common/WPF/Controls/CaptionButtons.xaml
new file mode 100644
index 0000000..e1b3666
--- /dev/null
+++ b/WPF/Common/WPF/Controls/CaptionButtons.xaml
@@ -0,0 +1,199 @@
+<UserControl x:Class="Common.WPF.Controls.CaptionButtons"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ mc:Ignorable="d">
+ <UserControl.Resources>
+
+ <ControlTemplate x:Key="ChromeButtonControlTemplate" TargetType="{x:Type ButtonBase}">
+ <Border x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}"
+ Margin="{Binding MarginButton, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
+ Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
+ <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}"
+ Content="{TemplateBinding Content}"
+ ContentStringFormat="{TemplateBinding ContentStringFormat}"
+ HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+ RecognizesAccessKey="True"
+ SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
+ VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ </Border>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter Property="Foreground" Value="#FFADADAD"/>
+ <Setter Property="Opacity" TargetName="Chrome" Value="0.5"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+
+ <DataTemplate x:Key="MaximizeButtonControlTemplate">
+ <TextBlock x:Name="StateText" TextWrapping="Wrap" Text="1" FontFamily="Webdings"
+ Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
+ FontSize="{Binding FontSize, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
+ <DataTemplate.Triggers>
+ <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Normal">
+ <Setter TargetName="StateText" Property="Text" Value="1"/>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Maximized">
+ <Setter TargetName="StateText" Property="Text" Value="2"/>
+ </DataTrigger>
+ </DataTemplate.Triggers>
+ </DataTemplate>
+
+ <DataTemplate x:Key="DefaultButtonControlTemplate">
+ <TextBlock TextWrapping="Wrap" Text="{TemplateBinding Content}" FontFamily="Webdings"
+ Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
+ FontSize="{Binding FontSize, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
+ </DataTemplate>
+
+ <Style x:Key="ReduceChromeButtonStyle" TargetType="{x:Type Button}">
+ <Style.Resources>
+ <Storyboard x:Key="OnMouseDownStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ <Storyboard x:Key="OnMouseEnterStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="0.8"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ <Storyboard x:Key="OnMouseLeaveStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="0.5"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </Style.Resources>
+ <Setter Property="Background" Value="#00000000"/>
+ <Setter Property="BorderBrush" Value="{x:Null}"/>
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="VerticalAlignment" Value="Top"/>
+ <Setter Property="Padding" Value="0"/>
+ <Setter Property="Template" Value="{StaticResource ChromeButtonControlTemplate}"/>
+ <Setter Property="Opacity" Value="0.5" />
+ <Setter Property="Visibility" Value="Collapsed"/>
+ <Style.Triggers>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter Property="Opacity" Value="0.5"/>
+ </Trigger>
+ <DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="Full">
+ <Setter Property="Visibility" Value="Visible"/>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="ReduceClose">
+ <Setter Property="Visibility" Value="Visible"/>
+ </DataTrigger>
+ <EventTrigger RoutedEvent="Mouse.PreviewMouseDown">
+ <BeginStoryboard x:Name="OnMouseDown_BeginStoryboard" Storyboard="{StaticResource OnMouseDownStoryboard}"/>
+ </EventTrigger>
+ <EventTrigger RoutedEvent="MouseEnter">
+ <BeginStoryboard x:Name="OnMouseEnter_BeginStoryboard" Storyboard="{StaticResource OnMouseEnterStoryboard}"/>
+ </EventTrigger>
+ <EventTrigger RoutedEvent="MouseLeave">
+ <BeginStoryboard x:Name="OnMouseLeave_BeginStoryboard" Storyboard="{StaticResource OnMouseLeaveStoryboard}"/>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+
+ <Style x:Key="MaximizeChromeButtonStyle" TargetType="{x:Type Button}">
+ <Style.Resources>
+ <Storyboard x:Key="OnMouseDownStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ <Storyboard x:Key="OnMouseEnterStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="0.8"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ <Storyboard x:Key="OnMouseLeaveStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="0.5"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </Style.Resources>
+ <Setter Property="Background" Value="#00000000"/>
+ <Setter Property="BorderBrush" Value="{x:Null}"/>
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="VerticalAlignment" Value="Top"/>
+ <Setter Property="Padding" Value="0"/>
+ <Setter Property="Template" Value="{StaticResource ChromeButtonControlTemplate}"/>
+ <Setter Property="Opacity" Value="0.5" />
+ <Setter Property="Visibility" Value="Collapsed"/>
+ <Style.Triggers>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter Property="Opacity" Value="0.5"/>
+ </Trigger>
+ <DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="Full">
+ <Setter Property="Visibility" Value="Visible"/>
+ </DataTrigger>
+ <EventTrigger RoutedEvent="Mouse.PreviewMouseDown">
+ <BeginStoryboard x:Name="OnMouseDown_BeginStoryboard" Storyboard="{StaticResource OnMouseDownStoryboard}"/>
+ </EventTrigger>
+ <EventTrigger RoutedEvent="MouseEnter">
+ <BeginStoryboard x:Name="OnMouseEnter_BeginStoryboard" Storyboard="{StaticResource OnMouseEnterStoryboard}"/>
+ </EventTrigger>
+ <EventTrigger RoutedEvent="MouseLeave">
+ <BeginStoryboard x:Name="OnMouseLeave_BeginStoryboard" Storyboard="{StaticResource OnMouseLeaveStoryboard}"/>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+
+ <Style x:Key="CloseChromeButtonStyle" TargetType="{x:Type Button}">
+ <Style.Resources>
+ <Storyboard x:Key="OnMouseDownStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ <Storyboard x:Key="OnMouseEnterStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="0.8"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ <Storyboard x:Key="OnMouseLeaveStoryboard">
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
+ <SplineDoubleKeyFrame KeyTime="0" Value="0.5"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </Style.Resources>
+ <Setter Property="Background" Value="#00000000"/>
+ <Setter Property="BorderBrush" Value="{x:Null}"/>
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="VerticalAlignment" Value="Top"/>
+ <Setter Property="Padding" Value="0"/>
+ <Setter Property="Template" Value="{StaticResource ChromeButtonControlTemplate}"/>
+ <Setter Property="Opacity" Value="0.5" />
+ <Setter Property="Visibility" Value="Visible"/>
+ <Style.Triggers>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter Property="Opacity" Value="0.5"/>
+ </Trigger>
+ <EventTrigger RoutedEvent="Mouse.PreviewMouseDown">
+ <BeginStoryboard x:Name="OnMouseDown_BeginStoryboard" Storyboard="{StaticResource OnMouseDownStoryboard}"/>
+ </EventTrigger>
+ <EventTrigger RoutedEvent="MouseEnter">
+ <BeginStoryboard x:Name="OnMouseEnter_BeginStoryboard" Storyboard="{StaticResource OnMouseEnterStoryboard}"/>
+ </EventTrigger>
+ <EventTrigger RoutedEvent="MouseLeave">
+ <BeginStoryboard x:Name="OnMouseLeave_BeginStoryboard" Storyboard="{StaticResource OnMouseLeaveStoryboard}"/>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+
+ <Style x:Key="CaptionButtonStyle" TargetType="{x:Type StackPanel}">
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Maximized">
+ <Setter Property="Margin" Value="0,10,8,0"/>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+
+ </UserControl.Resources>
+
+ <StackPanel Orientation="Horizontal" Style="{StaticResource CaptionButtonStyle}">
+ <Button Style="{StaticResource ReduceChromeButtonStyle}" Click="MinimizeButtonClick" ContentTemplate="{DynamicResource DefaultButtonControlTemplate}" Content="0" />
+ <Button Style="{StaticResource MaximizeChromeButtonStyle}" Click="RestoreButtonClick" ContentTemplate="{DynamicResource MaximizeButtonControlTemplate}" />
+ <Button Style="{StaticResource CloseChromeButtonStyle}" Click="CloseButtonClick" ContentTemplate="{DynamicResource DefaultButtonControlTemplate}" Content="r" />
+ </StackPanel>
+</UserControl>
\ No newline at end of file
WPF/Common/WPF/Controls/CaptionButtons.xaml.cs 136(+136 -0)
diff --git a/WPF/Common/WPF/Controls/CaptionButtons.xaml.cs b/WPF/Common/WPF/Controls/CaptionButtons.xaml.cs
new file mode 100644
index 0000000..3ba89d1
--- /dev/null
+++ b/WPF/Common/WPF/Controls/CaptionButtons.xaml.cs
@@ -0,0 +1,136 @@
+using System.Windows;
+// ReSharper disable UnusedMember.Global
+
+namespace Common.WPF.Controls
+{
+ /// <summary>
+ /// Interaction logic for CaptionButtons.xaml
+ /// </summary>
+ public partial class CaptionButtons
+ {
+ /// <summary>
+ /// The parent Window of the control.
+ /// </summary>
+ Window _parent;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CaptionButtons"/> class.
+ /// </summary>
+ public CaptionButtons()
+ {
+ InitializeComponent();
+ Loaded += CaptionButtonsLoaded;
+ }
+
+ /// <summary>
+ /// Event when the control is loaded.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
+ void CaptionButtonsLoaded(object sender, RoutedEventArgs e)
+ {
+ _parent = GetTopParent();
+ }
+
+ /// <summary>
+ /// Action on the button to close the window.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
+ void CloseButtonClick(object sender, RoutedEventArgs e)
+ {
+ _parent.Close();
+ }
+
+ /// <summary>
+ /// Changes the view of the window (maximized or normal).
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
+ void RestoreButtonClick(object sender, RoutedEventArgs e)
+ {
+ _parent.WindowState = _parent.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
+ }
+
+ /// <summary>
+ /// Minimizes the Window.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
+ void MinimizeButtonClick(object sender, RoutedEventArgs e)
+ {
+ _parent.WindowState = WindowState.Minimized;
+ }
+
+ /// <summary>
+ /// Gets the top parent (Window).
+ /// </summary>
+ /// <returns>The parent Window.</returns>
+ Window GetTopParent()
+ {
+ return Window.GetWindow(this);
+ }
+
+ /// <summary>
+ /// Gets or sets the margin button.
+ /// </summary>
+ /// <value>The margin button.</value>
+ public Thickness MarginButton
+ {
+ get { return (Thickness)GetValue(MarginButtonProperty); }
+ set
+ {
+ SetValue(MarginButtonProperty, value);
+ }
+ }
+
+ /// <summary>
+ /// The dependency property for the Margin between the buttons.
+ /// </summary>
+ public static DependencyProperty MarginButtonProperty = DependencyProperty.Register(
+ "MarginButton",
+ typeof(Thickness),
+ typeof(Window));
+
+ /// <summary>
+ /// Enum of the types of caption buttons
+ /// </summary>
+ public enum CaptionType
+ {
+ /// <summary>
+ /// All the buttons
+ /// </summary>
+ Full,
+ /// <summary>
+ /// Only the close button
+ /// </summary>
+ Close,
+ /// <summary>
+ /// Reduce and close buttons
+ /// </summary>
+ ReduceClose
+ }
+
+ /// <summary>
+ /// Gets or sets the visibility of the buttons.
+ /// </summary>
+ /// <value>The visible buttons.</value>
+ public CaptionType Type
+ {
+ get { return (CaptionType)GetValue(TypeProperty); }
+ set
+ {
+ SetValue(TypeProperty, value);
+ }
+ }
+
+ /// <summary>
+ /// The dependency property for the Margin between the buttons.
+ /// </summary>
+ public static DependencyProperty TypeProperty = DependencyProperty.Register(
+ "Type",
+ typeof(CaptionType),
+ typeof(Window),
+ new PropertyMetadata(CaptionType.Full));
+ }
+}
WPF/Common/WPF/Controls/EditorPresenter.cs 177(+177 -0)
diff --git a/WPF/Common/WPF/Controls/EditorPresenter.cs b/WPF/Common/WPF/Controls/EditorPresenter.cs
new file mode 100644
index 0000000..49dd91e
--- /dev/null
+++ b/WPF/Common/WPF/Controls/EditorPresenter.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Common.WPF.Controls
+{
+ public class EditorPresenter : Control
+ {
+ static EditorPresenter()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(EditorPresenter), new FrameworkPropertyMetadata(typeof(EditorPresenter)));
+ }
+
+ public static DependencyProperty IsEditingProperty = DependencyProperty.Register("IsEditing", typeof(bool), typeof(EditorPresenter), new FrameworkPropertyMetadata(false));
+ public bool IsEditing
+ {
+ get { return (bool)GetValue(IsEditingProperty); }
+ private set
+ {
+ bool val = IsEditing;
+ SetValue(IsEditingProperty, value);
+ if (val != IsEditing)
+ {
+ if (IsEditing && EditTemplate != null && IsTemplateEditable)
+ Template = EditTemplate;
+ else if (!IsEditing)
+ Template = ViewTemplate;
+ }
+ }
+ }
+
+ //Добавлено свойство, позволяющее блокировать ввод
+ public static DependencyProperty EditableTemplateProperty = DependencyProperty.Register("IsTemplateEditable", typeof(bool), typeof(EditorPresenter), new FrameworkPropertyMetadata(true));
+
+ public bool IsTemplateEditable
+ {
+ get { return (bool)GetValue(EditableTemplateProperty); }
+ set
+ {
+ SetValue(EditableTemplateProperty, value);
+ }
+ }
+
+ public static DependencyProperty ToggleableTemplateProperty = DependencyProperty.Register("IsTemplateToggleable", typeof(bool), typeof(EditorPresenter), new FrameworkPropertyMetadata(true));
+
+ public bool IsTemplateToggleable
+ {
+ get { return (bool)GetValue(ToggleableTemplateProperty); }
+ set
+ {
+ SetValue(ToggleableTemplateProperty, value);
+ }
+ }
+
+ public static DependencyProperty EditTemplateProperty = DependencyProperty.Register("EditTemplate", typeof(ControlTemplate), typeof(EditorPresenter), new FrameworkPropertyMetadata());
+ public ControlTemplate EditTemplate
+ {
+ get { return (ControlTemplate)GetValue(EditTemplateProperty); }
+ set { SetValue(EditTemplateProperty, value); }
+ }
+
+ public static DependencyProperty ViewTemplateProperty = DependencyProperty.Register("ViewTemplate", typeof(ControlTemplate), typeof(EditorPresenter), new FrameworkPropertyMetadata(ViewTemplateChanged));
+ public ControlTemplate ViewTemplate
+ {
+ get { return (ControlTemplate)GetValue(ViewTemplateProperty); }
+ set { SetValue(ViewTemplateProperty, value); }
+ }
+
+ bool _canBeEdit;
+ bool _isMouseWithinScope;
+ TreeViewItem _viewItem;
+
+ public EditorPresenter()
+ {
+ IsKeyboardFocusWithinChanged += OnEditorIsKeyboardFocusWithinChanged;
+ LostKeyboardFocus += OnEditorLostKeyboardFocus;
+ LayoutUpdated += OnEditorLayoutUpdated;
+ KeyDown += OnEditorKeyDown;
+ FocusVisualStyle = null;
+ IsTabStop = false;
+ }
+
+ static void ViewTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ EditorPresenter presenter = (EditorPresenter)d;
+ presenter.Template = (ControlTemplate)e.NewValue;
+ presenter.IsEditing = false;
+ }
+
+ protected override void OnMouseEnter(MouseEventArgs e)
+ {
+ base.OnMouseEnter(e);
+ if (!IsEditing && IsParentSelected)
+ {
+ _canBeEdit = true;
+ }
+ }
+ protected override void OnMouseLeave(MouseEventArgs e)
+ {
+ base.OnMouseLeave(e);
+ _isMouseWithinScope = false;
+ _canBeEdit = false;
+ }
+ protected override void OnPreviewMouseDoubleClick(MouseButtonEventArgs e)
+ {
+ OnMouseUp(e);
+
+ if (e.ChangedButton == MouseButton.Right || e.ChangedButton == MouseButton.Middle)
+ return;
+ if (!IsEditing && IsTemplateToggleable)
+ {
+ if (!e.Handled && (_canBeEdit || _isMouseWithinScope))
+ IsEditing = true;
+
+ if (IsParentSelected)
+ _isMouseWithinScope = true;
+ }
+ }
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ if (IsEditing)
+ Focus();
+ if (_viewItem == null)
+ _viewItem = GetDependencyObjectFromVisualTree(this, typeof(TreeViewItem)) as TreeViewItem;
+ }
+ void OnEditorLayoutUpdated(object sender, EventArgs e)
+ {
+ if (IsEditing && !IsKeyboardFocusWithin)
+ Focus();
+ }
+ void OnEditorKeyDown(object sender, KeyEventArgs e)
+ {
+ if (IsEditing && (e.Key == Key.Enter || e.Key == Key.F2))
+ {
+ IsEditing = false;
+ _canBeEdit = false;
+ }
+ }
+ void OnEditorLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
+ {
+ if (!IsKeyboardFocusWithin)
+ IsEditing = false;
+ }
+ void OnEditorIsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ if ((bool)e.OldValue && (bool)e.NewValue)
+ IsEditing = false;
+ }
+
+ bool IsParentSelected
+ {
+ get
+ {
+ if (_viewItem == null)
+ return true;
+ return _viewItem.IsSelected;
+ }
+ }
+
+ DependencyObject GetDependencyObjectFromVisualTree(DependencyObject startObject, Type type)
+ {
+ //Iterate the visual tree to get the parent(ItemsControl) of this control
+ DependencyObject parent = startObject;
+ while (parent != null)
+ {
+ if (type.IsInstanceOfType(parent))
+ break;
+ parent = VisualTreeHelper.GetParent(parent);
+ }
+ return parent;
+ }
+ }
+}
\ No newline at end of file
WPF/Common/WPF/Controls/TreeGridViewRowPresenter.cs 183(+183 -0)
diff --git a/WPF/Common/WPF/Controls/TreeGridViewRowPresenter.cs b/WPF/Common/WPF/Controls/TreeGridViewRowPresenter.cs
new file mode 100644
index 0000000..d83c29e
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeGridViewRowPresenter.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Shapes;
+
+namespace Common.WPF.Controls
+{
+ public class TreeGridViewRowPresenter : GridViewRowPresenter
+ {
+ public static DependencyProperty FirstColumnIndentProperty = DependencyProperty.Register("FirstColumnIndent", typeof(Double), typeof(TreeGridViewRowPresenter), new PropertyMetadata(0d));
+ public static DependencyProperty ExpanderProperty = DependencyProperty.Register("Expander", typeof(UIElement), typeof(TreeGridViewRowPresenter), new FrameworkPropertyMetadata(null, OnExpanderChanged));
+
+ UIElementCollection _childs;
+
+ static PropertyInfo _actualIndexProperty = typeof(GridViewColumn).GetProperty("ActualIndex", BindingFlags.NonPublic | BindingFlags.Instance);
+ static PropertyInfo _desiredWidthProperty = typeof(GridViewColumn).GetProperty("DesiredWidth", BindingFlags.NonPublic | BindingFlags.Instance);
+
+ public TreeGridViewRowPresenter()
+ {
+ _childs = new UIElementCollection(this, this);
+ DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(ColumnsProperty, typeof(TreeGridViewRowPresenter));
+ dpd?.AddValueChanged(this, (s, e) => EnsureLines());
+ }
+
+ public Double FirstColumnIndent
+ {
+ get { return (Double)GetValue(FirstColumnIndentProperty); }
+ set { SetValue(FirstColumnIndentProperty, value); }
+ }
+
+ public UIElement Expander
+ {
+ get { return (UIElement)GetValue(ExpanderProperty); }
+ set { SetValue(ExpanderProperty, value); }
+ }
+
+ static void OnExpanderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ // Use a second UIElementCollection so base methods work as original
+ TreeGridViewRowPresenter p = (TreeGridViewRowPresenter)d;
+
+ if (e.OldValue != null)
+ p._childs.Remove(e.OldValue as UIElement);
+ if (e.NewValue != null)
+ p._childs.Add((UIElement)e.NewValue);
+ }
+
+ public static readonly DependencyProperty SeparatorStyleProperty;
+ readonly List<FrameworkElement> _lines = new List<FrameworkElement>();
+ static TreeGridViewRowPresenter()
+ {
+ var defaultSeparatorStyle = new System.Windows.Style(typeof(Rectangle));
+ defaultSeparatorStyle.Setters.Add(new Setter(Shape.FillProperty, SystemColors.ControlLightBrush));
+ defaultSeparatorStyle.Setters.Add(new Setter(UIElement.IsHitTestVisibleProperty, false));
+ SeparatorStyleProperty = DependencyProperty.Register("SeparatorStyle", typeof(System.Windows.Style), typeof(TreeGridViewRowPresenter), new UIPropertyMetadata(defaultSeparatorStyle, SeparatorStyleChanged));
+ }
+
+ public System.Windows.Style SeparatorStyle
+ {
+ get { return (System.Windows.Style)GetValue(SeparatorStyleProperty); }
+ set { SetValue(SeparatorStyleProperty, value); }
+ }
+
+ static void SeparatorStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var presenter = (TreeGridViewRowPresenter)d;
+ var style = (System.Windows.Style)e.NewValue;
+ foreach (FrameworkElement line in presenter._lines)
+ line.Style = style;
+ }
+
+ void EnsureLines()
+ {
+ int count = Columns?.Count ?? 0;
+ count = count - _lines.Count;
+ for (var i = 0; i < count; i++)
+ {
+ var line = (FrameworkElement)Activator.CreateInstance(SeparatorStyle.TargetType);
+ //line = new Rectangle{Fill=Brushes.LightGray};
+ line.Style = SeparatorStyle;
+ AddVisualChild(line);
+ _lines.Add(line);
+ }
+ }
+
+ protected override Size ArrangeOverride(Size arrangeSize)
+ {
+ Size s = base.ArrangeOverride(arrangeSize);
+ if (Columns == null || Columns.Count == 0)
+ return s;
+ UIElement expander = Expander;
+
+ if (Columns != null)
+ EnsureLines();
+
+ double current = 0;
+ double max = arrangeSize.Width;
+ for (int x = 0; x < Columns.Count; x++)
+ {
+ GridViewColumn column = Columns[x];
+ // Actual index needed for column reorder
+ UIElement uiColumn = (UIElement)base.GetVisualChild((int)_actualIndexProperty.GetValue(column, null));
+
+ // Compute column width
+ double w = Math.Min(max, Double.IsNaN(column.Width) ? (double)_desiredWidthProperty.GetValue(column, null) : column.Width);
+
+ // First column indent
+ Rect rect;
+ if (x == 0 && expander != null)
+ {
+ double indent = FirstColumnIndent + expander.DesiredSize.Width;
+ rect = new Rect(current + indent, 0, w >= indent ? w - indent : 0, arrangeSize.Height);
+ }
+ else
+ rect = new Rect(current, 0, w, arrangeSize.Height);
+
+ uiColumn?.Arrange(rect);
+ if (x != 0)
+ {
+ var line = _lines[x];
+ Rect lineRect = new Rect(rect.X - 1.5, rect.Y, 1, rect.Height);
+ line.Measure(lineRect.Size);
+ line.Arrange(lineRect);
+ }
+ else if (expander != null)
+ {
+ double ew = FirstColumnIndent + expander.DesiredSize.Width <= w ? expander.DesiredSize.Width : w - FirstColumnIndent;
+ if (ew < 0)
+ ew = 0;
+ expander.Arrange(new Rect(FirstColumnIndent, 0, ew, expander.DesiredSize.Height));
+ }
+ max -= w;
+ current += w;
+ }
+ return s;
+ }
+ protected override Size MeasureOverride(Size constraint)
+ {
+ Size s = base.MeasureOverride(constraint);
+
+ // Measure expander
+ UIElement expander = Expander;
+ if (expander != null)
+ {
+ // Compute max measure
+ expander.Measure(constraint);
+ s.Width = Math.Max(s.Width, expander.DesiredSize.Width);
+ s.Height = Math.Max(s.Height, expander.DesiredSize.Height);
+ }
+
+ return s;
+ }
+ protected override Visual GetVisualChild(int index)
+ {
+ var count = base.VisualChildrenCount;
+ if (index < count)
+ return base.GetVisualChild(index);
+ if (index - count < _lines.Count)
+ return _lines[index - count];
+ return Expander;
+ }
+ protected override int VisualChildrenCount
+ {
+ get
+ {
+ if (Expander != null)
+ return base.VisualChildrenCount + 1 + _lines.Count;
+ return base.VisualChildrenCount + _lines.Count;
+ }
+ }
+ protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
+ {
+ var textBlock = visualAdded as TextBlock;
+ if (textBlock != null)
+ textBlock.VerticalAlignment = VerticalAlignment.Center;
+ base.OnVisualChildrenChanged(visualAdded, visualRemoved);
+ }
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Controls/TreeList/IItemComparer.cs b/WPF/Common/WPF/Controls/TreeList/IItemComparer.cs
new file mode 100644
index 0000000..e61c43b
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/IItemComparer.cs
@@ -0,0 +1,7 @@
+namespace Common.WPF.Controls.TreeList
+{
+ public interface IItemComparer
+ {
+ int Compare(TreeNodeViewModel x, TreeNodeViewModel y);
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Controls/TreeList/ITreeList.cs b/WPF/Common/WPF/Controls/TreeList/ITreeList.cs
new file mode 100644
index 0000000..c479736
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/ITreeList.cs
@@ -0,0 +1,10 @@
+namespace Common.WPF.Controls.TreeList
+{
+ public interface ITreeList
+ {
+ ObservableCollectionAdv<TreeNodeViewModel> Rows { get; }
+ object SelectedTreeNode { get; set; }
+ void SuspendSelection();
+ void ResumeSelection();
+ }
+}
diff --git a/WPF/Common/WPF/Controls/TreeList/RootTreeNodeViewModel.cs b/WPF/Common/WPF/Controls/TreeList/RootTreeNodeViewModel.cs
new file mode 100644
index 0000000..e8305d3
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/RootTreeNodeViewModel.cs
@@ -0,0 +1,135 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Windows.Controls;
+
+namespace Common.WPF.Controls.TreeList
+{
+ public class RootTreeNodeViewModel : TreeNodeViewModel, ITreeList
+ {
+ List<ITreeList> _treeLists;
+
+ public RootTreeNodeViewModel()
+ {
+ _treeLists = new List<ITreeList>();
+ Rows = new ObservableCollectionAdv<TreeNodeViewModel>();
+ IsExpanded = true;
+ IsRoot = true;
+ AssignToRoot(this);
+ }
+
+ public void AssignToTree(ITreeList treeList)
+ {
+ _treeLists.Add(treeList);
+ }
+ public void DisassignFromTree(ITreeList treeList)
+ {
+ _treeLists.Remove(treeList);
+ }
+ public void SetSource(IEnumerable source)
+ {
+ NotifyCollection = source as INotifyCollectionChanged;
+ Rows.Clear();
+ Nodes.Clear();
+ if (source != null)
+ foreach (TreeNodeViewModel item in source)
+ {
+ item.AssignToRoot(this);
+ Nodes.Add(item);
+ }
+ }
+
+ INotifyCollectionChanged _notifyCollection;
+ public INotifyCollectionChanged NotifyCollection
+ {
+ get { return _notifyCollection; }
+ set
+ {
+ if (NotifyCollection != null)
+ NotifyCollection.CollectionChanged -= ChildrenChanged;
+ _notifyCollection = value;
+ if (NotifyCollection != null)
+ NotifyCollection.CollectionChanged += ChildrenChanged;
+ }
+ }
+
+ void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewItems != null)
+ {
+ int index = e.NewStartingIndex;
+ for (int i = 0; i < e.NewItems.Count; i++)
+ Nodes.Insert(index + i, (TreeNodeViewModel)e.NewItems[i]);
+ }
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldItems != null)
+ {
+ int index = e.OldStartingIndex;
+ for (int i = 0; i < e.OldItems.Count; i++)
+ Nodes.RemoveAt(index + i);
+ }
+ break;
+ case NotifyCollectionChangedAction.Move:
+ case NotifyCollectionChangedAction.Replace:
+ case NotifyCollectionChangedAction.Reset:
+ SetSource((IEnumerable<TreeNodeViewModel>)NotifyCollection);
+ break;
+ }
+ }
+
+ #region ITreeList Members
+
+ public ObservableCollectionAdv<TreeNodeViewModel> Rows { get; }
+
+ public object SelectedTreeNode
+ {
+ get
+ {
+ return _treeLists.Count > 0 ? _treeLists[0].SelectedTreeNode : null;
+ }
+ set
+ {
+ _treeLists.ForEach(item =>
+ {
+ if (item.SelectedTreeNode != value)
+ item.SelectedTreeNode = value;
+ });
+ }
+ }
+
+ public void SuspendSelection()
+ {
+ _treeLists.ForEach(item => item.SuspendSelection());
+ }
+ public void ResumeSelection()
+ {
+ _treeLists.ForEach(item => item.ResumeSelection());
+ }
+
+ #endregion
+
+ public GridViewColumn SortColumn { get; private set; }
+ public ListSortDirection? SortDirection { get; private set; }
+ public IItemComparer ItemComparer { get; private set; }
+ public void RunSort(GridViewColumn column, IItemComparer itemComparer)
+ {
+ SortDirection = column == SortColumn ? (SortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending) : ListSortDirection.Ascending;
+ SortColumn = column;
+ RunSort(itemComparer);
+ }
+ public void RunSort(IItemComparer itemComparer)
+ {
+ if (SortDirection == null)
+ SortDirection = ListSortDirection.Ascending;
+ ItemComparer = itemComparer;
+ var selected = SelectedTreeNode;
+ Sort();
+ SelectedTreeNode = selected;
+ }
+ }
+}
diff --git a/WPF/Common/WPF/Controls/TreeList/RowExpander.cs b/WPF/Common/WPF/Controls/TreeList/RowExpander.cs
new file mode 100644
index 0000000..2b271c0
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/RowExpander.cs
@@ -0,0 +1,13 @@
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Common.WPF.Controls.TreeList
+{
+ public class RowExpander : Control
+ {
+ static RowExpander()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(RowExpander), new FrameworkPropertyMetadata(typeof(RowExpander)));
+ }
+ }
+}
WPF/Common/WPF/Controls/TreeList/SortBehavior.cs 150(+150 -0)
diff --git a/WPF/Common/WPF/Controls/TreeList/SortBehavior.cs b/WPF/Common/WPF/Controls/TreeList/SortBehavior.cs
new file mode 100644
index 0000000..bd9670f
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/SortBehavior.cs
@@ -0,0 +1,150 @@
+using System.ComponentModel;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+
+namespace Common.WPF.Controls.TreeList
+{
+ public static class SortBehavior
+ {
+ public static readonly DependencyProperty CanUserSortColumnsProperty = DependencyProperty.RegisterAttached("CanUserSortColumns", typeof(bool), typeof(SortBehavior), new FrameworkPropertyMetadata(OnCanUserSortColumnsChanged));
+ public static readonly DependencyProperty CanUseSortProperty = DependencyProperty.RegisterAttached("CanUseSort", typeof(bool), typeof(SortBehavior), new FrameworkPropertyMetadata(true));
+ public static readonly DependencyProperty SortDirectionProperty = DependencyProperty.RegisterAttached("SortDirection", typeof(ListSortDirection?), typeof(SortBehavior));
+ public static readonly DependencyProperty SortComparerProperty = DependencyProperty.RegisterAttached("SortComparer", typeof(IItemComparer), typeof(SortBehavior));
+ public static readonly DependencyProperty DefaultSortComparerProperty = DependencyProperty.RegisterAttached("DefaultSortComparer", typeof(IItemComparer), typeof(SortBehavior), new FrameworkPropertyMetadata(OnDefaultSortComparerChanged));
+
+ [AttachedPropertyBrowsableForType(typeof(ListView))]
+ public static bool GetCanUserSortColumns(ListView element)
+ {
+ return (bool)element.GetValue(CanUserSortColumnsProperty);
+ }
+ [AttachedPropertyBrowsableForType(typeof(ListView))]
+ public static void SetCanUserSortColumns(ListView element, bool value)
+ {
+ element.SetValue(CanUserSortColumnsProperty, value);
+ }
+
+ [AttachedPropertyBrowsableForType(typeof(ListView))]
+ public static IItemComparer GetDefaultSortComparer(ListView element)
+ {
+ return (IItemComparer)element.GetValue(DefaultSortComparerProperty);
+ }
+ [AttachedPropertyBrowsableForType(typeof(ListView))]
+ public static void SetDefaultSortComparer(ListView element, IItemComparer value)
+ {
+ element.SetValue(DefaultSortComparerProperty, value);
+ }
+
+ [AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
+ public static bool GetCanUseSort(GridViewColumn element)
+ {
+ if (element == null)
+ return false;
+ return (bool)element.GetValue(CanUseSortProperty);
+ }
+ [AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
+ public static void SetCanUseSort(GridViewColumn element, bool value)
+ {
+ element.SetValue(CanUseSortProperty, value);
+ }
+
+ [AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
+ public static ListSortDirection? GetSortDirection(GridViewColumn element)
+ {
+ return (ListSortDirection?)element.GetValue(SortDirectionProperty);
+ }
+ [AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
+ public static void SetSortDirection(GridViewColumn element, ListSortDirection? value)
+ {
+ element.SetValue(SortDirectionProperty, value);
+ }
+
+ [AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
+ public static IItemComparer GetSortComparer(GridViewColumn element)
+ {
+ return (IItemComparer)element.GetValue(SortComparerProperty);
+ }
+ [AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
+ public static void SetSortComparer(GridViewColumn element, IItemComparer value)
+ {
+ element.SetValue(SortComparerProperty, value);
+ }
+
+ static void OnCanUserSortColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var listView = (ListView)d;
+ if ((bool)e.NewValue)
+ {
+ listView.AddHandler(ButtonBase.ClickEvent, (RoutedEventHandler)OnColumnHeaderClick);
+ if (listView.IsLoaded)
+ DoInitialSort(listView);
+ else
+ listView.Loaded += OnLoaded;
+ }
+ else
+ listView.RemoveHandler(ButtonBase.ClickEvent, (RoutedEventHandler)OnColumnHeaderClick);
+ }
+ static void OnDefaultSortComparerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var listView = (ListView)d;
+ if (e.NewValue != null)
+ {
+ if (listView.IsLoaded)
+ DoInitialSort(listView);
+ else
+ listView.Loaded += OnLoaded;
+ }
+ }
+
+ static void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ var listView = (ListView)e.Source;
+ listView.Loaded -= OnLoaded;
+ DoInitialSort(listView);
+ }
+
+ static void DoInitialSort(ListView listView)
+ {
+ var defaultComparer = GetDefaultSortComparer(listView);
+ if (defaultComparer != null)
+ DoSort(listView, defaultComparer);
+ var gridView = (GridView)listView.View;
+ var column = gridView.Columns.FirstOrDefault(c => GetSortDirection(c) != null);
+ if (column != null)
+ DoSort(listView, column);
+ }
+
+ static void OnColumnHeaderClick(object sender, RoutedEventArgs e)
+ {
+ var columnHeader = e.OriginalSource as GridViewColumnHeader;
+ if (columnHeader != null && GetCanUseSort(columnHeader.Column))
+ DoSort((ListView)e.Source, columnHeader.Column);
+ }
+
+ static void DoSort(ListView listView, GridViewColumn column)
+ {
+ var tree = (TreeList)listView;
+ if (tree.Root.SortColumn != null)
+ SetSortDirection(tree.Root.SortColumn, null);
+ var comparer = GetSortComparer(column);
+ if (comparer != null)
+ {
+ tree.Root.RunSort(column, comparer);
+ SetSortDirection(column, tree.Root.SortDirection);
+ }
+ }
+ static void DoSort(ListView listView, IItemComparer comparer)
+ {
+ var tree = (TreeList)listView;
+ if (tree != null && comparer != null)
+ tree.Root.RunSort(comparer);
+ }
+
+ public static void DoSort(ListView listView)
+ {
+ var comparer = GetDefaultSortComparer(listView);
+ DoSort(listView, comparer);
+ }
+ }
+}
diff --git a/WPF/Common/WPF/Controls/TreeList/TreeItemCollection.cs b/WPF/Common/WPF/Controls/TreeList/TreeItemCollection.cs
new file mode 100644
index 0000000..6f92506
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/TreeItemCollection.cs
@@ -0,0 +1,63 @@
+using System;
+
+namespace Common.WPF.Controls.TreeList
+{
+ public class TreeItemCollection : ObservableCollectionAdv<TreeNodeViewModel>
+ {
+ TreeNodeViewModel _owner;
+
+ public TreeItemCollection(TreeNodeViewModel owner)
+ {
+ _owner = owner;
+ }
+
+ protected override void ClearItems()
+ {
+ while (Count != 0)
+ RemoveAt(Count - 1);
+ }
+ protected override void InsertItem(int index, TreeNodeViewModel item)
+ {
+ if (item == null)
+ throw new ArgumentNullException(nameof(item));
+
+ if (item.ParentNode != _owner)
+ {
+ if (item.ParentNode != null)
+ item.ParentNode.Nodes.Remove(item);
+ item.ParentNode = _owner;
+ item.Index = index;
+ if (_owner._sortOrder != null)
+ _owner._sortOrder.Add(index);
+ //item._tree = _owner.Tree;
+ for (int i = index; i < Count; i++)
+ this[i].Index++;
+ base.InsertItem(index, item);
+ }
+ }
+ protected override void RemoveItem(int index)
+ {
+ TreeNodeViewModel item = this[index];
+ if (_owner._sortOrder != null)
+ {
+ _owner._sortOrder.Remove(index);
+ for (int i = 0; i < _owner._sortOrder.Count; i++)
+ if (_owner._sortOrder[i] > index)
+ _owner._sortOrder[i]--;
+ }
+ item.Index = -1;
+ for (int i = index + 1; i < Count; i++)
+ this[i].Index--;
+ base.RemoveItem(index);
+ item.ParentNode = null;
+ item._root = null;
+ }
+ protected override void SetItem(int index, TreeNodeViewModel item)
+ {
+ if (item == null)
+ throw new ArgumentNullException(nameof(item));
+ RemoveAt(index);
+ InsertItem(index, item);
+ }
+ }
+}
\ No newline at end of file
WPF/Common/WPF/Controls/TreeList/TreeList.cs 139(+139 -0)
diff --git a/WPF/Common/WPF/Controls/TreeList/TreeList.cs b/WPF/Common/WPF/Controls/TreeList/TreeList.cs
new file mode 100644
index 0000000..66bbeac
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/TreeList.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Collections;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Input;
+
+namespace Common.WPF.Controls.TreeList
+{
+ public class TreeList : ListView, ITreeList
+ {
+ public static DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(IEnumerable), typeof(TreeList), new FrameworkPropertyMetadata(null, OnSourceChanged));
+ public IEnumerable Source
+ {
+ get { return (IEnumerable)GetValue(SourceProperty); }
+ set { SetValue(SourceProperty, value); }
+ }
+ static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var treeList = (TreeList)d;
+ treeList.Root.SetSource((IEnumerable)e.NewValue);
+ }
+
+ public static DependencyProperty RootProperty = DependencyProperty.Register("Root", typeof(RootTreeNodeViewModel), typeof(TreeList), new FrameworkPropertyMetadata(null, OnRootChanged));
+ public RootTreeNodeViewModel Root
+ {
+ get { return (RootTreeNodeViewModel)GetValue(RootProperty); }
+ set { SetValue(RootProperty, value); }
+ }
+ static void OnRootChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var treeList = (TreeList)d;
+ ((RootTreeNodeViewModel)e.OldValue)?.DisassignFromTree(treeList);
+ ((RootTreeNodeViewModel)e.NewValue).AssignToTree(treeList);
+ treeList.ItemsSource = ((RootTreeNodeViewModel)e.NewValue).Rows;
+ }
+
+ public static DependencyProperty SelectedTreeNodeProperty = DependencyProperty.Register("SelectedTreeNode", typeof(object), typeof(TreeList), new FrameworkPropertyMetadata(null, OnSelectedTreeItemChanged) { BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
+ public object SelectedTreeNode
+ {
+ get { return GetValue(SelectedTreeNodeProperty); }
+ set { SetValue(SelectedTreeNodeProperty, value); }
+ }
+ static void OnSelectedTreeItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var treeList = (TreeList)d;
+ treeList.SelectedItem = e.NewValue;
+ treeList.ScrollIntoView(treeList.SelectedTreeNode);
+ treeList.Root.SelectedTreeNode = e.NewValue;
+ }
+
+ public static DependencyProperty ItemActivatedCommandProperty = DependencyProperty.Register("ItemActivatedCommand", typeof(ICommand), typeof(TreeList));
+ public ICommand ItemActivatedCommand
+ {
+ get { return (ICommand)GetValue(ItemActivatedCommandProperty); }
+ set { SetValue(ItemActivatedCommandProperty, value); }
+ }
+ public static DependencyProperty ItemActivatedCommandParameterProperty = DependencyProperty.Register("ItemActivatedCommandParameter", typeof(object), typeof(TreeList));
+ public object ItemActivatedCommandParameter
+ {
+ get { return GetValue(ItemActivatedCommandParameterProperty); }
+ set { SetValue(ItemActivatedCommandParameterProperty, value); }
+ }
+
+ internal TreeNodeViewModel PendingFocusNode { get; set; }
+
+ public TreeList()
+ {
+ Root = new RootTreeNodeViewModel();
+ SelectionChanged += OnSelectionChanged;
+ ItemContainerGenerator.StatusChanged += ItemContainerGeneratorStatusChanged;
+ }
+
+ protected override DependencyObject GetContainerForItemOverride()
+ {
+ return new TreeListItem();
+ }
+ protected override bool IsItemItsOwnContainerOverride(object item)
+ {
+ return item is TreeListItem;
+ }
+ protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
+ {
+ var ti = element as TreeListItem;
+ var node = item as TreeNodeViewModel;
+ if (ti != null && node != null)
+ {
+ ti.Node = node;
+ ti.Tree = this;
+ base.PrepareContainerForItemOverride(element, node);
+ }
+ }
+ void ItemContainerGeneratorStatusChanged(object sender, EventArgs e)
+ {
+ if (ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated && PendingFocusNode != null)
+ {
+ var item = ItemContainerGenerator.ContainerFromItem(PendingFocusNode) as TreeListItem;
+ item?.Focus();
+ PendingFocusNode = null;
+ }
+ }
+
+ void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (e.OriginalSource == this && (e.AddedItems.Count > 0 || PendingFocusNode == null))
+ {
+ SelectedTreeNode = e.AddedItems.Count > 0 ? e.AddedItems[0] as TreeNodeViewModel : null;
+ SetFocus(SelectedTreeNode);
+ }
+ }
+ void SetFocus(object treeNode)
+ {
+ if (IsKeyboardFocused || IsKeyboardFocusWithin)
+ {
+ var item = ItemContainerGenerator.ContainerFromItem(treeNode) as TreeListItem;
+ if (item != null)
+ item.Focus();
+ else
+ PendingFocusNode = treeNode as TreeNodeViewModel;
+ }
+ }
+
+ #region ITreeList Members
+
+ ObservableCollectionAdv<TreeNodeViewModel> ITreeList.Rows => Root?.Rows;
+
+ public void SuspendSelection()
+ {
+ PendingFocusNode = SelectedTreeNode as TreeNodeViewModel;
+ }
+ public void ResumeSelection()
+ {
+ SelectedItem = SelectedTreeNode;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
WPF/Common/WPF/Controls/TreeList/TreeListItem.cs 106(+106 -0)
diff --git a/WPF/Common/WPF/Controls/TreeList/TreeListItem.cs b/WPF/Common/WPF/Controls/TreeList/TreeListItem.cs
new file mode 100644
index 0000000..88bc30c
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/TreeListItem.cs
@@ -0,0 +1,106 @@
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace Common.WPF.Controls.TreeList
+{
+ public class TreeListItem : ListViewItem, INotifyPropertyChanged
+ {
+ TreeNodeViewModel _node;
+ public TreeNodeViewModel Node
+ {
+ get { return _node; }
+ internal set
+ {
+ _node = value;
+ OnPropertyChanged("Node");
+ }
+ }
+
+ static TreeListItem()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeListItem), new FrameworkPropertyMetadata(typeof(TreeListItem)));
+ }
+
+ public TreeList Tree { get; internal set; }
+
+ protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
+ {
+ if (e.ChangedButton == MouseButton.Left && e.Source.GetType() != typeof(RowExpander) && Node != null && Node.HasChildren)
+ Node.IsExpanded = !Node.IsExpanded;
+ if (Tree != null)
+ {
+ if (Tree.ItemActivatedCommand != null && Tree.ItemActivatedCommand.CanExecute(Tree.ItemActivatedCommandParameter))
+ Tree.ItemActivatedCommand.Execute(Tree.ItemActivatedCommandParameter);
+ else
+ {
+ var viewModel = Tree.DataContext as IEditingBaseViewModel;
+ if (viewModel?.EditCommand != null && viewModel.EditCommand.CanExecute(null))
+ viewModel.EditCommand.Execute();
+ }
+ }
+ }
+ protected override void OnKeyDown(KeyEventArgs e)
+ {
+ if (Node != null)
+ switch (e.Key)
+ {
+ case Key.Right:
+ e.Handled = true;
+ if (!Node.IsExpanded)
+ {
+ Node.IsExpanded = true;
+ ChangeFocus(Node);
+ }
+ else if (Node.Nodes.Count > 0)
+ ChangeFocus(Node.Nodes[0]);
+ break;
+ case Key.Left:
+ e.Handled = true;
+ if (Node.IsExpanded && Node.HasChildren)
+ {
+ Node.IsExpanded = false;
+ ChangeFocus(Node);
+ }
+ else
+ ChangeFocus(Node.ParentNode);
+ break;
+ case Key.Subtract:
+ e.Handled = true;
+ Node.IsExpanded = false;
+ ChangeFocus(Node);
+ break;
+ case Key.Add:
+ e.Handled = true;
+ Node.IsExpanded = true;
+ ChangeFocus(Node);
+ break;
+ }
+ if (!e.Handled)
+ base.OnKeyDown(e);
+ }
+
+ void ChangeFocus(TreeNodeViewModel node)
+ {
+ if (Tree != null)
+ {
+ Tree.ScrollIntoView(node);
+ var item = Tree.ItemContainerGenerator.ContainerFromItem(node) as TreeListItem;
+ if (item != null)
+ item.Focus();
+ else
+ Tree.PendingFocusNode = node;
+ }
+ }
+
+ #region INotifyPropertyChanged Members
+ public event PropertyChangedEventHandler PropertyChanged;
+ void OnPropertyChanged(string name)
+ {
+ if (PropertyChanged != null)
+ PropertyChanged(this, new PropertyChangedEventArgs(name));
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Controls/TreeList/TreeNodeViewModel.cs b/WPF/Common/WPF/Controls/TreeList/TreeNodeViewModel.cs
new file mode 100644
index 0000000..fa9ea6c
--- /dev/null
+++ b/WPF/Common/WPF/Controls/TreeList/TreeNodeViewModel.cs
@@ -0,0 +1,410 @@
+using Common.Helpers;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Common.WPF.Controls.TreeList
+{
+ public class TreeNodeViewModel : BaseViewModel, IDisposable
+ {
+ public List<int> _sortOrder;
+ internal RootTreeNodeViewModel _root;
+ RootTreeNodeViewModel Root
+ {
+ get
+ {
+ if (_root == null && ParentNode != null)
+ _root = ParentNode.Root;
+ return _root;
+ }
+ }
+ public void AssignToRoot(RootTreeNodeViewModel root)
+ {
+ _root = root;
+ foreach (var child in Nodes)
+ child.AssignToRoot(root);
+ }
+
+ protected bool IsRoot { get; set; }
+ public int Level
+ {
+ get
+ {
+ if (this == Root)
+ return -1;
+ if (ParentNode == Root)
+ return 0;
+ return ParentNode.Level + 1;
+ }
+ }
+ public int Index { get; set; }
+ public bool IsSorted
+ {
+ get { return _sortOrder != null; }
+ }
+ public int VisualIndex
+ {
+ get { return ParentNode?._sortOrder?.IndexOf(Index) ?? Index; }
+ }
+ public TreeNodeViewModel ParentNode { get; set; }
+ public TreeItemCollection Nodes { get; private set; }
+
+ protected bool InsertSorted
+ {
+ get { return true; }
+ }
+
+ internal TreeNodeViewModel()
+ {
+ IsRoot = false;
+ _root = null;
+ Index = -1;
+ Nodes = new TreeItemCollection(this);
+ Nodes.CollectionChanged += ChildrenChanged;
+ Nodes.CollectionChanged += OnChildrenChanged;
+ }
+
+ bool IsVisible
+ {
+ get
+ {
+ TreeNodeViewModel node = ParentNode;
+ while (node != null)
+ {
+ if (!node.IsExpanded)
+ return false;
+ node = node.ParentNode;
+ }
+ return true;
+ }
+ }
+ TreeNodeViewModel BottomNode
+ {
+ get
+ {
+ if (ParentNode != null)
+ {
+ if (ParentNode.NextNode != null)
+ return ParentNode.NextNode;
+ return ParentNode.BottomNode;
+ }
+ return null;
+ }
+ }
+ TreeNodeViewModel NextVisibleNode
+ {
+ get
+ {
+ if (IsExpanded && Nodes.Count > 0)
+ return GetNodeByVisualIndex(0);
+ return NextNode ?? BottomNode;
+ }
+ }
+ TreeNodeViewModel NextNode
+ {
+ get
+ {
+ if (ParentNode != null)
+ {
+ int index = VisualIndex;
+ if (index >= 0 && index < ParentNode.Nodes.Count - 1)
+ return ParentNode.GetNodeByVisualIndex(index + 1);
+ }
+ return null;
+ }
+ }
+ int VisibleChildrenCount
+ {
+ get { return AllVisibleChildren.Count(); }
+ }
+ IEnumerable<TreeNodeViewModel> AllVisibleChildren
+ {
+ get
+ {
+ int level = Level;
+ TreeNodeViewModel node = this;
+ while (true)
+ {
+ node = node.NextVisibleNode;
+ if (node != null && node.Level > level)
+ yield return node;
+ else
+ break;
+ }
+ }
+ }
+
+ protected void OnChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ }
+ void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (IsExpanded && Root != null)
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewItems != null)
+ {
+ if (InsertSorted && Root?.ItemComparer != null)
+ InnerSort();
+ int newVisualIndex = InsertSorted && _sortOrder == null ? e.NewStartingIndex : _sortOrder.IndexOf(e.NewStartingIndex);
+ int index;
+ if (newVisualIndex == 0)
+ index = Root.Rows.IndexOf(this);
+ else
+ {
+ var previosIndex = _sortOrder?[newVisualIndex - 1] ?? newVisualIndex - 1;
+ index = Root.Rows.IndexOf(Nodes[previosIndex]) + Nodes[previosIndex].VisibleChildrenCount;
+ }
+ foreach (TreeNodeViewModel node in e.NewItems)
+ {
+ Root.Rows.Insert(index + 1, node);
+ node.CreateChildrenRows();
+ index++;
+ }
+ }
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ foreach (TreeNodeViewModel node in e.OldItems)
+ node.DropChildrenRows(true);
+ break;
+ case NotifyCollectionChangedAction.Move:
+ case NotifyCollectionChangedAction.Replace:
+ case NotifyCollectionChangedAction.Reset:
+ DropChildrenRows(false);
+ CreateChildrenRows();
+ break;
+ }
+ OnPropertyChanged(() => HasChildren);
+ OnPropertyChanged(() => Nodes);
+ }
+ void DropChildrenRows(bool removeParent)
+ {
+ int start = Root.Rows.IndexOf(this);
+ if (start >= 0 || IsRoot)
+ {
+ int count = VisibleChildrenCount;
+ if (removeParent)
+ count++;
+ else
+ start++;
+ Root.Rows.RemoveRange(start, count);
+ }
+ }
+ void CreateChildrenRows()
+ {
+ int index = Root.Rows.IndexOf(this);
+ if (index >= 0 || IsRoot)
+ {
+ var nodes = AllVisibleChildren.ToArray();
+ Root.Rows.InsertRange(index + 1, nodes);
+ //if (nodes.Contains(Tree.SelectedTreeItem))
+ // Tree.ResumeSelection();
+ }
+ }
+
+ bool _isExpanded;
+ public bool IsExpanded
+ {
+ get { return _isExpanded; }
+ set
+ {
+ if (value != IsExpanded)
+ {
+ if (value)
+ {
+ _isExpanded = true;
+ if (Root != null)
+ {
+ CreateChildrenRows();
+ Root.ResumeSelection();
+ }
+ }
+ else
+ {
+ if (Root != null)
+ {
+ Root.SuspendSelection();
+ DropChildrenRows(false);
+ }
+ _isExpanded = false;
+ }
+ OnPropertyChanged(() => HasChildren);
+ OnPropertyChanged(() => IsExpanded);
+ }
+ }
+ }
+
+ public bool IsSelected
+ {
+ get { return Root != null && Root.SelectedTreeNode == this; }
+ set
+ {
+ if (Root != null)
+ {
+ ExpandToThis();
+ Root.SelectedTreeNode = this;
+ }
+ OnPropertyChanged(() => IsSelected);
+ }
+ }
+ public bool HasChildren
+ {
+ get { return Nodes.Count > 0; }
+ }
+
+ public void ExpandToThis()
+ {
+ var parent = ParentNode;
+ while (parent != null)
+ {
+ parent.IsExpanded = true;
+ parent = parent.ParentNode;
+ }
+ }
+ public void CollapseChildren(bool withSelf = true)
+ {
+ ProcessAllChildren(this, withSelf, item => item.IsExpanded = false);
+ }
+ public void ExpandChildren(bool withSelf = true)
+ {
+ ProcessAllChildren(this, withSelf, item => item.IsExpanded = true);
+ }
+ void ProcessAllChildren(TreeNodeViewModel parent, bool withSelf, Action<TreeNodeViewModel> action)
+ {
+ if (withSelf)
+ action(parent);
+ foreach (TreeNodeViewModel t in parent.Nodes)
+ ProcessAllChildren(t, true, action);
+ }
+
+ protected void Sort()
+ {
+ if (Root?.ItemComparer != null)
+ {
+ DropChildrenRows(false);
+ InnerSort();
+ CreateChildrenRows();
+ }
+ }
+ protected void InnerSort()
+ {
+ _sortOrder = new List<int>();
+ if (Nodes.Count > 0)
+ {
+ var list = Nodes.ToList();
+ QSort.Sort(list, Root.ItemComparer.Compare, Root.SortDirection != ListSortDirection.Ascending);
+ foreach (TreeNodeViewModel t in list)
+ {
+ t.InnerSort();
+ _sortOrder.Add(t.Index);
+ }
+ }
+ }
+
+ protected TreeNodeViewModel GetNodeByVisualIndex(int index)
+ {
+ return IsSorted ? Nodes[_sortOrder[index]] : Nodes[index];
+ }
+
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ if (Nodes != null)
+ {
+ Nodes.CollectionChanged -= ChildrenChanged;
+ Nodes = null;
+ }
+ }
+
+ #endregion
+ }
+
+ public class TreeNodeViewModel<T> : TreeNodeViewModel
+ where T : TreeNodeViewModel<T>
+ {
+ protected TreeNodeViewModel()
+ {
+ }
+ public TreeNodeViewModel(IEnumerable<T> children)
+ : this()
+ {
+ Nodes.InsertRange(0, (TreeItemCollection)children);
+ }
+
+ public T Parent
+ {
+ get { return ParentNode as T; }
+ }
+ public T this[int index]
+ {
+ get { return Nodes[index] as T; }
+ }
+ public void AddChild(T item)
+ {
+ Nodes.Add(item);
+ }
+ public void AddChildFirst(T item)
+ {
+ Nodes.Insert(0, item);
+ }
+ public void InsertChild(T item)
+ {
+ var index = Parent.Nodes.IndexOf(this);
+ Parent.Nodes.Insert(index + 1, item);
+ }
+
+ public void InsertTo(T item, bool isAfterItem)
+ {
+ var index = Parent.Nodes.IndexOf(this);
+ Parent.Nodes.Insert(index + (isAfterItem? 1: 0), item);
+ }
+ public void RemoveChild(T item)
+ {
+ Nodes.Remove(item);
+ }
+ public void ClearChildren()
+ {
+ Nodes.Clear();
+ }
+ public int ChildrenCount
+ {
+ get { return Nodes.Count; }
+ }
+ public IEnumerable<T> Children
+ {
+ get
+ {
+ return Nodes.Cast<T>();
+ }
+ }
+ public List<T> GetAllChildren(bool withSelf = true)
+ {
+ var list = new List<T>();
+ if (withSelf)
+ list.Add((T)this);
+ foreach (TreeNodeViewModel<T> child in Nodes)
+ list.AddRange(child.GetAllChildren());
+ return list;
+ }
+ public List<T> GetAllParents()
+ {
+ if (Parent == null)
+ return new List<T>();
+ else
+ {
+ List<T> allParents = Parent.GetAllParents();
+ allParents.Add(Parent);
+ return allParents;
+ }
+ }
+ public T GetChildByVisualIndex(int index)
+ {
+ return GetNodeByVisualIndex(index) as T;
+ }
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Converters/BoolToVisibilityConverter.cs b/WPF/Common/WPF/Converters/BoolToVisibilityConverter.cs
new file mode 100644
index 0000000..b12dc49
--- /dev/null
+++ b/WPF/Common/WPF/Converters/BoolToVisibilityConverter.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ public class BoolToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return (bool)value ? Visibility.Visible : parameter != null && parameter.ToString() == "True" ? Visibility.Hidden : Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Converters/CanExpandConverter.cs b/WPF/Common/WPF/Converters/CanExpandConverter.cs
new file mode 100644
index 0000000..b6782ff
--- /dev/null
+++ b/WPF/Common/WPF/Converters/CanExpandConverter.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ public class CanExpandConverter : IValueConverter
+ {
+ public object Convert(object obj, Type type, object parameter, CultureInfo culture)
+ {
+ return (bool)obj ? Visibility.Visible : Visibility.Hidden;
+ }
+
+ public object ConvertBack(object obj, Type type, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Converters/ColorToBrushConverter.cs b/WPF/Common/WPF/Converters/ColorToBrushConverter.cs
new file mode 100644
index 0000000..515aff7
--- /dev/null
+++ b/WPF/Common/WPF/Converters/ColorToBrushConverter.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace Common.WPF.Converters
+{
+ public class ColorToBrushConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ switch (value.ToString())
+ {
+ case "�������":
+ return new SolidColorBrush(Colors.Crimson);
+ case "������":
+ return new SolidColorBrush(Colors.Yellow);
+ case "������":
+ return new SolidColorBrush(Colors.Green);
+ case "�������":
+ return new SolidColorBrush(Colors.SkyBlue);
+ case "�����":
+ return new SolidColorBrush(Colors.Blue);
+ case "����������":
+ return new SolidColorBrush(Colors.Violet);
+ case "�����":
+ return new SolidColorBrush(Colors.White);
+ default:
+ if (value.ToString() != "")
+ {
+ return (SolidColorBrush)new BrushConverter().ConvertFrom(value.ToString());
+ }
+ return new SolidColorBrush(Colors.Black);
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Converters/ColumnWidthConverter.cs b/WPF/Common/WPF/Converters/ColumnWidthConverter.cs
new file mode 100644
index 0000000..10171e6
--- /dev/null
+++ b/WPF/Common/WPF/Converters/ColumnWidthConverter.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ /// <summary>
+ /// This converter targets a column header,
+ /// in order to take its width to zero when
+ /// it should be hidden
+ /// </summary>
+ public class ColumnWidthConverter
+ : IValueConverter
+ {
+ public object Convert(
+ object value,
+ Type targetType,
+ object parameter,
+ System.Globalization.CultureInfo culture)
+ {
+ var isVisible = (bool)value;
+ var width = double.Parse(parameter as string);
+ return isVisible ? width : 0.0;
+ }
+
+
+ public object ConvertBack(
+ object value,
+ Type targetType,
+ object parameter,
+ System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+
+ }
+}
diff --git a/WPF/Common/WPF/Converters/EnumToDescrConverter.cs b/WPF/Common/WPF/Converters/EnumToDescrConverter.cs
new file mode 100644
index 0000000..95eeda0
--- /dev/null
+++ b/WPF/Common/WPF/Converters/EnumToDescrConverter.cs
@@ -0,0 +1,63 @@
+//using System;
+//using System.Collections.Generic;
+//using System.ComponentModel;
+//using System.Linq;
+//using System.Reflection;
+//using System.Text;
+//using System.Windows.Data;
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Reflection;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ public class EnumToDescriptionConverter: IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (value == null)
+ return "";
+ if (value.GetType().IsEnum)
+ return ((Enum)value).ToDescription();
+ return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return value;
+ }
+ }
+
+ public static class ExtensionMethods
+ {
+ public static bool IsNotNullOrEmpty<T>(this ICollection<T> collection)
+ {
+ return collection != null && collection.Count > 0;
+ }
+
+ public static bool IsExactly<T>(this object obj)
+ {
+ return obj != null && obj.GetType() == typeof(T);
+ }
+
+ public static string ToDescription(this Enum value)
+ {
+#if NET4
+ FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
+#else
+ FieldInfo fieldInfo = value.GetType().GetTypeInfo().GetField(value.ToString());
+#endif
+ if (fieldInfo != null)
+ {
+ DescriptionAttribute[] descriptionAttributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
+ if (descriptionAttributes.Length > 0)
+ return descriptionAttributes[0].Description;
+ return value.ToString();
+ }
+ return null;
+ }
+ }
+}
diff --git a/WPF/Common/WPF/Converters/InverseBooleanConverter.cs b/WPF/Common/WPF/Converters/InverseBooleanConverter.cs
new file mode 100644
index 0000000..9398fd8
--- /dev/null
+++ b/WPF/Common/WPF/Converters/InverseBooleanConverter.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ public class InverseBooleanConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if ((bool)value)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if ((bool)value)
+ {
+ return false;
+ }
+ return true;
+ }
+ }
+}
diff --git a/WPF/Common/WPF/Converters/InversedBoolToVisibilityConverter.cs b/WPF/Common/WPF/Converters/InversedBoolToVisibilityConverter.cs
new file mode 100644
index 0000000..9b37f06
--- /dev/null
+++ b/WPF/Common/WPF/Converters/InversedBoolToVisibilityConverter.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ public class InversedBoolToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return (bool)value ? Visibility.Collapsed : Visibility.Visible;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Converters/LevelToIndentConverter.cs b/WPF/Common/WPF/Converters/LevelToIndentConverter.cs
new file mode 100644
index 0000000..b2c08e5
--- /dev/null
+++ b/WPF/Common/WPF/Converters/LevelToIndentConverter.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ /// <summary>
+ /// Convert Level to left margin
+ /// Pass a prarameter if you want a unit length other than default.
+ /// </summary>
+ public class LevelToIndentConverter : IValueConverter
+ {
+ public object Convert(object o, Type type, object parameter, CultureInfo culture)
+ {
+ Double indentSize = 5;
+ if (parameter != null)
+ Double.TryParse(parameter.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out indentSize);
+
+ return (int)o * indentSize + " 0 0 0";
+ }
+
+ public object ConvertBack(object o, Type type, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/WPF/Common/WPF/Converters/RadioButtonToIntConverter.cs b/WPF/Common/WPF/Converters/RadioButtonToIntConverter.cs
new file mode 100644
index 0000000..cdd86bb
--- /dev/null
+++ b/WPF/Common/WPF/Converters/RadioButtonToIntConverter.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ public class RadioButtonToIntConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ int integer = (int)value;
+ if (integer == int.Parse(parameter.ToString()))
+ return true;
+ return false;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return parameter;
+ }
+ }
+}
diff --git a/WPF/Common/WPF/Converters/RoundProgressPathConverter.cs b/WPF/Common/WPF/Converters/RoundProgressPathConverter.cs
new file mode 100644
index 0000000..e759242
--- /dev/null
+++ b/WPF/Common/WPF/Converters/RoundProgressPathConverter.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Linq;
+using System.Windows;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace Common.WPF.Converters
+{
+ public class RoundProgressPathConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (values?.Contains(DependencyProperty.UnsetValue) != false)
+ return DependencyProperty.UnsetValue;
+
+ var v = (double)values[0]; // значение слайдера
+ var min = (double)values[1]; // минимальное значение
+ var max = (double)values[2]; // максимальное
+
+ var ratio = (v - min) / (max - min); // какую долю окружности закрашивать
+ var isFull = ratio >= 1; // для случая полной окружности нужна особая обработка
+ var angleRadians = 2 * Math.PI * ratio;
+ var angleDegrees = 360 * ratio;
+
+ // внешний радиус примем за 1, растянем в XAML'е.
+ var outerR = 1;
+ // как параметр передадим долю радиуса, которую занимает внутренняя часть
+ var innerR = System.Convert.ToDouble(parameter, System.Globalization.CultureInfo.InvariantCulture) * outerR;
+ // вспомогательные штуки: вектор направления вверх
+ var vector1 = new Vector(0, -1);
+ // ... и на конечную точку дуги
+ var vector2 = new Vector(Math.Sin(angleRadians), -Math.Cos(angleRadians));
+ var center = new Point();
+
+ var geo = new StreamGeometry();
+ geo.FillRule = FillRule.EvenOdd;
+
+ using (var ctx = geo.Open())
+ {
+ Size outerSize = new Size(outerR, outerR),
+ innerSize = new Size(innerR, innerR);
+
+ if (!isFull)
+ {
+ Point p1 = center + vector1 * outerR, p2 = center + vector2 * outerR,
+ p3 = center + vector2 * innerR, p4 = center + vector1 * innerR;
+
+ ctx.BeginFigure(p1, isFilled: true, isClosed: true);
+ ctx.ArcTo(p2, outerSize, angleDegrees, isLargeArc: angleDegrees > 180,
+ sweepDirection: SweepDirection.Clockwise, isStroked: true,
+ isSmoothJoin: false);
+ ctx.LineTo(p3, isStroked: true, isSmoothJoin: false);
+ ctx.ArcTo(p4, innerSize, -angleDegrees, isLargeArc: angleDegrees > 180,
+ sweepDirection: SweepDirection.Counterclockwise, isStroked: true,
+ isSmoothJoin: false);
+
+ Point diag1 = new Point(-outerR, -outerR),
+ diag2 = new Point(outerR, outerR);
+ ctx.BeginFigure(diag1, isFilled: false, isClosed: false);
+ ctx.LineTo(diag2, isStroked: false, isSmoothJoin: false);
+ }
+ else
+ {
+ Point p1 = center + vector1 * outerR, p2 = center - vector1 * outerR,
+ p3 = center + vector1 * innerR, p4 = center - vector1 * innerR;
+
+ ctx.BeginFigure(p1, isFilled: true, isClosed: true);
+ ctx.ArcTo(p2, outerSize, 180, isLargeArc: false,
+ sweepDirection: SweepDirection.Clockwise, isStroked: true,
+ isSmoothJoin: false);
+ ctx.ArcTo(p1, outerSize, 180, isLargeArc: false,
+ sweepDirection: SweepDirection.Clockwise, isStroked: true,
+ isSmoothJoin: false);
+ ctx.BeginFigure(p3, isFilled: true, isClosed: true);
+ ctx.ArcTo(p4, innerSize, 180, isLargeArc: false,
+ sweepDirection: SweepDirection.Clockwise, isStroked: true,
+ isSmoothJoin: false);
+ ctx.ArcTo(p3, innerSize, 180, isLargeArc: false,
+ sweepDirection: SweepDirection.Clockwise, isStroked: true,
+ isSmoothJoin: false);
+ }
+ }
+
+ geo.Freeze();
+ return geo;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/WPF/Common/WPF/Converters/StatusToColorConverter.cs b/WPF/Common/WPF/Converters/StatusToColorConverter.cs
new file mode 100644
index 0000000..cf73b10
--- /dev/null
+++ b/WPF/Common/WPF/Converters/StatusToColorConverter.cs
@@ -0,0 +1,42 @@
+using Common.Helpers;
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace Common.WPF.Converters
+{
+ public class StatusToColorConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ switch ((Status)value)
+ {
+
+ case Status.Default:
+ return new SolidColorBrush(Colors.DarkOrange);
+ case Status.ExportInProgress:
+ return new SolidColorBrush(Colors.DeepPink);
+ case Status.Warning:
+ return new SolidColorBrush(Colors.Gold);
+ case Status.SpecialWarning:
+ return new SolidColorBrush(Colors.Orange);
+ case Status.Error:
+ case Status.OperationFailed:
+ return new SolidColorBrush(Colors.Crimson);
+ case Status.OperationSuccess:
+ return new SolidColorBrush(Colors.LimeGreen);
+ case Status.Normal:
+ return new SolidColorBrush(Colors.Transparent);
+ default:
+ return new SolidColorBrush(Colors.Crimson);
+ }
+
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
WPF/Common/WPF/Converters/ValueConverter.cs 24(+24 -0)
diff --git a/WPF/Common/WPF/Converters/ValueConverter.cs b/WPF/Common/WPF/Converters/ValueConverter.cs
new file mode 100644
index 0000000..a8d0094
--- /dev/null
+++ b/WPF/Common/WPF/Converters/ValueConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Windows.Data;
+
+namespace Common.WPF.Converters
+{
+ public class IntToStringConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return value.ToString();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ string str = value as string;
+ if (string.IsNullOrEmpty(str))
+ return 0;
+
+ int.TryParse(str, out int res);
+
+ return res;
+ }
+ }
+}
WPF/Common/WPF/Dictionary.xaml 52(+52 -0)
diff --git a/WPF/Common/WPF/Dictionary.xaml b/WPF/Common/WPF/Dictionary.xaml
new file mode 100644
index 0000000..9f8b794
--- /dev/null
+++ b/WPF/Common/WPF/Dictionary.xaml
@@ -0,0 +1,52 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:converters="clr-namespace:Common.WPF.Converters">
+ <!--<conv:DoubleConverter x:Key="DoubleConverter"/>-->
+ <converters:IntToStringConverter x:Key="IntToStringConverter"/>
+ <converters:RoundProgressPathConverter x:Key="RoundProgressPathConverter"/>
+ <converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
+ <converters:EnumToDescriptionConverter x:Key="EnumToDescriptionConverter"/>
+ <converters:InversedBoolToVisibilityConverter x:Key="InversedBoolToVisibilityConverter"/>
+
+ <Style TargetType="{x:Type Button}" BasedOn="{StaticResource DefaultButton}"/>
+
+ <!--<BitmapImage x:Key="MainIcon" UriSource="pack://application:,,,/PasswordApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null;component/storage.ico" />-->
+
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="Style/TextBlockStyle.xaml" />
+ <ResourceDictionary Source="Style/TextBoxStyle.xaml" />
+ <ResourceDictionary Source="Style/TabControlStyle.xaml" />
+ <ResourceDictionary Source="Style/ExpanderStyle.xaml" />
+ <ResourceDictionary Source="Style/ProgressbarStyle.xaml" />
+ <ResourceDictionary Source="Style/Colors.xaml" />
+ <ResourceDictionary Source="Style/GroupBoxStyle.xaml" />
+ <ResourceDictionary Source="Style/ButtonStyle.xaml" />
+ <ResourceDictionary Source="Style/ListBoxStyle.xaml" />
+ <ResourceDictionary Source="Style/ExpandCollapseToggleStyle.xaml" />
+ <ResourceDictionary Source="Style/WindowStyle.xaml" />
+ <ResourceDictionary Source="Style/ScrollBarStyle.xaml" />
+ <ResourceDictionary Source="Style/ComboBoxStyle.xaml" />
+
+ <ResourceDictionary Source="Icons/Copy.xaml" />
+ <ResourceDictionary Source="Icons/Delete.xaml" />
+ <ResourceDictionary Source="Icons/Read.xaml" />
+ <ResourceDictionary Source="Icons/VisibleHide.xaml" />
+ <ResourceDictionary Source="Icons/VisibleOn.xaml" />
+ <ResourceDictionary Source="Icons/Open.xaml" />
+ <ResourceDictionary Source="Icons/Search.xaml" />
+ <ResourceDictionary Source="Icons/Warning.xaml" />
+ <ResourceDictionary Source="Icons/Help.xaml" />
+ <ResourceDictionary Source="Icons/TreeListExpander.xaml" />
+ <ResourceDictionary Source="Icons/Add.xaml" />
+ <ResourceDictionary Source="Icons/AddSub.xaml" />
+ <ResourceDictionary Source="Icons/DeleteItem.xaml" />
+ <ResourceDictionary Source="Icons/Up.xaml" />
+ <ResourceDictionary Source="Icons/Down.xaml" />
+ <ResourceDictionary Source="Icons/StartEndIcon.xaml" />
+ <ResourceDictionary Source="Icons/DeviceDeviceIcon.xaml" />
+ <ResourceDictionary Source="Icons/Pointer.xaml" />
+ <ResourceDictionary Source="Icons/Substract.xaml" />
+ <ResourceDictionary Source="Icons/Settings.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Icons/Add.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/Add.xaml b/WPF/Common/WPF/Icons/Add.xaml
new file mode 100644
index 0000000..45185f3
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Add.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="AddSub" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 39,46L 46,46L 46,39L 51,39L 51,46L 58,46L 58,51L 51,51L 51,58L 46,58L 46,51L 39,51L 39,46 Z M 31,25L 38,25L 38,18L 43,18L 43,25L 50,25L 50,30L 43,30L 43,37L 38,37L 38,30L 31,30L 31,25 Z M 18,39L 25,39L 25,32L 30,32L 30,39L 37,39L 37,44L 30,44L 30,51L 25,51L 25,44L 18,44L 18,39 Z "/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/AddSub.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/AddSub.xaml b/WPF/Common/WPF/Icons/AddSub.xaml
new file mode 100644
index 0000000..1d91894
--- /dev/null
+++ b/WPF/Common/WPF/Icons/AddSub.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="Add" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 35,19L 41,19L 41,35L 57,35L 57,41L 41,41L 41,57L 35,57L 35,41L 19,41L 19,35L 35,35L 35,19 Z "/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Copy.xaml 7(+7 -0)
diff --git a/WPF/Common/WPF/Icons/Copy.xaml b/WPF/Common/WPF/Icons/Copy.xaml
new file mode 100644
index 0000000..66db87a
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Copy.xaml
@@ -0,0 +1,7 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Viewbox x:Key="Copy" Width="24" Height="24">
+ <Canvas Width="24" Height="24">
+ <Path Data="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z" Fill="Black" />
+ </Canvas>
+ </Viewbox>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Delete.xaml 9(+9 -0)
diff --git a/WPF/Common/WPF/Icons/Delete.xaml b/WPF/Common/WPF/Icons/Delete.xaml
new file mode 100644
index 0000000..35fb3c9
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Delete.xaml
@@ -0,0 +1,9 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Geometry x:Key="DeleteData">M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19M8.46,11.88L9.87,10.47L12,12.59L14.12,10.47L15.53,11.88L13.41,14L15.53,16.12L14.12,17.53L12,15.41L9.88,17.53L8.47,16.12L10.59,14L8.46,11.88M15.5,4L14.5,3H9.5L8.5,4H5V6H19V4H15.5Z</Geometry>
+ <Viewbox x:Key="Delete" Width="24" Height="24">
+ <Canvas Width="24" Height="24">
+ <Path Data="{DynamicResource DeleteData}" Fill="Black" />
+ </Canvas>
+ </Viewbox>
+
+</ResourceDictionary>
WPF/Common/WPF/Icons/DeleteItem.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/DeleteItem.xaml b/WPF/Common/WPF/Icons/DeleteItem.xaml
new file mode 100644
index 0000000..33dd131
--- /dev/null
+++ b/WPF/Common/WPF/Icons/DeleteItem.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="DeleteItem" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 14,51L 14,24L 40,24L 40,32L 46,32L 46,43L 40,43L 40,51L 14,51 Z M 43,40L 43,35L 17,35L 17,40L 43,40 Z M 37,43L 17,43L 17,48L 37,48L 37,43 Z M 37,32L 37,27L 17,27L 17,32L 37,32 Z M 50.2708,42.3542L 54.625,38L 50.2708,33.6458L 52.6458,31.2708L 57,35.625L 61.3542,31.2708L 63.7291,33.6458L 59.375,38L 63.7292,42.3542L 61.3542,44.7292L 57,40.375L 52.6458,44.7292L 50.2708,42.3542 Z "/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/DeviceDeviceIcon.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/DeviceDeviceIcon.xaml b/WPF/Common/WPF/Icons/DeviceDeviceIcon.xaml
new file mode 100644
index 0000000..ec618bd
--- /dev/null
+++ b/WPF/Common/WPF/Icons/DeviceDeviceIcon.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="DeviceDeviceIcon" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 2,2L 2,17L 5,17L 5,5L 8,5L 8,17L 11,17L 11,2L 2,2 Z M 14,2L 14,17L 17,17L 17,5L 20,5L 20,17L 23,17L 23,2L 14,2 Z"/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Down.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/Down.xaml b/WPF/Common/WPF/Icons/Down.xaml
new file mode 100644
index 0000000..6dd5774
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Down.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="Down" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 42,19.0002L 34,19.0002L 34,43.7502L 24,33.7502L 24,44.2502L 38,58.2502L 52,44.2502L 52,33.7502L 42,43.7502L 42,19.0002 Z "/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Help.xaml 23(+23 -0)
diff --git a/WPF/Common/WPF/Icons/Help.xaml b/WPF/Common/WPF/Icons/Help.xaml
new file mode 100644
index 0000000..2b25a8c
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Help.xaml
@@ -0,0 +1,23 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="Help" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="#1585d0" Geometry="F1 M 15.7493,0.494669C 7.052,0.494669 0,7.54667 0,16.244C 0,24.948 7.052,32 15.7493,32C 24.4533,32 31.5053,24.948 31.5053,16.244C 31.5053,7.54667 24.4533,0.494669 15.7493,0.494669 Z "/>
+ <GeometryDrawing Brush="#BBD0DE" Geometry="F1 M 15.3458,22.268C 13.5787,22.268 12.3203,23.5247 12.3203,25.3578C 12.3203,27.1249 13.5457,28.4477 15.3458,28.4477C 17.2169,28.4477 18.4026,27.1249 18.4026,25.3578C 18.3646,23.5247 17.1772,22.268 15.3458,22.268 Z "/>
+ <GeometryDrawing Brush="#BBD0DE" Geometry="F1 M 15.8164,4.77245C 13.4103,4.77245 11.4037,5.44954 10.1453,6.15967L 11.3014,9.86884C 12.1849,9.25615 13.5457,8.84328 14.6621,8.84328C 16.3647,8.88127 17.1459,9.69378 17.1459,10.8812C 17.1459,12.0108 16.2607,13.1272 15.1707,14.4549C 13.6431,16.255 13.0684,18.0221 13.1708,19.7512L 13.2038,20.6347L 17.7189,20.6347L 17.7189,20.022C 17.6875,18.4944 18.2358,17.1716 19.4546,15.7777C 20.7444,14.3525 22.3777,12.6499 22.3777,10.0687C 22.3777,7.24963 20.3067,4.77245 15.8164,4.77245 Z "/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+ <Viewbox x:Key="Alert" Width="48" Height="48">
+ <Canvas Width="24" Height="24">
+ <Path Data="M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z" Fill="Black" />
+ </Canvas>
+ </Viewbox>
+ <Viewbox x:Key="Info" Width="48" Height="48">
+ <Canvas Width="24" Height="24">
+ <Path Data="M13,9H11V7H13M13,17H11V11H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" Fill="Black"/>
+ </Canvas>
+ </Viewbox>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Open.xaml 9(+9 -0)
diff --git a/WPF/Common/WPF/Icons/Open.xaml b/WPF/Common/WPF/Icons/Open.xaml
new file mode 100644
index 0000000..9fe4f17
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Open.xaml
@@ -0,0 +1,9 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Geometry x:Key="OpenData">M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z</Geometry>
+ <Viewbox x:Key="Open" Width="24" Height="24">
+ <Canvas Width="24" Height="24">
+ <Path Data="{DynamicResource OpenData}" Fill="Black" />
+ </Canvas>
+ </Viewbox>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Icons/Pointer.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/Pointer.xaml b/WPF/Common/WPF/Icons/Pointer.xaml
new file mode 100644
index 0000000..7dffd59
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Pointer.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="Pointer" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 35,19L 41,19L 41,32L 35,32 Z M 19,35L 19,41L 32,41L 32,35 Z M 35,43L 35,57L 41,57L 41,43 Z M 43,35L 43,41L 57,41L 57,35 Z"/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Read.xaml 10(+10 -0)
diff --git a/WPF/Common/WPF/Icons/Read.xaml b/WPF/Common/WPF/Icons/Read.xaml
new file mode 100644
index 0000000..6e959fd
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Read.xaml
@@ -0,0 +1,10 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Geometry x:Key="PathR">M4,16V3H6L9,3A4,4 0 0,1 13,7C13,8.54 12.13,9.88 10.85,10.55L14,16H12L9.11,11H6V16H4M6,9H9A2,2 0 0,0 11,7A2,2 0 0,0 9,5H6V9Z</Geometry>
+ <Geometry x:Key="PathOK">M21.59,11.59L23,13L13.5,22.5L8.42,17.41L9.83,16L13.5,19.68L21.59,11.59</Geometry>
+ <Viewbox x:Key="Read" Width="24" Height="24">
+ <Canvas Width="24" Height="24">
+ <Path Data="{DynamicResource PathR}" Fill="Black" />
+ <Path Data="{DynamicResource PathOK}" Fill="Black"/>
+ </Canvas>
+ </Viewbox>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Search.xaml 8(+8 -0)
diff --git a/WPF/Common/WPF/Icons/Search.xaml b/WPF/Common/WPF/Icons/Search.xaml
new file mode 100644
index 0000000..026d949
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Search.xaml
@@ -0,0 +1,8 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Viewbox x:Key="Search" Width="24" Height="24">
+ <Canvas Width="24" Height="24">
+ <Path Data="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" Fill="Black" />
+ </Canvas>
+ </Viewbox>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Icons/Settings.xaml 20(+20 -0)
diff --git a/WPF/Common/WPF/Icons/Settings.xaml b/WPF/Common/WPF/Icons/Settings.xaml
new file mode 100644
index 0000000..e30cc7d
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Settings.xaml
@@ -0,0 +1,20 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="Settings" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 39,71L 25.5,70.25L 25.75,55.5L 39.25,54.75L 44.25,47L 37.75,34.75L 50.5,27.25L 58.25,38.25L 67,38.25L 75,27.25L 88,34.75L 81.5,47L 87,54.75L 99.5,55L 99.5,71L 86.25,71L 81.5,79.25L 87.75,91L 75,97.5L 67.5,87.25L 58.5,87.25L 51,98.75L 37.25,90.75L 44.25,78.75L 38.75,70.75L 26,70L 26,55.75L 39.25,54.5L 52.25,59.75L 51.25,62.5L 51.75,65.75L 53.25,68.5L 55.25,71L 58,73L 61.5,74L 65.25,73.5L 68.5,72.25L 70.75,69.75L 72.5,67.5L 73.5,64L 73.75,60.5L 72.75,58.5L 71.75,55.25L 68.5,52.75L 65.75,52L 62,51.75L 58,51.75L 55.75,53.75L 53.75,56.25L 52.5,59.75 Z"/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+ <DrawingBrush x:Key="SettingsOnHover" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForegroundAlt}" Geometry="F1 M 39,71L 25.5,70.25L 25.75,55.5L 39.25,54.75L 44.25,47L 37.75,34.75L 50.5,27.25L 58.25,38.25L 67,38.25L 75,27.25L 88,34.75L 81.5,47L 87,54.75L 99.5,55L 99.5,71L 86.25,71L 81.5,79.25L 87.75,91L 75,97.5L 67.5,87.25L 58.5,87.25L 51,98.75L 37.25,90.75L 44.25,78.75L 38.75,70.75L 26,70L 26,55.75L 39.25,54.5L 52.25,59.75L 51.25,62.5L 51.75,65.75L 53.25,68.5L 55.25,71L 58,73L 61.5,74L 65.25,73.5L 68.5,72.25L 70.75,69.75L 72.5,67.5L 73.5,64L 73.75,60.5L 72.75,58.5L 71.75,55.25L 68.5,52.75L 65.75,52L 62,51.75L 58,51.75L 55.75,53.75L 53.75,56.25L 52.5,59.75 Z"/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/StartEndIcon.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/StartEndIcon.xaml b/WPF/Common/WPF/Icons/StartEndIcon.xaml
new file mode 100644
index 0000000..2145aeb
--- /dev/null
+++ b/WPF/Common/WPF/Icons/StartEndIcon.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="StartEndIcon" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 5,8L 5,2L 2,2L 2,17L 5,17L 5,11L 8,11L 8,17L 11,17L 11,2L 8,2L 8,8L 5,8 Z M 14,2L 14,17L 17,17L 17,11L 20,17L 23,17L 20,11L 20,8L 23,2L 20,2L 17,8L 17,2L 14,2 Z"/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Substract.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/Substract.xaml b/WPF/Common/WPF/Icons/Substract.xaml
new file mode 100644
index 0000000..1b28d01
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Substract.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="Substract" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 57,35L 57,41L 19,41L 19,35 Z"/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
WPF/Common/WPF/Icons/TreeListExpander.xaml 12(+12 -0)
diff --git a/WPF/Common/WPF/Icons/TreeListExpander.xaml b/WPF/Common/WPF/Icons/TreeListExpander.xaml
new file mode 100644
index 0000000..a6b54f0
--- /dev/null
+++ b/WPF/Common/WPF/Icons/TreeListExpander.xaml
@@ -0,0 +1,12 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="TreeListExpander" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 71.2133,42.6613L 113.652,85.4337L 71.3521,128.012L 61.3534,117.985L 93.3355,85.3087L 61.3395,52.7572L 71.2133,42.6613 Z "/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
+
WPF/Common/WPF/Icons/Up.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/Up.xaml b/WPF/Common/WPF/Icons/Up.xaml
new file mode 100644
index 0000000..469dc1c
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Up.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="Up" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="{DynamicResource UiElementForeground}" Geometry="F1 M 34,57L 42,57L 42,32.25L 52,42.25L 52,31.75L 38,17.75L 24,31.75L 24,42.25L 34,32.25L 34,57 Z "/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
diff --git a/WPF/Common/WPF/Icons/VisibleHide.xaml b/WPF/Common/WPF/Icons/VisibleHide.xaml
new file mode 100644
index 0000000..9c7a88f
--- /dev/null
+++ b/WPF/Common/WPF/Icons/VisibleHide.xaml
@@ -0,0 +1,7 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Viewbox x:Key="Hide" Width="24" Height="24">
+ <Canvas Width="24" Height="24">
+ <Path Data="M11.83,9L15,12.16C15,12.11 15,12.05 15,12A3,3 0 0,0 12,9C11.94,9 11.89,9 11.83,9M7.53,9.8L9.08,11.35C9.03,11.56 9,11.77 9,12A3,3 0 0,0 12,15C12.22,15 12.44,14.97 12.65,14.92L14.2,16.47C13.53,16.8 12.79,17 12,17A5,5 0 0,1 7,12C7,11.21 7.2,10.47 7.53,9.8M2,4.27L4.28,6.55L4.73,7C3.08,8.3 1.78,10 1,12C2.73,16.39 7,19.5 12,19.5C13.55,19.5 15.03,19.2 16.38,18.66L16.81,19.08L19.73,22L21,20.73L3.27,3M12,7A5,5 0 0,1 17,12C17,12.64 16.87,13.26 16.64,13.82L19.57,16.75C21.07,15.5 22.27,13.86 23,12C21.27,7.61 17,4.5 12,4.5C10.6,4.5 9.26,4.75 8,5.2L10.17,7.35C10.74,7.13 11.35,7 12,7Z" Fill="Black" />
+ </Canvas>
+ </Viewbox>
+</ResourceDictionary>
WPF/Common/WPF/Icons/VisibleOn.xaml 7(+7 -0)
diff --git a/WPF/Common/WPF/Icons/VisibleOn.xaml b/WPF/Common/WPF/Icons/VisibleOn.xaml
new file mode 100644
index 0000000..d122cf0
--- /dev/null
+++ b/WPF/Common/WPF/Icons/VisibleOn.xaml
@@ -0,0 +1,7 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Viewbox x:Key="Visible" Width="24" Height="24">
+ <Canvas Width="24" Height="24">
+ <Path Data="M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17M12,4.5C7,4.5 2.73,7.61 1,12C2.73,16.39 7,19.5 12,19.5C17,19.5 21.27,16.39 23,12C21.27,7.61 17,4.5 12,4.5Z" Fill="Black" />
+ </Canvas>
+ </Viewbox>
+</ResourceDictionary>
WPF/Common/WPF/Icons/Warning.xaml 11(+11 -0)
diff --git a/WPF/Common/WPF/Icons/Warning.xaml b/WPF/Common/WPF/Icons/Warning.xaml
new file mode 100644
index 0000000..29aef13
--- /dev/null
+++ b/WPF/Common/WPF/Icons/Warning.xaml
@@ -0,0 +1,11 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <DrawingBrush x:Key="Warning" Stretch="Uniform">
+ <DrawingBrush.Drawing>
+ <DrawingGroup>
+ <DrawingGroup.Children>
+ <GeometryDrawing Brush="Coral" Geometry="F1 M 58.5832,55.4172L 17.4169,55.4171C 15.5619,53.5621 15.5619,50.5546 17.4168,48.6996L 35.201,15.8402C 37.056,13.9852 40.0635,13.9852 41.9185,15.8402L 58.5832,48.6997C 60.4382,50.5546 60.4382,53.5622 58.5832,55.4172 Z M 34.0417,25.7292L 36.0208,41.9584L 39.9791,41.9583L 41.9583,25.7292L 34.0417,25.7292 Z M 38,44.3333C 36.2511,44.3333 34.8333,45.7511 34.8333,47.5C 34.8333,49.2489 36.2511,50.6667 38,50.6667C 39.7489,50.6667 41.1666,49.2489 41.1666,47.5C 41.1666,45.7511 39.7489,44.3333 38,44.3333 Z "/>
+ </DrawingGroup.Children>
+ </DrawingGroup>
+ </DrawingBrush.Drawing>
+ </DrawingBrush>
+</ResourceDictionary>
\ No newline at end of file
diff --git a/WPF/Common/WPF/IEditingBaseViewModel.cs b/WPF/Common/WPF/IEditingBaseViewModel.cs
new file mode 100644
index 0000000..7559f8f
--- /dev/null
+++ b/WPF/Common/WPF/IEditingBaseViewModel.cs
@@ -0,0 +1,7 @@
+namespace Common.WPF
+{
+ public interface IEditingBaseViewModel
+ {
+ RelayCommand EditCommand { get; }
+ }
+}
\ No newline at end of file
WPF/Common/WPF/ModifyViewModel.cs 49(+49 -0)
diff --git a/WPF/Common/WPF/ModifyViewModel.cs b/WPF/Common/WPF/ModifyViewModel.cs
new file mode 100644
index 0000000..9a7e833
--- /dev/null
+++ b/WPF/Common/WPF/ModifyViewModel.cs
@@ -0,0 +1,49 @@
+using System.Windows;
+
+namespace Common.WPF
+{
+ public class ModifyViewModel : BaseViewModel
+ {
+ protected ModifyViewModel()
+ {
+ MinimizeCommand = new RelayCommand(OnMinimize);
+ MaximizeCommand = new RelayCommand<Window>(OnMaximize);
+ CloseCommand = new RelayCommand(OnClose);
+ }
+
+ private WindowState _windowState;
+ public WindowState WindowState
+ {
+ get { return _windowState; }
+ set
+ {
+ _windowState = value;
+ OnPropertyChanged(() => WindowState);
+ }
+ }
+
+ public RelayCommand MinimizeCommand { get; }
+ public RelayCommand<Window> MaximizeCommand { get; }
+ public RelayCommand CloseCommand { get; }
+
+ protected virtual void OnMinimize()
+ {
+ WindowState = WindowState.Minimized;
+ }
+
+ protected virtual void OnMaximize(Window window)
+ {
+ if (window != null)
+ {
+ window.WindowState = window.WindowState == WindowState.Normal
+ ? WindowState.Maximized
+ : WindowState.Normal;
+ }
+ }
+
+ protected virtual void OnClose()
+ {
+ Application.Current.Shutdown();
+ }
+ }
+}
diff --git a/WPF/Common/WPF/NotifyPropertyChangedHelper.cs b/WPF/Common/WPF/NotifyPropertyChangedHelper.cs
new file mode 100644
index 0000000..182c9cd
--- /dev/null
+++ b/WPF/Common/WPF/NotifyPropertyChangedHelper.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace Common.WPF
+{
+ public class NotifyPropertyChangedHelper
+ {
+ PropertyChangedEventHandler _propertyChangeHandler;
+
+ public void Add(PropertyChangedEventHandler value)
+ {
+ _propertyChangeHandler += value;
+ }
+
+ public void Remove(PropertyChangedEventHandler value)
+ {
+ if (_propertyChangeHandler != null) _propertyChangeHandler -= value;
+ }
+
+ public void NotifyPropertyChanged(object sender, string propertyName)
+ {
+ _propertyChangeHandler?.Invoke(sender, new PropertyChangedEventArgs(propertyName));
+ }
+
+ public void SetValue<T>(object containingObject, ref T field, T value, params string[] names)
+ {
+ if (names == null) throw new ArgumentNullException(nameof(names));
+
+ if (!EqualityComparer<T>.Default.Equals(field, value))
+ {
+ field = value;
+ foreach (string t in names)
+ {
+ NotifyPropertyChanged(containingObject, t);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
WPF/Common/WPF/ObservableCollectionAdv.cs 57(+57 -0)
diff --git a/WPF/Common/WPF/ObservableCollectionAdv.cs b/WPF/Common/WPF/ObservableCollectionAdv.cs
new file mode 100644
index 0000000..135009b
--- /dev/null
+++ b/WPF/Common/WPF/ObservableCollectionAdv.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Common.WPF
+{
+ public class ObservableCollectionAdv<T> : ObservableCollection<T>
+ {
+ public void RemoveRange(int index, int count)
+ {
+ CheckReentrancy();
+ ((List<T>)Items).RemoveRange(index, count);
+ OnReset();
+ }
+
+ public void InsertRange(int index, IEnumerable<T> collection)
+ {
+ CheckReentrancy();
+ ((List<T>)Items).InsertRange(index, collection);
+ OnReset();
+ }
+
+ public void Sort()
+ {
+ List<T> sorted = ((List<T>)Items).OrderBy(x => x).ToList();
+ for (int i = 0; i < sorted.Count; i++) Move(((List<T>)Items).IndexOf(sorted[i]), i);
+ }
+
+ //public ObservableCollectionAdv(IEnumerable<T> collection)
+ //{
+ // CheckReentrancy();
+ // ((List<T>)Items).Clear();
+ // ((List<T>)Items).InsertRange(0, collection);
+ // OnReset();
+ // }
+
+ // public ObservableCollectionAdv()
+ // {}
+
+
+ void OnReset()
+ {
+ OnPropertyChanged("Count");
+ OnPropertyChanged("Item[]");
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+
+ void OnPropertyChanged(string propertyName)
+ {
+ OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+}
WPF/Common/WPF/RelayCommand.cs 152(+152 -0)
diff --git a/WPF/Common/WPF/RelayCommand.cs b/WPF/Common/WPF/RelayCommand.cs
new file mode 100644
index 0000000..3832826
--- /dev/null
+++ b/WPF/Common/WPF/RelayCommand.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Input;
+
+namespace Common.WPF
+{
+ public delegate bool PredicateDelegate();
+ public class RelayCommand : ICommand
+ {
+ #region Fields
+ readonly Action _execute;
+ readonly Predicate<object> _canExecute;
+ #endregion
+
+ #region Ctors
+
+ public RelayCommand(Action execute, Predicate<object> canExecute = null)
+ {
+ if (execute == null)
+ throw new ArgumentNullException(nameof(execute));
+
+ _execute = execute;
+ _canExecute = canExecute;
+ }
+
+ public RelayCommand(Action execute, PredicateDelegate canExecute)
+ {
+ if (execute == null)
+ throw new ArgumentNullException(nameof(execute));
+
+ _execute = execute;
+ _canExecute = obj => canExecute();
+ }
+ #endregion
+
+ public void Execute()
+ {
+ if (CanExecute(null))
+ ForceExecute();
+ }
+
+ [DebuggerStepThrough]
+ public void ForceExecute()
+ {
+ try
+ {
+ _execute();
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show(e.Message);
+ }
+ }
+
+ #region ICommand Members
+
+ [DebuggerStepThrough]
+ void ICommand.Execute(object parameter)
+ {
+ ForceExecute();
+ }
+
+ public bool CanExecute(object parameter)
+ {
+ if (_canExecute != null)
+ {
+ try
+ {
+ return _canExecute(parameter);
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public event EventHandler CanExecuteChanged
+ {
+ add { CommandManager.RequerySuggested += value; }
+ remove { CommandManager.RequerySuggested -= value; }
+ }
+ #endregion
+ }
+
+ public class RelayCommand<T> : ICommand
+ {
+ #region Fields
+
+ readonly Action<T> _execute;
+ readonly Predicate<T> _canExecute;
+
+ #endregion
+
+ #region Ctors
+
+ public RelayCommand(Action<T> execute, Predicate<T> canExecute = null)
+ {
+ if (execute == null)
+ throw new ArgumentNullException(nameof(execute));
+
+ _execute = execute;
+ _canExecute = canExecute;
+ }
+
+ #endregion
+
+ public void Execute(T parameter)
+ {
+ if (CanExecute(parameter))
+ ForceExecute(parameter);
+ }
+
+ [DebuggerStepThrough]
+ public void ForceExecute(T parameter)
+ {
+ try
+ {
+ _execute(parameter);
+ }
+ catch (Exception e)
+ {
+ System.Diagnostics.Debug.WriteLine("RelayCommand exception: " + e.Message);
+ }
+ }
+
+ #region ICommand Members
+
+ [DebuggerStepThrough]
+ void ICommand.Execute(object parameter)
+ {
+ ForceExecute((T)parameter);
+ }
+
+ [DebuggerStepThrough]
+ public bool CanExecute(object parameter)
+ {
+ if (_canExecute != null)
+ return _canExecute((T)(parameter ?? default(T)));
+ return true;
+ }
+
+ event EventHandler ICommand.CanExecuteChanged
+ {
+ add { CommandManager.RequerySuggested += value; }
+ remove { CommandManager.RequerySuggested -= value; }
+ }
+ #endregion
+ }
+}
\ No newline at end of file
WPF/Common/WPF/Style/ButtonStyle.xaml 334(+334 -0)
diff --git a/WPF/Common/WPF/Style/ButtonStyle.xaml b/WPF/Common/WPF/Style/ButtonStyle.xaml
new file mode 100644
index 0000000..6d165c8
--- /dev/null
+++ b/WPF/Common/WPF/Style/ButtonStyle.xaml
@@ -0,0 +1,334 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <Style x:Key="DefaultButton" TargetType="{x:Type Button}">
+ <Setter Property="OverridesDefaultStyle" Value="True" />
+ <Setter Property="BorderThickness" Value="1"/>
+ <Setter Property="Foreground" Value="Black"/>
+ <Setter Property="HorizontalContentAlignment" Value="Center"/>
+ <Setter Property="VerticalContentAlignment" Value="Center"/>
+ <Setter Property="Padding" Value="10 4"/>
+ <Setter Property="Margin" Value="10 3" />
+ <Setter Property="Background" Value="#F0F0F0" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type Button}">
+ <Grid>
+ <Border x:Name="Chrome" CornerRadius="3" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true" BorderBrush="#ACACAC" Background="{TemplateBinding Background}">
+ <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ </Border>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsEnabled" Value="false">
+ <Setter Property="Foreground" Value="#ADADAD"/>
+ </Trigger>
+
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FFFCFCFC" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+
+
+ <Style x:Key="ReturnButton" TargetType="{x:Type Button}">
+ <Setter Property="Background" Value="#FF323239" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas Width="14" Height="14" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="14" Height="14" Data="F1M646.688,13.5518L646.783,13.4593 646.965,13.639 668.383,35.0583 689.459,35.0583 665.155,10.751 657.503,3.10126 657.323,2.92023 664.876,-4.63837 689.184,-28.9417 668.109,-28.9417 646.688,-7.52637 636.15,3.01398 646.688,13.5518z" Stretch="Uniform" Fill="#FFFFFFFF" RenderTransformOrigin="0.5,0.5" />
+ </Canvas>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FF474754" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+ <Style x:Key="PinButtonPinned" TargetType="{x:Type Button}">
+ <Setter Property="Background" Value="#FF323239" />
+ <Setter Property="ToolTip" Value="Открепить окно"></Setter>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas Width="17" Height="14" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="17" Height="17" Stretch="Fill" Fill="#FFF0F4E5" Data="F1 M 30,38L 46,38L 41,40L 44,53L 56,56L 41,56L 38,66L 35,56L 20,56L 32,53L 35,40L 30,38 Z "/>
+ </Canvas>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FF474754" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+ <Style x:Key="PinButtonNotPinned" TargetType="{x:Type Button}">
+ <Setter Property="Background" Value="#FFF0F4E5" />
+ <Setter Property="ToolTip" Value="Закрепить окно поверх остальных окон"></Setter>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas Width="17" Height="14" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="17" Height="17" Stretch="Fill" Fill="#FF323239" Data="F1 M 30,38L 46,38L 41,40L 44,53L 56,56L 41,56L 38,66L 35,56L 20,56L 32,53L 35,40L 30,38 Z "/>
+ </Canvas>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FFDCDCDC" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+ <Style x:Key="CloseButton" TargetType="{x:Type Button}">
+ <Style.Resources>
+ <Brush x:Key="ImageColor">#FFF0F4E5</Brush>
+ <Brush x:Key="BgColor">#FF323239</Brush>
+ </Style.Resources>
+ <Setter Property="Background" Value="{DynamicResource BgColor}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas Width="14" Height="14" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="14" Height="14" Stretch="Fill" Fill="{DynamicResource ImageColor}" Data="F1 M 26.9166,22.1667L 37.9999,33.25L 49.0832,22.1668L 53.8332,26.9168L 42.7499,38L 53.8332,49.0834L 49.0833,53.8334L 37.9999,42.75L 26.9166,53.8334L 22.1666,49.0833L 33.25,38L 22.1667,26.9167L 26.9166,22.1667 Z "/>
+ </Canvas>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FF474754" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+ <Style x:Key="CloseButtonGrey" TargetType="{x:Type Button}" BasedOn="{StaticResource CloseButton}">
+ <Style.Resources>
+ <Brush x:Key="ImageColor">#FF323239</Brush>
+ <Brush x:Key="BgColor">#a3a3a1</Brush>
+ </Style.Resources>
+ </Style>
+
+ <Style x:Key="MinimizeButton" TargetType="{x:Type Button}">
+ <Style.Resources>
+ <Brush x:Key="ImageColor">#FFF0F4E5</Brush>
+ <Brush x:Key="BgColor">#FF323239</Brush>
+ </Style.Resources>
+ <Setter Property="Background" Value="{DynamicResource BgColor}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas Width="14" Height="12" VerticalAlignment="Bottom" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="14" Height="4" Stretch="Fill" Fill="{DynamicResource ImageColor}" Data="F1 M 19,38L 57,38L 57,44L 19,44L 19,38 Z "/>
+ </Canvas>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FF474754" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+
+
+ <Style x:Key="MinimizeButtonGrey" TargetType="{x:Type Button}" BasedOn="{StaticResource MinimizeButton}">
+ <Style.Resources>
+ <Brush x:Key="ImageColor">#FF323239</Brush>
+ <Brush x:Key="BgColor">#a3a3a1</Brush>
+ </Style.Resources>
+ </Style>
+
+ <Style x:Key="MaximizeButton" TargetType="{x:Type Button}">
+ <Style.Resources>
+ <Brush x:Key="ImageColor">#FFF0F4E5</Brush>
+ <Brush x:Key="BgColor">#FF323239</Brush>
+ </Style.Resources>
+ <Setter Property="Background" Value="{DynamicResource BgColor}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas x:Name="appbar_window_maximize" Width="14" Height="14" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="14" Height="14" Stretch="Fill" Fill="{DynamicResource ImageColor}" Data="F1 M 43,48L 46,48L 46,57L 19,57L 19,34L 32,34L 32,40L 22,40L 22,54L 43,54L 43,48 Z M 21,19L 57,19L 57,50L 49,50L 49,46L 53,46L 53,27L 25,27L 25,32L 21,32L 21,19 Z M 37.75,30L 50,30L 50,42.25L 46,46.25L 46,37.25L 38,45.25L 34.75,42L 42.75,34L 33.75,34L 37.75,30 Z "/>
+ </Canvas>
+ <!--<Canvas x:Name="appbar_window_restore" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="38" Height="38" Canvas.Left="19" Canvas.Top="19" Stretch="Fill" Fill="#FFF0F4E5" Data="F1 M 54,54L 54,40L 33,40L 33,54L 54,54 Z M 57,34L 57,57L 30,57L 30,34L 57,34 Z M 43,25L 22,25L 22,39L 27,39L 27,42L 19,42L 19,19L 46,19L 46,31L 43,31L 43,25 Z "/>
+ </Canvas>-->
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FF474754" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+ <Style x:Key="MaximizeButtonGrey" TargetType="{x:Type Button}" BasedOn="{StaticResource MaximizeButton}">
+ <Style.Resources>
+ <Brush x:Key="ImageColor">#FF323239</Brush>
+ <Brush x:Key="BgColor">#a3a3a1</Brush>
+ </Style.Resources>
+ </Style>
+
+ <Style x:Key="SettingsButton" TargetType="{x:Type Button}">
+ <Setter Property="Background" Value="#FF323239" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas Width="14" Height="14" VerticalAlignment="Center" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="14" Height="14" Stretch="Fill" Fill="#FFF0F4E5" Data="F1 M 38,23.5C 38.8643,23.5 39.7109,23.5756 40.5337,23.7206L 42.6275,18.5381L 48.1901,20.787L 46.0964,25.9692C 47.6473,27.0149 48.9851,28.3527 50.0308,29.9036L 55.213,27.8099L 57.4619,33.3725L 52.2794,35.4664C 52.4244,36.2891 52.5,37.1357 52.5,38C 52.5,38.8643 52.4244,39.7109 52.2794,40.5337L 57.4619,42.6275L 55.213,48.1901L 50.0308,46.0964C 49.0795,47.5073 47.8865,48.7418 46.5112,49.7405L 48.7844,54.8462L 43.3041,57.2891L 41.0307,52.1828C 40.0533,52.3906 39.0394,52.5 38,52.5C 37.1357,52.5 36.2891,52.4244 35.4664,52.2794L 33.3725,57.462L 27.8099,55.213L 29.9036,50.0309C 28.3527,48.9851 27.0149,47.6473 25.9691,46.0964L 20.787,48.1901L 18.538,42.6275L 23.7206,40.5336C 23.5756,39.7109 23.5,38.8643 23.5,38C 23.5,37.1357 23.5756,36.2891 23.7206,35.4664L 18.538,33.3725L 20.787,27.8099L 25.9691,29.9036C 26.9205,28.4927 28.1135,27.2582 29.4889,26.2594L 27.2157,21.1537L 32.6959,18.7109L 34.9694,23.8172C 35.9468,23.6094 36.9606,23.5 38,23.5 Z M 38,28C 32.4771,28 28,32.4772 28,38C 28,43.5229 32.4771,48 38,48C 43.5228,48 48,43.5229 48,38C 48,32.4772 43.5228,28 38,28 Z "/>
+ </Canvas>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FF474754" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+ <Style x:Key="ToolBarButton" TargetType="{x:Type Button}">
+ <Setter Property="Height" Value="40" />
+ <Setter Property="Width" Value="40" />
+ <Setter Property="VerticalAlignment" Value="Center" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Border Name="border"
+ Margin="2"
+ BorderBrush="Transparent"
+ BorderThickness="1"
+ CornerRadius="1"
+ Padding="2"
+ ToolTip="{TemplateBinding ToolTip}"
+ ToolTipService.ShowOnDisabled="True">
+ <Rectangle Name="Image" Fill="{TemplateBinding Background}" />
+ </Border>
+ <ControlTemplate.Triggers>
+ <Trigger Property="UIElement.IsMouseOver" Value="True">
+ <Setter TargetName="border" Property="Border.BorderBrush" Value="{DynamicResource UiElementBackgroundHighlight}" />
+ <Setter TargetName="border" Property="Border.Background" Value="{DynamicResource UiElementBackgroundHighlight}" />
+ </Trigger>
+ <Trigger Property="Button.IsPressed" Value="True">
+ <Setter TargetName="border" Property="Border.Background" Value="{DynamicResource UiElementBackgroundHighlightAlt}" />
+ </Trigger>
+ <Trigger Property="Button.IsEnabled" Value="False">
+ <Setter TargetName="border" Property="Opacity" Value="0.5" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <!--<Style x:Key="UgoMinimizeButton" TargetType="{x:Type Button}">
+ <Setter Property="Background" Value="#FFE6E6E6" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas Width="14" Height="12" VerticalAlignment="Bottom" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="14" Height="4" Stretch="Fill" Fill="#FF474754" Data="F1 M 19,38L 57,38L 57,44L 19,44L 19,38 Z "/>
+ </Canvas>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FFC8C8C8" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+ <Style x:Key="UgoMaximizeButton" TargetType="{x:Type Button}">
+ <Setter Property="Background" Value="#FFE6E6E6" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas x:Name="appbar_window_maximize" Width="14" Height="14" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="14" Height="14" Stretch="Fill" Fill="#FF474754" Data="F1 M 43,48L 46,48L 46,57L 19,57L 19,34L 32,34L 32,40L 22,40L 22,54L 43,54L 43,48 Z M 21,19L 57,19L 57,50L 49,50L 49,46L 53,46L 53,27L 25,27L 25,32L 21,32L 21,19 Z M 37.75,30L 50,30L 50,42.25L 46,46.25L 46,37.25L 38,45.25L 34.75,42L 42.75,34L 33.75,34L 37.75,30 Z "/>
+ </Canvas>
+ --><!--<Canvas x:Name="appbar_window_restore" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="38" Height="38" Canvas.Left="19" Canvas.Top="19" Stretch="Fill" Fill="#FFF0F4E5" Data="F1 M 54,54L 54,40L 33,40L 33,54L 54,54 Z M 57,34L 57,57L 30,57L 30,34L 57,34 Z M 43,25L 22,25L 22,39L 27,39L 27,42L 19,42L 19,19L 46,19L 46,31L 43,31L 43,25 Z "/>
+ </Canvas>--><!--
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FFC8C8C8" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>
+
+ <Style x:Key="UgoCloseButton" TargetType="{x:Type Button}">
+ <Setter Property="Background" Value="#FFE6E6E6" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid>
+ <Rectangle Height="26" Width="34" Fill="{TemplateBinding Property=Background}" />
+ <Canvas Width="14" Height="14" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
+ <Path Width="14" Height="14" Stretch="Fill" Fill="#FF474754" Data="F1 M 26.9166,22.1667L 37.9999,33.25L 49.0832,22.1668L 53.8332,26.9168L 42.7499,38L 53.8332,49.0834L 49.0833,53.8334L 37.9999,42.75L 26.9166,53.8334L 22.1666,49.0833L 33.25,38L 22.1667,26.9167L 26.9166,22.1667 Z "/>
+ </Canvas>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="#FFC8C8C8" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Cursor" Value="Hand" />
+ </Style>-->
+
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/Colors.xaml 29(+29 -0)
diff --git a/WPF/Common/WPF/Style/Colors.xaml b/WPF/Common/WPF/Style/Colors.xaml
new file mode 100644
index 0000000..33d33bf
--- /dev/null
+++ b/WPF/Common/WPF/Style/Colors.xaml
@@ -0,0 +1,29 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <SolidColorBrush Color="#2d2d30" x:Key="WindowBackground" />
+ <SolidColorBrush Color="#c0c0c0" x:Key="UgoWindowBackground" />
+ <SolidColorBrush Color="#A2A2A0" x:Key="WindowBorder" />
+
+ <SolidColorBrush Color="#1585d0" x:Key="Text" />
+ <SolidColorBrush Color="#1585d0" x:Key="AltText" />
+ <SolidColorBrush Color="#000000" x:Key="GridText" />
+ <SolidColorBrush Color="#FFFFFF" x:Key="GridBackground" />
+ <SolidColorBrush Color="#FFFFFF" x:Key="HighlitedGridText" />
+ <SolidColorBrush Color="#1585d0" x:Key="UiElementForeground" />
+ <SolidColorBrush Color="#13a2e8" x:Key="UiElementForegroundAlt" />
+ <SolidColorBrush Color="#e8b313" x:Key="UiElementForegroundHighlight" />
+ <SolidColorBrush Color="#13a2e8" x:Key="UiElementForegroundHighlightAlt" />
+ <SolidColorBrush Color="#1585d0" x:Key="UiElementBackground" />
+ <SolidColorBrush Color="#1585d0" x:Key="UiElementBackgroundAlt" />
+ <SolidColorBrush Color="#13a2e8" x:Key="UiElementBackgroundHighlight" />
+ <SolidColorBrush Color="#e8b313" x:Key="UiElementBackgroundHighlightAlt" />
+ <SolidColorBrush Color="#57a64a" x:Key="Green"/>
+ <SolidColorBrush Color="#65b557" x:Key="LightGreen"/>
+ <SolidColorBrush Color="#4a8d3f" x:Key="DarkGreen"/>
+ <SolidColorBrush Color="#92caf4" x:Key="Blue"/>
+ <SolidColorBrush Color="#569cd6" x:Key="DarkBlue"/>
+ <SolidColorBrush Color="#d7ba7d" x:Key="Yellow"/>
+ <SolidColorBrush Color="#cda95c" x:Key="DarkYellow"/>
+
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/ComboBoxStyle.xaml 160(+160 -0)
diff --git a/WPF/Common/WPF/Style/ComboBoxStyle.xaml b/WPF/Common/WPF/Style/ComboBoxStyle.xaml
new file mode 100644
index 0000000..fa271aa
--- /dev/null
+++ b/WPF/Common/WPF/Style/ComboBoxStyle.xaml
@@ -0,0 +1,160 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition />
+ <ColumnDefinition Width="20" />
+ </Grid.ColumnDefinitions>
+ <Border
+ x:Name="Border"
+ Grid.ColumnSpan="2"
+ CornerRadius="0"
+ Background="#FF3F3F3F"
+ BorderBrush="#FF97A0A5"
+ BorderThickness="1" />
+ <Border
+ Grid.Column="0"
+ CornerRadius="0"
+ Margin="1"
+ Background="#FF3F3F3F"
+ BorderBrush="#FF97A0A5"
+ BorderThickness="0,0,1,0" />
+ <Path
+ x:Name="Arrow"
+ Grid.Column="1"
+ Fill="#13a2e8"
+ HorizontalAlignment="Center"
+ VerticalAlignment="Center"
+ Data="M0,0 L0,2 L4,6 L8,2 L8,0 L4,4 z"
+ />
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="ToggleButton.IsMouseOver" Value="true">
+ <Setter TargetName="Border" Property="Background" Value="#808080" />
+ </Trigger>
+ <Trigger Property="ToggleButton.IsChecked" Value="true">
+ <Setter TargetName="Border" Property="Background" Value="#E0E0E0" />
+ </Trigger>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter TargetName="Border" Property="Background" Value="#EEEEEE" />
+ <Setter TargetName="Border" Property="BorderBrush" Value="#AAAAAA" />
+ <Setter Property="Foreground" Value="#888888"/>
+ <Setter TargetName="Arrow" Property="Fill" Value="#888888" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+
+ <ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}">
+ <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" />
+ </ControlTemplate>
+ <Style x:Key="ComboBoxStyle" TargetType="{x:Type ComboBox}">
+ <Setter Property="SnapsToDevicePixels" Value="true"/>
+ <Setter Property="OverridesDefaultStyle" Value="true"/>
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
+ <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
+ <Setter Property="MinWidth" Value="120"/>
+ <Setter Property="MinHeight" Value="20"/>
+ <Setter Property="Foreground" Value="White"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type ComboBox}">
+ <Grid>
+ <ToggleButton
+ Name="ToggleButton"
+ Template="{StaticResource ComboBoxToggleButton}"
+ Focusable="false"
+ IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
+ ClickMode="Press">
+ </ToggleButton>
+ <ContentPresenter Name="ContentSite" IsHitTestVisible="False" Content="{TemplateBinding SelectionBoxItem}"
+ ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
+ ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
+ Margin="3,3,23,3"
+ VerticalAlignment="Center"
+ HorizontalAlignment="Left" />
+ <TextBox x:Name="PART_EditableTextBox"
+ Style="{x:Null}"
+ Template="{StaticResource ComboBoxTextBox}"
+ HorizontalAlignment="Left"
+ VerticalAlignment="Center"
+ Margin="3,3,23,3"
+ Focusable="True"
+ Background="#FF3F3F3F"
+ Foreground="Green"
+ Visibility="Hidden"
+ IsReadOnly="{TemplateBinding IsReadOnly}"/>
+ <Popup
+ Name="Popup"
+ Placement="Bottom"
+ IsOpen="{TemplateBinding IsDropDownOpen}"
+ AllowsTransparency="True"
+ Focusable="False"
+ PopupAnimation="Slide">
+
+ <Grid Name="DropDown"
+ SnapsToDevicePixels="True"
+ MinWidth="{TemplateBinding ActualWidth}"
+ MaxHeight="{TemplateBinding MaxDropDownHeight}">
+ <Border
+ x:Name="DropDownBorder"
+ Background="#FF3F3F3F"
+
+ BorderThickness="1"
+ BorderBrush="#888888"/>
+ <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
+ <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
+ </ScrollViewer>
+ </Grid>
+ </Popup>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="HasItems" Value="false">
+ <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
+ </Trigger>
+ <Trigger Property="IsEnabled" Value="false">
+ <Setter Property="Foreground" Value="#888888"/>
+ </Trigger>
+ <Trigger Property="IsGrouping" Value="true">
+ <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
+ </Trigger>
+ <Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
+ <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="0"/>
+ <Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/>
+ </Trigger>
+ <Trigger Property="IsEditable" Value="true">
+ <Setter Property="IsTabStop" Value="false"/>
+ <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
+ <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ <Style x:Key="ComboBoxItemStyle" TargetType="{x:Type ComboBoxItem}">
+ <Setter Property="SnapsToDevicePixels" Value="true"/>
+ <Setter Property="Foreground" Value="White"/>
+ <Setter Property="OverridesDefaultStyle" Value="true"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type ComboBoxItem}">
+ <Border Name="Border"
+ Padding="2"
+ SnapsToDevicePixels="true">
+ <ContentPresenter />
+ </Border>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsHighlighted" Value="true">
+ <Setter TargetName="Border" Property="Background" Value="#FF4F4F4F"/>
+ </Trigger>
+ <Trigger Property="IsEnabled" Value="false">
+ <Setter Property="Foreground" Value="#888888"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
\ No newline at end of file
diff --git a/WPF/Common/WPF/Style/ExpandCollapseToggleStyle.xaml b/WPF/Common/WPF/Style/ExpandCollapseToggleStyle.xaml
new file mode 100644
index 0000000..73acd1a
--- /dev/null
+++ b/WPF/Common/WPF/Style/ExpandCollapseToggleStyle.xaml
@@ -0,0 +1,28 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
+ <Setter Property="Focusable" Value="False" />
+ <Setter Property="Width" Value="30" />
+ <Setter Property="Height" Value="30" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ToggleButton">
+ <Border Background="Transparent">
+ <Path x:Name="CheckMark" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" Fill="Gray" />
+ </Border>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter TargetName="CheckMark" Property="Fill" Value="{DynamicResource HighlightedBackgoundBrush}" />
+ </Trigger>
+ <Trigger Property="IsChecked" Value="False">
+ <Setter TargetName="CheckMark" Property="Data" Value="M6,2 L10,2 L10,-2 L12,-2 L12,2 L16,2 L16,4 L12,4 L12,8 L10,8 L10,4 L6,4 L6,2 z" />
+ </Trigger>
+ <Trigger Property="IsChecked" Value="True">
+ <Setter TargetName="CheckMark" Property="Data" Value="M6,2 L16,2 L16,4 L6,4 z" />
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/ExpanderStyle.xaml 89(+89 -0)
diff --git a/WPF/Common/WPF/Style/ExpanderStyle.xaml b/WPF/Common/WPF/Style/ExpanderStyle.xaml
new file mode 100644
index 0000000..a7bcfd8
--- /dev/null
+++ b/WPF/Common/WPF/Style/ExpanderStyle.xaml
@@ -0,0 +1,89 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="Colors.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+
+ <Style x:Key="AdvancedExpander" TargetType="{x:Type Expander}">
+
+ <Style.Resources>
+ <ControlTemplate x:Key="SimpleExpanderButtonTemp" TargetType="{x:Type ToggleButton}">
+ <Border x:Name="ExpanderButtonBorder"
+ Background="{TemplateBinding Background}"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Padding="{TemplateBinding Padding}">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Rectangle Fill="Transparent" Grid.ColumnSpan="2"/>
+ <Ellipse Name="Circle"
+ Grid.Column="0"
+ Stroke="{StaticResource DarkGreen}"
+ StrokeThickness="1.5"
+ Width="20"
+ Height="20"
+ HorizontalAlignment="Center"
+ VerticalAlignment="Center"/>
+ <Path x:Name="Sign"
+ Grid.Column="0"
+ Data="M 0,5 H 10 M 5,0 V 10 Z"
+ Stroke="{StaticResource DarkGreen}"
+ Width="10"
+ Height="10"
+ StrokeThickness="2"
+ HorizontalAlignment="Center"
+ VerticalAlignment="Center"
+ RenderTransformOrigin="0.5,0.5">
+ <Path.RenderTransform>
+ <RotateTransform Angle="0"/>
+ </Path.RenderTransform>
+ </Path>
+ <ContentPresenter x:Name="HeaderContent" Grid.Column="1" Margin="4,0,0,0" ContentSource="Content" VerticalAlignment="Center"/>
+ </Grid>
+ </Border>
+ <ControlTemplate.Triggers>
+ <!--Change the sign to minus when toggled-->
+ <Trigger Property="IsChecked" Value="True">
+ <Setter Property="Data" TargetName="Sign" Value="M 0,5 H 10 Z"/>
+ </Trigger>
+ <!-- MouseOver, Pressed behaviours-->
+ <Trigger Property="IsMouseOver" Value="true">
+ <Setter Property="Stroke" Value="{StaticResource Yellow}" TargetName="Circle"/>
+ <Setter Property="Stroke" Value="{StaticResource Yellow}" TargetName="Sign"/>
+ </Trigger>
+ <Trigger Property="IsPressed" Value="true">
+ <Setter Property="Stroke" Value="{StaticResource LightGreen}" TargetName="Circle"/>
+ <Setter Property="StrokeThickness" Value="1.5" TargetName="Circle"/>
+ <Setter Property="Stroke" Value="{StaticResource LightGreen}" TargetName="Sign"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Style.Resources>
+
+
+
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type Expander}">
+ <DockPanel>
+ <ToggleButton x:Name="ExpanderButton" DockPanel.Dock="Top"
+ Template="{StaticResource SimpleExpanderButtonTemp}"
+ Content="{TemplateBinding Header}"
+ IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
+ OverridesDefaultStyle="True"
+ Padding="1.5,0"/>
+ <ContentPresenter x:Name="ExpanderContent" Visibility="Collapsed" DockPanel.Dock="Bottom"/>
+ </DockPanel>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsExpanded" Value="True">
+ <Setter TargetName="ExpanderContent" Property="Visibility" Value="Visible"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/GroupBoxStyle.xaml 29(+29 -0)
diff --git a/WPF/Common/WPF/Style/GroupBoxStyle.xaml b/WPF/Common/WPF/Style/GroupBoxStyle.xaml
new file mode 100644
index 0000000..920d143
--- /dev/null
+++ b/WPF/Common/WPF/Style/GroupBoxStyle.xaml
@@ -0,0 +1,29 @@
+
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <Style x:Key="MyGbStyle" TargetType="GroupBox">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="GroupBox">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <Border Grid.Row="0" BorderThickness="1"
+ BorderBrush="#13a2e8"
+ Background="#13a2e8">
+ <Label Foreground="White">
+ <ContentPresenter Margin="0" ContentSource="Header" RecognizesAccessKey="True" />
+ </Label>
+ </Border>
+ <Border Grid.Row="1" BorderThickness="1,0,1,1" BorderBrush="#13a2e8">
+ <ContentPresenter Margin="4" />
+ </Border>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/ListBoxStyle.xaml 12(+12 -0)
diff --git a/WPF/Common/WPF/Style/ListBoxStyle.xaml b/WPF/Common/WPF/Style/ListBoxStyle.xaml
new file mode 100644
index 0000000..c41cb2b
--- /dev/null
+++ b/WPF/Common/WPF/Style/ListBoxStyle.xaml
@@ -0,0 +1,12 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <!--dwg list-->
+
+ <Style x:Key="MyLbStyle" TargetType="{x:Type ListBoxItem}">
+ <Style.Resources>
+ <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="White" />
+ <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
+ </Style.Resources>
+ </Style>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/ProgressbarStyle.xaml 99(+99 -0)
diff --git a/WPF/Common/WPF/Style/ProgressbarStyle.xaml b/WPF/Common/WPF/Style/ProgressbarStyle.xaml
new file mode 100644
index 0000000..a471427
--- /dev/null
+++ b/WPF/Common/WPF/Style/ProgressbarStyle.xaml
@@ -0,0 +1,99 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="clr-namespace:PasswordApp.WPF.Style"
+ xmlns:converters="clr-namespace:Common.WPF.Converters">
+ <Style x:Key="RoundProgressBarStyle" TargetType="{x:Type ProgressBar}"
+ xmlns:sys="clr-namespace:System;assembly=mscorlib">
+ <Style.Resources>
+ <converters:RoundProgressPathConverter x:Key="RoundProgressPathConverter"/>
+ <!-- нам понадобится пара констант -->
+ <!-- доля рабиуса для внутренней части -->
+ <sys:Double x:Key="RelativeThickness">0.75</sys:Double>
+ <!-- просто 0 -->
+ <sys:Double x:Key="Zero">0.0</sys:Double>
+ <!-- просто 1 -->
+ <sys:Double x:Key="One">1.0</sys:Double>
+ <!-- какой процент рисовать для неопределённого состояния -->
+ <sys:Double x:Key="IndeterminatePart">0.25</sys:Double>
+ <!-- обычно прогресс по умолчанию зелёный -->
+ <SolidColorBrush x:Key="ProgressBar.Progress" Color="#FF06B025"/>
+ <!-- стандартный фон -->
+ <SolidColorBrush x:Key="ProgressBar.Background" Color="#FFE6E6E6"/>
+ <!-- стандартный цвет границы -->
+ <SolidColorBrush x:Key="ProgressBar.Border" Color="#FFBCBCBC"/>
+ </Style.Resources>
+ <Setter Property="Foreground" Value="{StaticResource ProgressBar.Progress}"/>
+ <Setter Property="Background" Value="{StaticResource ProgressBar.Background}"/>
+ <Setter Property="BorderBrush" Value="{StaticResource ProgressBar.Border}"/>
+ <Setter Property="BorderThickness" Value="1"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type ProgressBar}">
+ <Grid x:Name="TemplateRoot">
+ <!-- в неопределённом состоянии запускаем вращающуюся анимацию -->
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Determinate"/>
+ <VisualState x:Name="Indeterminate">
+ <Storyboard RepeatBehavior="Forever">
+ <DoubleAnimation
+ Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"
+ Storyboard.TargetName="Animation"
+ From="0" To="360" Duration="0:0:2"/>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+
+ <!-- это фон, красим его в цвет фона-->
+ <Path Fill="{TemplateBinding Background}" Stretch="Uniform"
+ Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}">
+ <Path.Data>
+ <MultiBinding Converter="{StaticResource RoundProgressPathConverter}"
+ ConverterParameter="{StaticResource RelativeThickness}">
+ <!-- val=1, min=0, max=1 даёт полный круг -->
+ <Binding Source="{StaticResource One}"/>
+ <Binding Source="{StaticResource Zero}"/>
+ <Binding Source="{StaticResource One}"/>
+ </MultiBinding>
+ </Path.Data>
+ </Path>
+ <Path Fill="{TemplateBinding Foreground}" Stretch="Uniform" Name="Indicator">
+ <Path.Data>
+ <MultiBinding Converter="{StaticResource RoundProgressPathConverter}"
+ ConverterParameter="{StaticResource RelativeThickness}">
+ <Binding Path="Value" RelativeSource="{RelativeSource TemplatedParent}"/>
+ <Binding Path="Minimum" RelativeSource="{RelativeSource TemplatedParent}"/>
+ <Binding Path="Maximum" RelativeSource="{RelativeSource TemplatedParent}"/>
+ </MultiBinding>
+ </Path.Data>
+ </Path>
+ <!-- это анимировнная штука, будет показываться в неопределённом состоянии -->
+ <Path Fill="{TemplateBinding Foreground}" Stretch="Uniform" Name="Animation"
+ Visibility="Collapsed" RenderTransformOrigin="0.5,0.5">
+ <Path.Data>
+ <MultiBinding Converter="{StaticResource RoundProgressPathConverter}"
+ ConverterParameter="{StaticResource RelativeThickness}">
+ <Binding Source="{StaticResource IndeterminatePart}"/>
+ <Binding Source="{StaticResource Zero}"/>
+ <Binding Source="{StaticResource One}"/>
+ </MultiBinding>
+ </Path.Data>
+ <!-- положим пустое вращение, чтобы к нему цеплялась анимация -->
+ <Path.RenderTransform>
+ <RotateTransform/>
+ </Path.RenderTransform>
+ </Path>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <!-- в случае неопределённого состояния уберём нормальный индикатор и покажем анимацию -->
+ <Trigger Property="IsIndeterminate" Value="true">
+ <Setter Property="Visibility" TargetName="Indicator" Value="Collapsed"/>
+ <Setter Property="Visibility" TargetName="Animation" Value="Visible"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/ScrollBarStyle.xaml 89(+89 -0)
diff --git a/WPF/Common/WPF/Style/ScrollBarStyle.xaml b/WPF/Common/WPF/Style/ScrollBarStyle.xaml
new file mode 100644
index 0000000..9faa878
--- /dev/null
+++ b/WPF/Common/WPF/Style/ScrollBarStyle.xaml
@@ -0,0 +1,89 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <Style x:Key="ScrollBarLineButtonStyle" TargetType="{x:Type RepeatButton}">
+ <Setter Property="Focusable" Value="False"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type RepeatButton}">
+ <Canvas Height="18">
+ <Polygon Fill="{DynamicResource UiElementForegroundAlt}" Points="3,15 15,15 9,3"></Polygon>
+ </Canvas>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="ScrollBarLineButtonBottomStyle" TargetType="{x:Type RepeatButton}">
+ <Setter Property="Focusable" Value="False"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type RepeatButton}">
+ <Canvas Height="18">
+ <Polygon Fill="{DynamicResource UiElementForegroundAlt}" Points="3,3 9,15 15,3"></Polygon>
+ </Canvas>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="ScrollBarPageButtonStyle" TargetType="{x:Type RepeatButton}">
+ <Setter Property="IsTabStop" Value="False"/>
+ <Setter Property="Focusable" Value="False"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type RepeatButton}">
+ <Border BorderBrush="Transparent"></Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="ScrollBarThumbStyle" TargetType="{x:Type Thumb}">
+ <Setter Property="IsTabStop" Value="False"/>
+ <Setter Property="Focusable" Value="False"/>
+ <Setter Property="Margin" Value="1,0,1,0" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type Thumb}">
+ <Rectangle Fill="{DynamicResource UiElementForegroundAlt}" Margin="2"></Rectangle>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition MaxHeight="18"/>
+ <RowDefinition Height="*"/>
+ <RowDefinition MaxHeight="18"/>
+ </Grid.RowDefinitions>
+
+ <RepeatButton Grid.Row="0" Height="18"
+ Style="{StaticResource ScrollBarLineButtonStyle}"
+ Command="ScrollBar.LineUpCommand" >
+ </RepeatButton>
+ <Track Name="PART_Track" Grid.Row="1"
+ IsDirectionReversed="True">
+ <Track.DecreaseRepeatButton>
+ <RepeatButton Command="ScrollBar.PageUpCommand" Style="{StaticResource ScrollBarPageButtonStyle}">
+ </RepeatButton>
+ </Track.DecreaseRepeatButton>
+ <Track.Thumb>
+ <Thumb Style="{StaticResource ScrollBarThumbStyle}">
+ </Thumb>
+ </Track.Thumb>
+ <Track.IncreaseRepeatButton>
+ <RepeatButton Command="ScrollBar.PageDownCommand" Style="{StaticResource ScrollBarPageButtonStyle}">
+ </RepeatButton>
+ </Track.IncreaseRepeatButton>
+ </Track>
+ <RepeatButton Grid.Row="2" Height="18"
+ Style="{StaticResource ScrollBarLineButtonBottomStyle}"
+ Command="ScrollBar.LineDownCommand">
+ </RepeatButton>
+ </Grid>
+ </ControlTemplate>
+
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/TabControlStyle.xaml 93(+93 -0)
diff --git a/WPF/Common/WPF/Style/TabControlStyle.xaml b/WPF/Common/WPF/Style/TabControlStyle.xaml
new file mode 100644
index 0000000..d310b6a
--- /dev/null
+++ b/WPF/Common/WPF/Style/TabControlStyle.xaml
@@ -0,0 +1,93 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <!-- Полностью скопированный стандартный шаблон TabControl -->
+ <!-- за исключением панели переключения элементов -->
+ <Style x:Key="ControlStyleWithAddButton" TargetType="{x:Type TabControl}">
+ <Setter Property="Padding" Value="2"/>
+ <Setter Property="HorizontalContentAlignment" Value="Center"/>
+ <Setter Property="VerticalContentAlignment" Value="Center"/>
+ <Setter Property="Background" Value="White"/>
+ <Setter Property="BorderBrush" Value="#FFACACAC"/>
+ <Setter Property="BorderThickness" Value="1"/>
+ <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type TabControl}">
+ <Grid x:Name="templateRoot" ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition x:Name="ColumnDefinition0"/>
+ <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
+ <RowDefinition x:Name="RowDefinition1" Height="*"/>
+ </Grid.RowDefinitions>
+
+ <!-- Панель переключения элементов: начало -->
+
+ <!-- Стандартная панель переключения -->
+ <!-- <TabPanel x:Name="headerPanel" Background="Transparent" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" Grid.Column="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/> -->
+
+ <Grid Grid.Column="0" Grid.Row="0">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+
+ <Button Grid.Column="0"
+ Width="30" Margin="10,0,2,0" Padding="0"
+ Command="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext.AddCommand}"
+ CommandParameter="{Binding CommandParameter}">
+
+ <TextBlock Text="+" FontWeight="Bold" FontSize="22" Margin="0" Padding="0"/>
+ </Button>
+ <TabPanel Grid.Column="1" x:Name="HeaderPanel" Background="Transparent" IsItemsHost="True" Margin="2,2,10,0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
+ </Grid>
+
+ <!-- Панель переключения элементов: конец -->
+
+ <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
+ <ContentPresenter x:Name="PART_SelectedContentHost" ContentTemplate="{TemplateBinding SelectedContentTemplate}" Content="{TemplateBinding SelectedContent}" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
+ </Border>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="TabStripPlacement" Value="Bottom">
+ <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
+ <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
+ <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
+ <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
+ <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
+ </Trigger>
+ <Trigger Property="TabStripPlacement" Value="Left">
+ <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
+ <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
+ <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
+ <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
+ <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
+ <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
+ <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
+ <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
+ <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
+ </Trigger>
+ <Trigger Property="TabStripPlacement" Value="Right">
+ <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
+ <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
+ <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
+ <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
+ <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
+ <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
+ <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
+ <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
+ <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
+ </Trigger>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/TextBlockStyle.xaml 72(+72 -0)
diff --git a/WPF/Common/WPF/Style/TextBlockStyle.xaml b/WPF/Common/WPF/Style/TextBlockStyle.xaml
new file mode 100644
index 0000000..36249c0
--- /dev/null
+++ b/WPF/Common/WPF/Style/TextBlockStyle.xaml
@@ -0,0 +1,72 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <Style x:Key="MainTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#1585d0" />
+ <Setter Property="Margin" Value="5" />
+ </Style>
+ <Style x:Key="CaptionTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#13a2e8" />
+ <Setter Property="FontSize" Value="18" />
+ </Style>
+ <Style x:Key="NormalTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#13a2e8" />
+ <Setter Property="FontSize" Value="14" />
+ </Style>
+ <Style x:Key="WhiteNormalTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#FFE0E0E0" />
+ <Setter Property="FontSize" Value="14" />
+ </Style>
+ <Style x:Key="WarningTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="Yellow" />
+ <Setter Property="FontSize" Value="16" />
+ <Setter Property="FontStyle" Value="Italic"/>
+ </Style>
+ <Style x:Key="UgoTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#252525" />
+ <Setter Property="FontSize" Value="13" />
+ </Style>
+ <Style x:Key="WhiteCaptionTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#FFFFFF" />
+ <Setter Property="FontSize" Value="18" />
+ </Style>
+ <Style x:Key="MainHyperlinkStyle" TargetType="{x:Type Hyperlink}">
+ <Setter Property="Foreground" Value="#1585d0" />
+ <Setter Property="TextDecorations" Value="{x:Null}" />
+ <Setter Property="FontSize" Value="16" />
+ <Style.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Foreground" Value="#13a2e8" />
+ </Trigger>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter Property="Foreground" Value="#FFA9BAC6" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ <Style x:Key="CurrentVersion" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#1585d0" />
+ <Setter Property="FontSize" Value="8" />
+ <Setter Property="Text" Value="" />
+ </Style>
+ <Style x:Key="AltTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#FFBBD0DE" />
+ <Setter Property="Margin" Value="5" />
+ </Style>
+
+ <Style x:Key="{x:Type TextBlock}" TargetType="{x:Type TextBlock}">
+ <Setter Property="VerticalAlignment" Value="Center" />
+ <Setter Property="FontSize" Value="16" />
+ <Setter Property="FontFamily" Value="Helvetica" />
+ <Setter Property="Margin" Value="1" />
+ </Style>
+ <Style x:Key="AltWhiteCaptionTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="#FFFFFF" />
+ <Setter Property="FontSize" Value="16" />
+ </Style>
+ <Style x:Key="ButtonTextBlockStyle" TargetType="TextBlock">
+ <Setter Property="FontWeight" Value="Bold" />
+ <Setter Property="FontSize" Value="14" />
+ <Setter Property="TextWrapping" Value="WrapWithOverflow" />
+ <Setter Property="TextAlignment" Value="Center" />
+ </Style>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/TextBoxStyle.xaml 30(+30 -0)
diff --git a/WPF/Common/WPF/Style/TextBoxStyle.xaml b/WPF/Common/WPF/Style/TextBoxStyle.xaml
new file mode 100644
index 0000000..1825856
--- /dev/null
+++ b/WPF/Common/WPF/Style/TextBoxStyle.xaml
@@ -0,0 +1,30 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Style TargetType="{x:Type TextBox}">
+ <Setter Property="Padding" Value="1"/>
+ <Setter Property="AllowDrop" Value="true"/>
+ <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
+ <Setter Property="TextAlignment" Value="Center"/>
+ <Setter Property="VerticalAlignment" Value="Center" />
+ <Setter Property="FontSize" Value="16" />
+ <Setter Property="FontFamily" Value="Helvetica" />
+ <Setter Property="Margin" Value="2" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type TextBox}">
+ <Grid>
+ <Border BorderThickness="1">
+ <Border.Background>
+ <SolidColorBrush Color="#F9F9F9" x:Name="BgBrush" />
+ </Border.Background>
+ <Border.BorderBrush>
+ <SolidColorBrush Color="LightGray" x:Name="BordBrush" />
+ </Border.BorderBrush>
+ <ScrollViewer Margin="3" x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
+ </Border>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
\ No newline at end of file
WPF/Common/WPF/Style/WindowStyle.xaml 138(+138 -0)
diff --git a/WPF/Common/WPF/Style/WindowStyle.xaml b/WPF/Common/WPF/Style/WindowStyle.xaml
new file mode 100644
index 0000000..beb6b3d
--- /dev/null
+++ b/WPF/Common/WPF/Style/WindowStyle.xaml
@@ -0,0 +1,138 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:shell="clr-namespace:Microsoft.Windows.Shell;assembly=Microsoft.Windows.Shell"
+ xmlns:controls="clr-namespace:Common.WPF.Controls">
+
+ <Style x:Key="MainWindowStyle" TargetType="{x:Type Window}">
+ <Setter Property="shell:WindowChrome.WindowChrome">
+ <Setter.Value>
+ <shell:WindowChrome
+ ResizeBorderThickness="6"
+ CaptionHeight="30"
+ CornerRadius="0"
+ GlassFrameThickness="0,0,0,1"/>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Template" Value="{DynamicResource MainWindowControlTemplate}"/>
+ <Setter Property="SnapsToDevicePixels" Value="False" />
+ <Setter Property="RenderOptions.BitmapScalingMode" Value="HighQuality" />
+ <Setter Property="ShowInTaskbar" Value="True" />
+ </Style>
+
+ <Style x:Key="UgoWindowStyle" TargetType="{x:Type Window}">
+ <Setter Property="shell:WindowChrome.WindowChrome">
+ <Setter.Value>
+ <shell:WindowChrome
+ ResizeBorderThickness="6"
+ CaptionHeight="30"
+ CornerRadius="0"
+ GlassFrameThickness="0,0,0,1"/>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Template" Value="{DynamicResource UgoWindowControlTemplate}"/>
+ <Setter Property="SnapsToDevicePixels" Value="False" />
+ <Setter Property="RenderOptions.BitmapScalingMode" Value="HighQuality" />
+ <Setter Property="ShowInTaskbar" Value="True" />
+ </Style>
+
+ <Style x:Key="FixedSizeWindowStyle" TargetType="{x:Type Window}">
+ <Setter Property="shell:WindowChrome.WindowChrome">
+ <Setter.Value>
+ <shell:WindowChrome
+ ResizeBorderThickness="0"
+ CaptionHeight="30"
+ CornerRadius="0"
+ GlassFrameThickness="0,0,0,1"/>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Template" Value="{DynamicResource FixedSizeWindowControlTemplate}"/>
+ <Setter Property="SnapsToDevicePixels" Value="False" />
+ <Setter Property="RenderOptions.BitmapScalingMode" Value="HighQuality" />
+ <Setter Property="ShowInTaskbar" Value="True" />
+ </Style>
+
+ <ControlTemplate x:Key="MainWindowControlTemplate" TargetType="{x:Type Window}">
+ <Border>
+ <Border.Style>
+ <Style TargetType="{x:Type Border}">
+ <Setter Property="BorderThickness" Value="0"/>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding ElementName=Window, Path=WindowState}" Value="Maximized">
+ <Setter Property="BorderThickness" Value="{Binding Source={x:Static shell:SystemParameters2.Current}, Path=WindowResizeBorderThickness}"/>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Border.Style>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="30" />
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+
+ <!-- Captions Buttons to control the window borderless-->
+ <Border Background="{DynamicResource WindowBorder}" Grid.Row="0" />
+ <TextBlock Padding="10" Style="{DynamicResource CurrentVersion}" Grid.Row="0" />
+ <TextBlock Grid.Row="0" HorizontalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Title}" VerticalAlignment="Center" />
+ <controls:CaptionButtons Margin="0,0,10,0" Grid.Row="0" HorizontalAlignment="Right" Type="Full"
+ Foreground="{DynamicResource CaptionButtonColor}" FontSize="14" MarginButton="0,0,5,0"
+ VerticalAlignment="Center" shell:WindowChrome.IsHitTestVisibleInChrome="True"/>
+ <Border Grid.Row="1" Background="{DynamicResource WindowBackground}">
+ <ContentPresenter Content="{TemplateBinding Content}" />
+ </Border>
+ </Grid>
+ </Border>
+ </ControlTemplate>
+
+ <ControlTemplate x:Key="UgoWindowControlTemplate" TargetType="{x:Type Window}">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="30" />
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+
+ <!-- Captions Buttons to control the window borderless-->
+ <Border Background="{DynamicResource WindowBorder}" Grid.Row="0" />
+ <TextBlock Padding="10" Style="{DynamicResource CurrentVersion}" Grid.Row="0" />
+ <TextBlock Grid.Row="0" HorizontalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Title}" VerticalAlignment="Center" />
+ <controls:CaptionButtons Margin="0,0,10,0" Grid.Row="0" HorizontalAlignment="Right" Type="Full"
+ Foreground="{DynamicResource CaptionButtonColor}" FontSize="14" MarginButton="0,0,5,0"
+ VerticalAlignment="Center" shell:WindowChrome.IsHitTestVisibleInChrome="True"/>
+ <Border Grid.Row="1" Background="{DynamicResource UgoWindowBackground}">
+ <ContentPresenter Content="{TemplateBinding Content}" />
+ </Border>
+ </Grid>
+ </ControlTemplate>
+
+ <ControlTemplate x:Key="FixedSizeWindowControlTemplate" TargetType="{x:Type Window}">
+ <Border>
+ <Border.Style>
+ <Style TargetType="{x:Type Border}">
+ <Setter Property="BorderThickness" Value="0"/>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding ElementName=Window, Path=WindowState}" Value="Maximized">
+ <Setter Property="BorderThickness" Value="{Binding Source={x:Static shell:SystemParameters2.Current}, Path=WindowResizeBorderThickness}"/>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Border.Style>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="30" />
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+
+ <!-- Captions Buttons to control the window borderless-->
+ <Border Background="{DynamicResource WindowBorder}" Grid.Row="0" />
+ <TextBlock Padding="10" Style="{DynamicResource CurrentVersion}" Grid.Row="0" />
+ <TextBlock Grid.Row="0" HorizontalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Title}" VerticalAlignment="Center" />
+ <controls:CaptionButtons Margin="0,0,10,0" Grid.Row="0" HorizontalAlignment="Right" Type="ReduceClose"
+ Foreground="{DynamicResource CaptionButtonColor}" FontSize="14" MarginButton="0,0,5,0"
+ VerticalAlignment="Center" shell:WindowChrome.IsHitTestVisibleInChrome="True" />
+ <Border Grid.Row="1" Background="{DynamicResource WindowBackground}">
+ <ContentPresenter Content="{TemplateBinding Content}" />
+ </Border>
+ </Grid>
+ </Border>
+
+ </ControlTemplate>
+</ResourceDictionary>
\ No newline at end of file
WPF/FodyWeavers.xml 3(+3 -0)
diff --git a/WPF/FodyWeavers.xml b/WPF/FodyWeavers.xml
new file mode 100644
index 0000000..5029e70
--- /dev/null
+++ b/WPF/FodyWeavers.xml
@@ -0,0 +1,3 @@
+<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
+ <Costura />
+</Weavers>
\ No newline at end of file
WPF/FodyWeavers.xsd 111(+111 -0)
diff --git a/WPF/FodyWeavers.xsd b/WPF/FodyWeavers.xsd
new file mode 100644
index 0000000..44a5374
--- /dev/null
+++ b/WPF/FodyWeavers.xsd
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
+ <xs:element name="Weavers">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="Costura" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:all>
+ <xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:all>
+ <xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="DisableCompression" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="DisableCleanup" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="LoadAtModuleInit" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="ExcludeAssemblies" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="IncludeAssemblies" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="Unmanaged32Assemblies" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="Unmanaged64Assemblies" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="PreloadOrder" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+ <xs:attribute name="VerifyAssembly" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="VerifyIgnoreCodes" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="GenerateXsd" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
WPF/Model/EnumTheorem.cs 16(+16 -0)
diff --git a/WPF/Model/EnumTheorem.cs b/WPF/Model/EnumTheorem.cs
new file mode 100644
index 0000000..c0c8f7c
--- /dev/null
+++ b/WPF/Model/EnumTheorem.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.ComponentModel;
+
+namespace WPF.Model
+{
+ public enum EnumTheorem
+ {
+ [Description("Первая теорема")]
+ First = 1,
+ [Description("Вторая теорема")]
+ Second = 2,
+ }
+}
WPF/packages.config 5(+5 -0)
diff --git a/WPF/packages.config b/WPF/packages.config
new file mode 100644
index 0000000..01e2767
--- /dev/null
+++ b/WPF/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Costura.Fody" version="4.1.0" targetFramework="net45" />
+ <package id="Fody" version="6.0.0" targetFramework="net45" developmentDependency="true" />
+</packages>
\ No newline at end of file
WPF/Properties/AssemblyInfo.cs 55(+55 -0)
diff --git a/WPF/Properties/AssemblyInfo.cs b/WPF/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4fe502b
--- /dev/null
+++ b/WPF/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// Общие сведения об этой сборке предоставляются следующим набором
+// набор атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
+// связанные со сборкой.
+[assembly: AssemblyTitle("WPF")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WPF")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми
+// для компонентов COM. Если необходимо обратиться к типу в этой сборке через
+// из модели COM, установите атрибут ComVisible для этого типа в значение true.
+[assembly: ComVisible(false)]
+
+//Чтобы начать создание локализуемых приложений, задайте
+//<UICulture>CultureYouAreCodingWith</UICulture> в файле .csproj
+//в <PropertyGroup>. Например, при использовании английского (США)
+//в своих исходных файлах установите <UICulture> в en-US. Затем отмените преобразование в комментарий
+//атрибута NeutralResourceLanguage ниже. Обновите "en-US" в
+//строка внизу для обеспечения соответствия настройки UICulture в файле проекта.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //где расположены словари ресурсов по конкретным тематикам
+ //(используется, если ресурс не найден на странице,
+ // или в словарях ресурсов приложения)
+ ResourceDictionaryLocation.SourceAssembly //где расположен словарь универсальных ресурсов
+ //(используется, если ресурс не найден на странице,
+ // в приложении или в каких-либо словарях ресурсов для конкретной темы)
+)]
+
+
+// Сведения о версии для сборки включают четыре следующих значения:
+//
+// Основной номер версии
+// Дополнительный номер версии
+// Номер сборки
+// Номер редакции
+//
+// Можно задать все значения или принять номера сборки и редакции по умолчанию
+// используя "*", как показано ниже:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
WPF/Properties/Resources.Designer.cs 71(+71 -0)
diff --git a/WPF/Properties/Resources.Designer.cs b/WPF/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..f5ce365
--- /dev/null
+++ b/WPF/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// Этот код был создан программным средством.
+// Версия среды выполнения: 4.0.30319.42000
+//
+// Изменения в этом файле могут привести к неправильному поведению и будут утрачены, если
+// код создан повторно.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace WPF.Properties
+{
+
+
+ /// <summary>
+ /// Класс ресурсов со строгим типом для поиска локализованных строк и пр.
+ /// </summary>
+ // Этот класс был автоматически создан при помощи StronglyTypedResourceBuilder
+ // класс с помощью таких средств, как ResGen или Visual Studio.
+ // Для добавления или удаления члена измените файл .ResX, а затем перезапустите ResGen
+ // с параметром /str или заново постройте свой VS-проект.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ /// <summary>
+ /// Возврат кэшированного экземпляра ResourceManager, используемого этим классом.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WPF.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Переопределяет свойство CurrentUICulture текущего потока для всех
+ /// подстановки ресурсов с помощью этого класса ресурсов со строгим типом.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
WPF/Properties/Resources.resx 117(+117 -0)
diff --git a/WPF/Properties/Resources.resx b/WPF/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/WPF/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
\ No newline at end of file
WPF/Properties/Settings.Designer.cs 30(+30 -0)
diff --git a/WPF/Properties/Settings.Designer.cs b/WPF/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..e172b6d
--- /dev/null
+++ b/WPF/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace WPF.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
WPF/Properties/Settings.settings 7(+7 -0)
diff --git a/WPF/Properties/Settings.settings b/WPF/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/WPF/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
\ No newline at end of file
WPF/View/MainWindow.xaml 88(+88 -0)
diff --git a/WPF/View/MainWindow.xaml b/WPF/View/MainWindow.xaml
new file mode 100644
index 0000000..7d5b892
--- /dev/null
+++ b/WPF/View/MainWindow.xaml
@@ -0,0 +1,88 @@
+<Window x:Class="WPF.View.MainWindow"
+ 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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:local="clr-namespace:WPF.View"
+ xmlns:converters="clr-namespace:Common.WPF.Converters"
+ WindowStartupLocation="CenterScreen"
+ mc:Ignorable="d"
+ x:Name="Window"
+ WindowState="{Binding WindowState}"
+ Background="{StaticResource WindowBackground}"
+ WindowStyle="None"
+ ResizeMode="CanResizeWithGrip"
+ AllowsTransparency="True"
+ Loaded="Window_Loaded"
+ Title="Password storage"
+ Height="450" Width="800"
+ MinHeight="370" MinWidth="630"
+ BorderBrush="#FF494957"
+ BorderThickness="1">
+ <Window.Resources>
+ <Style TargetType="{x:Type ScrollBar}">
+ <Setter Property="Template" Value="{StaticResource VerticalScrollBar}"/>
+ </Style>
+ <Style TargetType="{x:Type Expander}" BasedOn="{StaticResource AdvancedExpander}"/>
+ <Style TargetType="ToolTip">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ToolTip">
+ <Border BorderThickness="1" BorderBrush="Gray" CornerRadius="2" Background="{StaticResource WindowBackground}">
+ <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ </Window.Resources>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+
+ <Grid Grid.Row="0" Background="{StaticResource WindowBackground}" x:Name="Header">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"></ColumnDefinition>
+ <ColumnDefinition Width="Auto"></ColumnDefinition>
+ </Grid.ColumnDefinitions>
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.Column="0" Margin="74,0,0,0">
+ <!--<TextBlock Text="RubezhCAD - " FontSize="18" Foreground="{StaticResource UiElementForegroundAlt}" Visibility="{Binding StandaloneApplication, Converter={StaticResource InversedBoolToVisibilityConverter}}"/>-->
+ <TextBlock Text="Password strorage" FontSize="18" Foreground="{StaticResource Yellow}"/>
+ </StackPanel>
+ <StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,5,0">
+ <Button Style="{StaticResource MinimizeButton}" Width="23" Height="23"
+ Command="{Binding MinimizeCommand}" />
+ <Button Height="23" Width="23" Style="{StaticResource MaximizeButton}"
+ Command="{Binding MaximizeCommand}" CommandParameter="{Binding ElementName=Window}" />
+ <Button Style="{StaticResource CloseButton}" Width="23" Height="23"
+ Command="{Binding CloseCommand}"
+ CommandParameter="{Binding ElementName=Window}" HorizontalAlignment="Right"/>
+ </StackPanel>
+ </Grid>
+
+ <Grid Grid.Row="1" Background="{StaticResource WindowBackground}">
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+
+ <ComboBox Grid.Row="0" Grid.Column="0" Style="{StaticResource ComboBoxStyle}" ItemsSource="{Binding EnumTheorems}" SelectedItem="{Binding SelectedTheorem}" Width="Auto">
+ <ComboBox.ItemTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding Converter={StaticResource EnumToDescriptionConverter}}"/>
+ </DataTemplate>
+ </ComboBox.ItemTemplate>
+ </ComboBox>
+
+ </Grid>
+
+ </Grid>
+</Window>
WPF/View/MainWindow.xaml.cs 94(+94 -0)
diff --git a/WPF/View/MainWindow.xaml.cs b/WPF/View/MainWindow.xaml.cs
new file mode 100644
index 0000000..0db4991
--- /dev/null
+++ b/WPF/View/MainWindow.xaml.cs
@@ -0,0 +1,94 @@
+using WPF.ViewModel;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace WPF.View
+{
+ /// <summary>
+ /// Логика взаимодействия для MainWindow.xaml
+ /// </summary>
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ DataContext = new MainViewModel();
+ Application.Current.Dispatcher.BeginInvoke(
+ System.Windows.Threading.DispatcherPriority.ApplicationIdle,
+ new Action(() =>
+ {
+ (DataContext as MainViewModel).OnLoad();
+ }));
+ }
+
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ var myHeaderGrid = (Grid)this.FindName("Header");
+ if (myHeaderGrid != null)
+ {
+ myHeaderGrid.MouseLeftButtonDown += OnMouseDown;
+ }
+ }
+
+ private void OnMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ if (e.ChangedButton == MouseButton.Left)
+ {
+ DragMove();
+ }
+ }
+
+ private void textBox_DoubleInput(object sender, TextCompositionEventArgs e)
+ {
+ TextBox thisTextBox = (sender as TextBox);
+ e.Handled =
+ (!(char.IsDigit(e.Text, 0) /*&& !((thisTextBox.Text.IndexOf("-") == 0) && thisTextBox.SelectionStart == 0)*/ )) &&
+ //((e.Text.Substring(0, 1) != "-") || (thisTextBox.Text.IndexOf("-") == 0) || thisTextBox.SelectionStart != 0) &&
+ ((e.Text.Substring(0, 1) != ".") || (thisTextBox.Text.IndexOf(".") != -1) || (thisTextBox.SelectionStart == 0) || (!char.IsDigit(thisTextBox.Text.Substring(thisTextBox.SelectionStart - 1, 1), 0)) || ((thisTextBox.Text.IndexOf(",") != -1))) &&
+ ((e.Text.Substring(0, 1) != ",") || (thisTextBox.Text.IndexOf(",") != -1) || (thisTextBox.SelectionStart == 0) || (!char.IsDigit(thisTextBox.Text.Substring(thisTextBox.SelectionStart - 1, 1), 0)) || ((thisTextBox.Text.IndexOf(".") != -1)));
+ }
+ private void textBox_IntInput(object sender, TextCompositionEventArgs e)
+ {
+ TextBox thisTextBox = (sender as TextBox);
+ e.Handled = (!(char.IsNumber(e.Text, 0)));
+ }
+
+ private void TextBox_LostFocus(object sender, RoutedEventArgs e)
+ {
+ if (sender is TextBox textBox)
+ {
+ if (string.IsNullOrEmpty(textBox.Text))
+ {
+ textBox.Text = "0";
+ return;
+ }
+ if (double.TryParse(textBox.Text.Replace(',', '.'), System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, out double res))
+ {
+ if (res < 0)
+ textBox.Text = "0";
+ }
+ else
+ {
+ textBox.Text = "0";
+ }
+ }
+ }
+
+ private bool isFocused = false;
+ private void TextBox_GotFocus(object sender, RoutedEventArgs e)
+ {
+ isFocused = true;
+ }
+
+ private void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
+ {
+ if (isFocused)
+ {
+ isFocused = false;
+ (sender as TextBox).SelectAll();
+ }
+ }
+ }
+}
WPF/ViewModel/MainViewModel.cs 62(+62 -0)
diff --git a/WPF/ViewModel/MainViewModel.cs b/WPF/ViewModel/MainViewModel.cs
new file mode 100644
index 0000000..c802607
--- /dev/null
+++ b/WPF/ViewModel/MainViewModel.cs
@@ -0,0 +1,62 @@
+using Common.WPF;
+//using WPF.Helpers;
+using WPF.Model;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace WPF.ViewModel
+{
+ public class MainViewModel : ModifyViewModel
+ {
+ public MainViewModel() : base()
+ {
+ //Items = new ObservableCollection<ItemViewModel>();
+ //System.Windows.Data.BindingOperations.EnableCollectionSynchronization(Items, _lock);
+ //CreatePanel = new CreatingViewModel(this);
+ //IsAllDataHide = true;
+
+ EnumTheorems = Enum.GetValues(typeof(EnumTheorem)).Cast<EnumTheorem>().ToList();
+ SelectedTheorem = EnumTheorems.First();
+
+ //AddItemCommand = new RelayCommand<ItemViewModel>(OnAddItem, item => Items.FirstOrDefault(e => e.Value == item.Value) == null);
+ //RemoveItemCommand = new RelayCommand<ItemViewModel>(OnRemoveItem, item => !item.Readonly);
+ //OpenFileCommand = new RelayCommand(OnOpenFile);
+ //SwitchDataVisibleCommand = new RelayCommand(OnSwitchDataVisible);
+ //ClearSearchCommand = new RelayCommand(OnClearSearch);
+ }
+
+ #region Поля и свойства
+
+ public List<EnumTheorem> EnumTheorems { get; }
+
+ private EnumTheorem _selectedTheorem;
+ public EnumTheorem SelectedTheorem
+ {
+ set
+ {
+ _selectedTheorem = value;
+ OnPropertyChanged(()=> SelectedTheorem);
+ // do smth
+ }
+
+ get => _selectedTheorem;
+ }
+
+ #endregion
+
+ #region Методы и команды
+
+ public void OnLoad()
+ {
+ //LoadData(App.DataFilePath);
+ //LoadDataAsync(App.DataFilePath, true);
+ }
+
+ #endregion
+
+ }
+}
WPF/WPF.csproj 321(+321 -0)
diff --git a/WPF/WPF.csproj b/WPF/WPF.csproj
new file mode 100644
index 0000000..8bab0e8
--- /dev/null
+++ b/WPF/WPF.csproj
@@ -0,0 +1,321 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" />
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{6086DC2B-27CD-43B8-BA7B-D6A41C92CE4B}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <RootNamespace>WPF</RootNamespace>
+ <AssemblyName>WPF</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ <Deterministic>true</Deterministic>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
+ <HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.Windows.Shell">
+ <HintPath>Common\Microsoft.Windows.Shell.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xaml">
+ <RequiredTargetFramework>4.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="WindowsBase" />
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ <Page Include="Common\WPF\Controls\CaptionButtons.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Dictionary.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Add.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\AddSub.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Copy.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Delete.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\DeleteItem.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\DeviceDeviceIcon.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Down.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Help.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Open.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Pointer.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Read.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Search.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Settings.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\StartEndIcon.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Substract.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\TreeListExpander.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Up.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\VisibleHide.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\VisibleOn.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Icons\Warning.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\ButtonStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\Colors.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\ComboBoxStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\ExpandCollapseToggleStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\ExpanderStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\GroupBoxStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\ListBoxStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\ProgressbarStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\ScrollBarStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\TabControlStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\TextBlockStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\TextBoxStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Common\WPF\Style\WindowStyle.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="View\MainWindow.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Common\Helpers\AppPaths.cs" />
+ <Compile Include="Common\Helpers\BringToFront.cs" />
+ <Compile Include="Common\Helpers\IniFile.cs" />
+ <Compile Include="Common\Helpers\MyExtensions.cs" />
+ <Compile Include="Common\Helpers\ProgressBar.cs" />
+ <Compile Include="Common\Helpers\QSort.cs" />
+ <Compile Include="Common\Helpers\SelfDiagnose.cs" />
+ <Compile Include="Common\Helpers\StatusBar.cs" />
+ <Compile Include="Common\Parameters\Parameter.cs" />
+ <Compile Include="Common\Parameters\ParameterBool.cs" />
+ <Compile Include="Common\Parameters\ParameterDouble.cs" />
+ <Compile Include="Common\Parameters\ParameterInt.cs" />
+ <Compile Include="Common\Parameters\ParameterRange.cs" />
+ <Compile Include="Common\Parameters\ParameterString.cs" />
+ <Compile Include="Common\Parameters\Status.cs" />
+ <Compile Include="Common\WPF\BaseViewModel.cs" />
+ <Compile Include="Common\WPF\Controls\CaptionButtons.xaml.cs">
+ <DependentUpon>CaptionButtons.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Common\WPF\Controls\EditorPresenter.cs" />
+ <Compile Include="Common\WPF\Controls\TreeGridViewRowPresenter.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\IItemComparer.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\ITreeList.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\RootTreeNodeViewModel.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\RowExpander.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\SortBehavior.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\TreeItemCollection.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\TreeList.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\TreeListItem.cs" />
+ <Compile Include="Common\WPF\Controls\TreeList\TreeNodeViewModel.cs" />
+ <Compile Include="Common\WPF\Converters\BoolToVisibilityConverter.cs" />
+ <Compile Include="Common\WPF\Converters\CanExpandConverter.cs" />
+ <Compile Include="Common\WPF\Converters\ColorToBrushConverter.cs" />
+ <Compile Include="Common\WPF\Converters\ColumnWidthConverter.cs" />
+ <Compile Include="Common\WPF\Converters\EnumToDescrConverter.cs" />
+ <Compile Include="Common\WPF\Converters\InverseBooleanConverter.cs" />
+ <Compile Include="Common\WPF\Converters\InversedBoolToVisibilityConverter.cs" />
+ <Compile Include="Common\WPF\Converters\LevelToIndentConverter.cs" />
+ <Compile Include="Common\WPF\Converters\RadioButtonToIntConverter.cs" />
+ <Compile Include="Common\WPF\Converters\RoundProgressPathConverter.cs" />
+ <Compile Include="Common\WPF\Converters\StatusToColorConverter.cs" />
+ <Compile Include="Common\WPF\Converters\ValueConverter.cs" />
+ <Compile Include="Common\WPF\IEditingBaseViewModel.cs" />
+ <Compile Include="Common\WPF\ModifyViewModel.cs" />
+ <Compile Include="Common\WPF\NotifyPropertyChangedHelper.cs" />
+ <Compile Include="Common\WPF\ObservableCollectionAdv.cs" />
+ <Compile Include="Common\WPF\RelayCommand.cs" />
+ <Compile Include="Model\EnumTheorem.cs" />
+ <Compile Include="ViewModel\MainViewModel.cs" />
+ <Compile Include="View\MainWindow.xaml.cs">
+ <DependentUpon>MainWindow.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <None Include="packages.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\HyperGraphModel\HyperGraphModel.csproj">
+ <Project>{09fecaa7-0025-45b4-a633-9f07edb28c5a}</Project>
+ <Name>HyperGraphModel</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Common\Assets\" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="FodyWeavers.xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Common\Microsoft.Windows.Shell.dll" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="..\packages\Fody.6.0.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.0.0\build\Fody.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>Данный проект ссылается на пакеты NuGet, отсутствующие на этом компьютере. Используйте восстановление пакетов NuGet, чтобы скачать их. Дополнительную информацию см. по адресу: http://go.microsoft.com/fwlink/?LinkID=322105. Отсутствует следующий файл: {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\packages\Fody.6.0.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.0.0\build\Fody.targets'))" />
+ <Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" />
+ </Target>
+</Project>
\ No newline at end of file