瀏覽代碼

添加项目文件。

jz.kai 1 年之前
當前提交
94e8cb17c7
共有 100 個文件被更改,包括 6018 次插入0 次删除
  1. 63 0
      .gitattributes
  2. 27 0
      .gitignore
  3. 7 0
      Arthas-WPFUI/.gitignore
  4. 8 0
      Arthas-WPFUI/Arthas.Demo/App.xaml
  5. 8 0
      Arthas-WPFUI/Arthas.Demo/App.xaml.cs
  6. 14 0
      Arthas-WPFUI/Arthas.Demo/Arthas.Demo.csproj
  7. 516 0
      Arthas-WPFUI/Arthas.Demo/MainWindow.xaml
  8. 121 0
      Arthas-WPFUI/Arthas.Demo/MainWindow.xaml.cs
  9. 118 0
      Arthas-WPFUI/Arthas.Demo/MainWindow_Model.cs
  10. 3 0
      Arthas-WPFUI/Arthas.Demo/Properties/AssemblyInfo.cs
  11. 二進制
      Arthas-WPFUI/Arthas.Demo/Resources/editIcon.png
  12. 二進制
      Arthas-WPFUI/Arthas.Demo/Resources/icon.png
  13. 二進制
      Arthas-WPFUI/Arthas.Demo/Resources/iconMove.png
  14. 二進制
      Arthas-WPFUI/Arthas.Demo/Resources/pic.jpg
  15. 二進制
      Arthas-WPFUI/Arthas.Demo/Resources/tabIcon.png
  16. 二進制
      Arthas-WPFUI/Arthas.Demo/Resources/titleMuenIcon.png
  17. 41 0
      Arthas-WPFUI/Arthas.sln
  18. 8 0
      Arthas-WPFUI/Arthas/Arthas.csproj
  19. 5 0
      Arthas-WPFUI/Arthas/Controls/MetroBase.xaml
  20. 29 0
      Arthas-WPFUI/Arthas/Controls/MetroBorder.cs
  21. 30 0
      Arthas-WPFUI/Arthas/Controls/MetroButton.cs
  22. 75 0
      Arthas-WPFUI/Arthas/Controls/MetroButton.xaml
  23. 31 0
      Arthas-WPFUI/Arthas/Controls/MetroCanvasGrid.cs
  24. 51 0
      Arthas-WPFUI/Arthas/Controls/MetroCanvasGrid.xaml
  25. 240 0
      Arthas-WPFUI/Arthas/Controls/MetroColorPicker.xaml
  26. 233 0
      Arthas-WPFUI/Arthas/Controls/MetroColorPicker.xaml.cs
  27. 26 0
      Arthas-WPFUI/Arthas/Controls/MetroComboBox.cs
  28. 37 0
      Arthas-WPFUI/Arthas/Controls/MetroComboBox.xaml
  29. 18 0
      Arthas-WPFUI/Arthas/Controls/MetroComboBoxItem.cs
  30. 7 0
      Arthas-WPFUI/Arthas/Controls/MetroComboBoxItem.xaml
  31. 18 0
      Arthas-WPFUI/Arthas/Controls/MetroContextMenu.cs
  32. 30 0
      Arthas-WPFUI/Arthas/Controls/MetroContextMenu.xaml
  33. 94 0
      Arthas-WPFUI/Arthas/Controls/MetroExpander.cs
  34. 146 0
      Arthas-WPFUI/Arthas/Controls/MetroExpander.xaml
  35. 31 0
      Arthas-WPFUI/Arthas/Controls/MetroFocusButton.cs
  36. 75 0
      Arthas-WPFUI/Arthas/Controls/MetroFocusButton.xaml
  37. 13 0
      Arthas-WPFUI/Arthas/Controls/MetroGroupBox.cs
  38. 31 0
      Arthas-WPFUI/Arthas/Controls/MetroGroupBox.xaml
  39. 40 0
      Arthas-WPFUI/Arthas/Controls/MetroImage.cs
  40. 27 0
      Arthas-WPFUI/Arthas/Controls/MetroImage.xaml
  41. 24 0
      Arthas-WPFUI/Arthas/Controls/MetroMenuItem.cs
  42. 73 0
      Arthas-WPFUI/Arthas/Controls/MetroMenuItem.xaml
  43. 13 0
      Arthas-WPFUI/Arthas/Controls/MetroMenuSeparator.cs
  44. 17 0
      Arthas-WPFUI/Arthas/Controls/MetroMenuSeparator.xaml
  45. 53 0
      Arthas-WPFUI/Arthas/Controls/MetroMenuTabControl.cs
  46. 186 0
      Arthas-WPFUI/Arthas/Controls/MetroMenuTabControl.xaml
  47. 23 0
      Arthas-WPFUI/Arthas/Controls/MetroMenuTabItem.cs
  48. 60 0
      Arthas-WPFUI/Arthas/Controls/MetroMenuTabItem.xaml
  49. 19 0
      Arthas-WPFUI/Arthas/Controls/MetroPath.cs
  50. 25 0
      Arthas-WPFUI/Arthas/Controls/MetroPath.xaml
  51. 47 0
      Arthas-WPFUI/Arthas/Controls/MetroProgressBar.cs
  52. 110 0
      Arthas-WPFUI/Arthas/Controls/MetroProgressBar.xaml
  53. 224 0
      Arthas-WPFUI/Arthas/Controls/MetroRichTextBox.cs
  54. 103 0
      Arthas-WPFUI/Arthas/Controls/MetroRichTextBox.xaml
  55. 29 0
      Arthas-WPFUI/Arthas/Controls/MetroScrollViewer.cs
  56. 229 0
      Arthas-WPFUI/Arthas/Controls/MetroScrollViewer.xaml
  57. 39 0
      Arthas-WPFUI/Arthas/Controls/MetroSwitch.cs
  58. 73 0
      Arthas-WPFUI/Arthas/Controls/MetroSwitch.xaml
  59. 26 0
      Arthas-WPFUI/Arthas/Controls/MetroTabControl.cs
  60. 69 0
      Arthas-WPFUI/Arthas/Controls/MetroTabControl.xaml
  61. 19 0
      Arthas-WPFUI/Arthas/Controls/MetroTabItem.cs
  62. 59 0
      Arthas-WPFUI/Arthas/Controls/MetroTabItem.xaml
  63. 30 0
      Arthas-WPFUI/Arthas/Controls/MetroTextBlock.cs
  64. 42 0
      Arthas-WPFUI/Arthas/Controls/MetroTextBlock.xaml
  65. 64 0
      Arthas-WPFUI/Arthas/Controls/MetroTextBox.cs
  66. 178 0
      Arthas-WPFUI/Arthas/Controls/MetroTextBox.xaml
  67. 13 0
      Arthas-WPFUI/Arthas/Controls/MetroTextButton.cs
  68. 48 0
      Arthas-WPFUI/Arthas/Controls/MetroTextButton.xaml
  69. 66 0
      Arthas-WPFUI/Arthas/Controls/MetroThumb.cs
  70. 18 0
      Arthas-WPFUI/Arthas/Controls/MetroTitleMenu.cs
  71. 28 0
      Arthas-WPFUI/Arthas/Controls/MetroTitleMenu.xaml
  72. 24 0
      Arthas-WPFUI/Arthas/Controls/MetroTitleMenuItem.cs
  73. 82 0
      Arthas-WPFUI/Arthas/Controls/MetroTitleMenuItem.xaml
  74. 32 0
      Arthas-WPFUI/Arthas/Controls/MetroVisualElement.cs
  75. 36 0
      Arthas-WPFUI/Arthas/Controls/MetroVisualElement.xaml
  76. 144 0
      Arthas-WPFUI/Arthas/Controls/MetroWaterfallFlow.cs
  77. 15 0
      Arthas-WPFUI/Arthas/Controls/MetroWaterfallFlow.xaml
  78. 91 0
      Arthas-WPFUI/Arthas/Controls/MetroWindow.cs
  79. 209 0
      Arthas-WPFUI/Arthas/Controls/MetroWindow.xaml
  80. 27 0
      Arthas-WPFUI/Arthas/Controls/MetroWindow.xaml.cs
  81. 50 0
      Arthas-WPFUI/Arthas/Controls/Utility.cs
  82. 28 0
      Arthas-WPFUI/Arthas/Converter/CornerRadiusToDouble.cs
  83. 40 0
      Arthas-WPFUI/Arthas/Converter/DoubleFactor.cs
  84. 27 0
      Arthas-WPFUI/Arthas/Converter/DoubleToCornerRadius.cs
  85. 85 0
      Arthas-WPFUI/Arthas/Converter/DoubleToThickness.cs
  86. 19 0
      Arthas-WPFUI/Arthas/Converter/StringToVisibility.cs
  87. 5 0
      Arthas-WPFUI/Arthas/Properties/AssemblyInfo.cs
  88. 32 0
      Arthas-WPFUI/Arthas/Themes/Generic.xaml
  89. 21 0
      Arthas-WPFUI/Arthas/Themes/Theme.cs
  90. 82 0
      Arthas-WPFUI/Arthas/Utility/Element/ElementBase.cs
  91. 21 0
      Arthas-WPFUI/Arthas/Utility/Element/VisualObj.cs
  92. 81 0
      Arthas-WPFUI/Arthas/Utility/Media/HsbaColor.cs
  93. 38 0
      Arthas-WPFUI/Arthas/Utility/Media/ResObj.cs
  94. 95 0
      Arthas-WPFUI/Arthas/Utility/Media/RgbaColor.cs
  95. 30 0
      Arthas-WPFUI/Arthas/Utility/Media/StreamObj.cs
  96. 196 0
      Arthas-WPFUI/Arthas/Utility/Media/Utility.cs
  97. 21 0
      Arthas-WPFUI/LICENSE
  98. 17 0
      Arthas-WPFUI/README.md
  99. 二進制
      Arthas-WPFUI/Screenshots/1.png
  100. 242 0
      DataAccess/AppConfigHelper.cs

+ 63 - 0
.gitattributes

@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs     diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following 
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln       merge=binary
+#*.csproj    merge=binary
+#*.vbproj    merge=binary
+#*.vcxproj   merge=binary
+#*.vcproj    merge=binary
+#*.dbproj    merge=binary
+#*.fsproj    merge=binary
+#*.lsproj    merge=binary
+#*.wixproj   merge=binary
+#*.modelproj merge=binary
+#*.sqlproj   merge=binary
+#*.wwaproj   merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg   binary
+#*.png   binary
+#*.gif   binary
+
+###############################################################################
+# diff behavior for common document formats
+# 
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the 
+# entries below.
+###############################################################################
+#*.doc   diff=astextplain
+#*.DOC   diff=astextplain
+#*.docx  diff=astextplain
+#*.DOCX  diff=astextplain
+#*.dot   diff=astextplain
+#*.DOT   diff=astextplain
+#*.pdf   diff=astextplain
+#*.PDF   diff=astextplain
+#*.rtf   diff=astextplain
+#*.RTF   diff=astextplain

+ 27 - 0
.gitignore

@@ -0,0 +1,27 @@
+################################################################################
+# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
+################################################################################
+
+/.git
+/.vs
+/Bin
+/Bin_x64
+/Bin_x86
+/packages
+/x64
+/DataAccess/bin
+/DataAccess/obj
+/LayuiPack/Core/Layui.Core/bin
+/LayuiPack/Core/Layui.Core/obj
+/LayuiPack/LayuiApp/bin
+/LayuiPack/LayuiApp/obj
+/LayuiPack/LayuiTemplate/bin
+/LayuiPack/LayuiTemplate/obj
+/LayuiPack/Models/LayuiComponentExample/bin
+/LayuiPack/Models/LayuiComponentExample/obj
+/LayuiPack/Models/LayuiFundamentalElement/bin
+/LayuiPack/Models/LayuiFundamentalElement/obj
+/LayuiPack/Models/LayuiHome/bin
+/LayuiPack/Models/LayuiHomme/obj
+/WpfModBus/bin
+/WpfModBus/obj

+ 7 - 0
Arthas-WPFUI/.gitignore

@@ -0,0 +1,7 @@
+# VS
+.VS
+bin
+obj
+*.csproj.user
+*.pubxml.user
+.idea

+ 8 - 0
Arthas-WPFUI/Arthas.Demo/App.xaml

@@ -0,0 +1,8 @@
+<Application
+    x:Class="Arthas.Demo.App"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    StartupUri="MainWindow.xaml">
+    <Application.Resources>
+    </Application.Resources>
+</Application>

+ 8 - 0
Arthas-WPFUI/Arthas.Demo/App.xaml.cs

@@ -0,0 +1,8 @@
+using System.Windows;
+
+namespace Arthas.Demo
+{
+    public partial class App : Application
+    {
+    }
+}

+ 14 - 0
Arthas-WPFUI/Arthas.Demo/Arthas.Demo.csproj

@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
+    <PropertyGroup>
+        <TargetFrameworks>net452</TargetFrameworks>
+        <LangVersion>latest</LangVersion>
+        <UseWPF>true</UseWPF>
+        <OutputType>WinExe</OutputType>
+    </PropertyGroup>
+    <ItemGroup>
+        <ProjectReference Include="..\Arthas\Arthas.csproj" />
+    </ItemGroup>
+    <ItemGroup>
+        <Resource Include="Resources\**" />
+    </ItemGroup>
+</Project>

+ 516 - 0
Arthas-WPFUI/Arthas.Demo/MainWindow.xaml

@@ -0,0 +1,516 @@
+<Metro:MetroWindow
+    x:Class="Arthas.Demo.MainWindow"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:local="clr-namespace:Arthas.Demo"
+    xmlns:Metro="https://github.com/1217950746/Arthas-WPFUI"
+    Title="{Binding Title}">
+    <Metro:MetroWindow.DataContext>
+        <local:MainWindow_Model />
+    </Metro:MetroWindow.DataContext>
+    <Metro:MetroWindow.Menu>
+        <Metro:MetroTitleMenu>
+            <Metro:MetroTitleMenuItem Header="多级菜单测试" Icon="Resources/titleMuenIcon.png">
+                <Metro:MetroMenuItem Header="二级菜单" />
+                <Metro:MetroMenuItem Header="二级菜单" IsEnabled="False" />
+                <Metro:MetroMenuItem Header="二级菜单" />
+                <Metro:MetroMenuSeparator />
+                <Metro:MetroMenuItem Header="二级菜单" />
+                <Metro:MetroMenuItem Header="二级菜单" Icon="Resources/titleMuenIcon.png" />
+                <Metro:MetroMenuItem Header="内部是三级菜单" Icon="Resources/titleMuenIcon.png">
+                    <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                    <Metro:MetroMenuItem Header="三级菜单" IsEnabled="False" Icon="Resources/titleMuenIcon.png" />
+                    <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                    <Metro:MetroMenuSeparator />
+                    <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                    <Metro:MetroMenuItem Header="内部是三级菜单" Icon="Resources/titleMuenIcon.png">
+                        <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                        <Metro:MetroMenuItem Header="三级菜单" IsEnabled="False" Icon="Resources/titleMuenIcon.png" />
+                        <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                        <Metro:MetroMenuSeparator />
+                        <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                        <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                    </Metro:MetroMenuItem>
+                </Metro:MetroMenuItem>
+                <Metro:MetroMenuItem Header="二级菜单" />
+            </Metro:MetroTitleMenuItem>
+            <Metro:MetroTitleMenuItem Header="测试" IsEnabled="False" Icon="Resources/titleMuenIcon.png" />
+            <Metro:MetroTitleMenuItem Header="测试" IsEnabled="False" />
+            <Metro:MetroTitleMenuItem Header="文件" />
+            <Metro:MetroTitleMenuItem Header="关于" Icon="Resources/titleMuenIcon.png" />
+        </Metro:MetroTitleMenu>
+    </Metro:MetroWindow.Menu>
+    <Metro:MetroWindow.ContextMenu>
+        <Metro:MetroContextMenu>
+            <Metro:MetroMenuItem Header="二级菜单" />
+            <Metro:MetroMenuItem Header="二级菜单" IsEnabled="False" />
+            <Metro:MetroMenuItem Header="二级菜单" />
+            <Metro:MetroMenuSeparator />
+            <Metro:MetroMenuItem Header="二级菜单" />
+            <Metro:MetroMenuItem Header="二级菜单" Icon="Resources/titleMuenIcon.png" />
+            <Metro:MetroMenuItem Header="内部是三级菜单" Icon="Resources/titleMuenIcon.png">
+                <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                <Metro:MetroMenuItem Header="三级菜单" IsEnabled="False" Icon="Resources/titleMuenIcon.png" />
+                <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                <Metro:MetroMenuSeparator />
+                <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                <Metro:MetroMenuItem Header="内部是三级菜单" Icon="Resources/titleMuenIcon.png">
+                    <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                    <Metro:MetroMenuItem Header="三级菜单" IsEnabled="False" Icon="Resources/titleMuenIcon.png" />
+                    <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                    <Metro:MetroMenuSeparator />
+                    <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                    <Metro:MetroMenuItem Header="三级菜单" Icon="Resources/titleMuenIcon.png" />
+                </Metro:MetroMenuItem>
+            </Metro:MetroMenuItem>
+            <Metro:MetroMenuSeparator />
+            <Metro:MetroMenuItem x:Name="exit" Header="退出程序" />
+        </Metro:MetroContextMenu>
+    </Metro:MetroWindow.ContextMenu>
+    <Grid>
+        <Metro:MetroMenuTabControl x:Name="tab" IconMode="True">
+            <Metro:MetroMenuTabItem Header="控件" Icon="Resources/icon.png" IconMove="Resources/iconMove.png">
+                <Grid>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition MinWidth="160" Width="Auto" />
+                        <ColumnDefinition />
+                    </Grid.ColumnDefinitions>
+                    <Metro:MetroScrollViewer>
+                        <Border BorderBrush="#19000000" BorderThickness="0,0,1,0">
+                            <StackPanel x:Name="lists">
+                                <Metro:MetroExpander Header="Button" Hint="提示" Icon="Resources/tabIcon.png" />
+                                <Metro:MetroExpander Header="Button" Hint="1 / 100" />
+                                <Metro:MetroExpander Header="Header" Hint="可以修改" HintBackground="#FFF15151">
+                                    <StackPanel>
+                                        <Metro:MetroExpander Header="Button" Icon="Resources/tabIcon.png" />
+                                        <Metro:MetroExpander Header="Button" Icon="Resources/tabIcon.png" />
+                                        <Metro:MetroExpander Header="Button" Icon="Resources/tabIcon.png" />
+                                        <Metro:MetroExpander Header="Button" />
+                                        <Metro:MetroExpander Header="Button" />
+                                    </StackPanel>
+                                </Metro:MetroExpander>
+                                <Metro:MetroExpander Header="Header" IsExpanded="True">
+                                    <StackPanel>
+                                        <Metro:MetroExpander Header="子内容长标题测试" Icon="Resources/tabIcon.png" Hint="1 / 100" />
+                                        <Metro:MetroExpander Header="Button" />
+                                        <Metro:MetroExpander Header="Button" />
+                                        <Metro:MetroExpander Header="Button" />
+                                    </StackPanel>
+                                </Metro:MetroExpander>
+                                <Metro:MetroExpander Header="Button" />
+                                <Metro:MetroExpander Header="Button" />
+                            </StackPanel>
+                        </Border>
+                    </Metro:MetroScrollViewer>
+                    <Metro:MetroTabControl x:Name="tabc" Grid.Column="1">
+                        <Metro:MetroTabItem Header="预览控件" Icon="Resources/tabIcon.png">
+                            <Grid>
+                                <Metro:MetroScrollViewer>
+                                    <Metro:MetroWaterfallFlow x:Name="waterfallFlow" ListWidth="300">
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="主题颜色(MetroColorPicker 实现)">
+                                                <Grid>
+                                                    <WrapPanel Orientation="Horizontal">
+                                                        <Metro:MetroColorPicker x:Name="color1" Width="50" Height="50" Background="#6D819A" DefaultColor="#6D819A" Padding="5" />
+                                                        <Metro:MetroColorPicker x:Name="color2" Width="50" Height="50" Background="#6D819A" DefaultColor="#6D819A" Padding="5" IsEnabled="False" />
+                                                    </WrapPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="组合框">
+                                                <Grid>
+                                                    <StackPanel>
+                                                        <Metro:MetroComboBox IsEnabled="False" Text="MetroComboBox" Icon="Resources/editIcon.png" Title="默认标题">
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem0" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem1" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem2" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem3" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem4" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem5" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem6" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem7" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem8" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem9" />
+                                                        </Metro:MetroComboBox>
+                                                        <Metro:MetroComboBox Text="MetroComboBox" />
+                                                        <Metro:MetroComboBox Text="MetroComboBox" Title="默认标题">
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem0" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem1" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem2" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem3" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem4" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem5" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem6" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem7" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem8" />
+                                                            <Metro:MetroComboBoxItem Content="MetroComboBoxItem9" />
+                                                        </Metro:MetroComboBox>
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="多选框">
+                                                <Grid>
+                                                    <StackPanel>
+                                                        <StackPanel Orientation="Horizontal">
+                                                            <CheckBox Content="CheckBox" Margin="5" IsEnabled="False" />
+                                                            <CheckBox Content="CheckBox" Margin="5" />
+                                                        </StackPanel>
+                                                        <StackPanel Orientation="Horizontal">
+                                                            <CheckBox Content="CheckBox" Margin="5" IsEnabled="False" IsChecked="True" />
+                                                            <CheckBox Content="CheckBox" Margin="5" IsChecked="True" />
+                                                        </StackPanel>
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="字体选择器">
+                                                <Grid>
+                                                    <StackPanel></StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="等待">
+                                                <Grid>
+                                                    <StackPanel Background="#00000000">
+                                                        <Metro:MetroProgressBar Title="MetroProgressBar 等待禁用" Margin="60,5,5,5" ProgressBarState="Wait" IsEnabled="False" />
+                                                        <Metro:MetroProgressBar x:Name="vis" Title="MetroProgressBar 等待" Margin="5" ProgressBarState="Wait" />
+                                                        <Metro:MetroVisualElement Visual="{Binding ElementName=vis}" VisualOpacity="0.5" VisualBlurRadius="10" Width="{Binding ActualWidth,ElementName=vis}" Height="{Binding ActualHeight,ElementName=vis}" />
+                                                        <Metro:MetroProgressBar Title="MetroProgressBar 等待调整大小" Margin="5,5,60,5" ProgressBarState="Wait" ProgressBarHeight="30" CornerRadius="15" />
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="单选框">
+                                                <Grid>
+                                                    <StackPanel>
+                                                        <StackPanel Orientation="Horizontal">
+                                                            <RadioButton Content="CheckBox" Margin="5" IsEnabled="False" />
+                                                            <RadioButton Content="CheckBox" Margin="5" />
+                                                        </StackPanel>
+                                                        <StackPanel Orientation="Horizontal">
+                                                            <RadioButton Content="CheckBox" Margin="5" IsEnabled="False" IsChecked="True" />
+                                                            <RadioButton Content="CheckBox" Margin="5" IsChecked="True" />
+                                                        </StackPanel>
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="进度条">
+                                                <Grid>
+                                                    <StackPanel Background="#00000000">
+                                                        <Metro:MetroProgressBar Margin="5" Value="15" ProgressBarHeight="30" CornerRadius="0" ProgressBarState="None" IsEnabled="False" />
+                                                        <Metro:MetroProgressBar x:Name="pb1" Title="MetroProgressBar 调整" Margin="5" Value="20" ProgressBarHeight="20" CornerRadius="0" ProgressBarState="None" TextHorizontalAlignment="Center" />
+                                                        <Metro:MetroProgressBar x:Name="pb2" Title="MetroProgressBar 正常" Margin="5" Value="0" TextHorizontalAlignment="Right" Maximum="50" />
+                                                        <Metro:MetroProgressBar Title="MetroProgressBar 错误" Margin="5" Value="40" ProgressBarState="Error" />
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="文本编辑器">
+                                                <Grid>
+                                                    <StackPanel>
+                                                        <Metro:MetroRichTextBox MaxHeight="50" Margin="5" IsEnabled="False">
+                                                            <FlowDocument>
+                                                                <Paragraph>
+                                                                    <Run Text="禁用" />
+                                                                </Paragraph>
+                                                            </FlowDocument>
+                                                        </Metro:MetroRichTextBox>
+                                                        <Metro:MetroRichTextBox x:Name="rt1" Margin="5" MaxHeight="50" IsReadOnly="True">
+                                                            <FlowDocument>
+                                                                <Paragraph>
+                                                                    <Run Text="阅读模式" />
+                                                                </Paragraph>
+                                                            </FlowDocument>
+                                                        </Metro:MetroRichTextBox>
+                                                        <Metro:MetroRichTextBox x:Name="rt3" MaxHeight="100" Margin="5" AutoLimitMouse="True">
+                                                            <FlowDocument>
+                                                                <Paragraph>
+                                                                    <Run Text="追加内容" />
+                                                                </Paragraph>
+                                                                <Paragraph>
+                                                                    <Run Text="自动高度" />
+                                                                </Paragraph>
+                                                            </FlowDocument>
+                                                        </Metro:MetroRichTextBox>
+                                                        <Metro:MetroRichTextBox Margin="5" MaxHeight="100" BorderThickness="0" CornerRadius="0" Background="#00000000" IsEnabled="False">
+                                                            <FlowDocument>
+                                                                <Paragraph>
+                                                                    <Run Text="修改外观的 MetroRichTextBox" />
+                                                                </Paragraph>
+                                                                <Paragraph>
+                                                                    <Run Text="禁用" />
+                                                                </Paragraph>
+                                                            </FlowDocument>
+                                                        </Metro:MetroRichTextBox>
+                                                        <Metro:MetroRichTextBox Margin="5" MaxHeight="100" BorderThickness="0" CornerRadius="0" Background="#00000000">
+                                                            <FlowDocument>
+                                                                <Paragraph>
+                                                                    <Run Text="修改外观的 MetroRichTextBox" />
+                                                                </Paragraph>
+                                                                <Paragraph>
+                                                                    <Run Text="正常" />
+                                                                </Paragraph>
+                                                            </FlowDocument>
+                                                        </Metro:MetroRichTextBox>
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="树形框">
+                                                <Grid>
+                                                    <StackPanel>
+                                                        <TreeView IsEnabled="False" Margin="5">
+                                                            <TreeViewItem Header="TreeViewItem" />
+                                                            <TreeViewItem Header="TreeViewItem">
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                            </TreeViewItem>
+                                                            <TreeViewItem Header="TreeViewItem" />
+                                                        </TreeView>
+                                                        <TreeView IsEnabled="False" Margin="5">
+                                                            <TreeViewItem Header="TreeViewItem" />
+                                                            <TreeViewItem Header="TreeViewItem" IsExpanded="True">
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                            </TreeViewItem>
+                                                            <TreeViewItem Header="TreeViewItem" />
+                                                        </TreeView>
+                                                        <TreeView x:Name="treeView" Margin="5">
+                                                            <TreeViewItem Header="TreeViewItem" />
+                                                            <TreeViewItem Header="TreeViewItem">
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                                <TreeViewItem Header="TreeViewItem" />
+                                                            </TreeViewItem>
+                                                            <TreeViewItem Header="TreeViewItem" />
+                                                        </TreeView>
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="画布背景">
+                                                <Grid>
+                                                    <StackPanel>
+                                                        <Metro:MetroCanvasGrid Height="100" Margin="5" />
+                                                        <Metro:MetroCanvasGrid Height="100" Width="100" Margin="5" Background="Blue" GridOpacity="0.5"  CornerRadius="50"  >
+                                                            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+                                                                <Metro:MetroTextBlock Text="test" TextBlock.FontSize="35"  />
+                                                            </StackPanel>
+                                                        </Metro:MetroCanvasGrid>
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="图片框">
+                                                <Grid>
+                                                    <StackPanel>
+                                                        <Metro:MetroTextBlock Text="自动调整大小,不用管图片的PPI" Opacity="0.65" />
+                                                        <Metro:MetroImage Source="Resources/pic.jpg" Margin="0,5,0,0" />
+                                                    </StackPanel>
+                                                </Grid>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="开关">
+                                                <StackPanel>
+                                                    <Metro:MetroSwitch Content="关闭禁用" Margin="10" IsEnabled="False" />
+                                                    <Metro:MetroSwitch Content="打开禁用" IsChecked="true" Margin="10" IsEnabled="False" />
+                                                    <Metro:MetroSwitch Content="可以修改对齐方式" IsChecked="true" Margin="10" TextHorizontalAlignment="Right" />
+                                                    <Metro:MetroSwitch x:Name="ts" Content="特殊动画" Margin="10" CornerRadius="100" />
+                                                    <Metro:MetroSwitch Content="方块模式" Margin="10" CornerRadius="2" BorderCornerRadius="3" />
+                                                </StackPanel>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="编辑框">
+                                                <StackPanel>
+                                                    <Metro:MetroTextBox x:Name="password" InputHint="PassWord Input Box!" IsPassWordBox="True" ButtonTitle="确定" PopupHint="请输入密码" />
+                                                    <Metro:MetroTextBox InputHint="InputHint..." PopupHint="This is TextBox!" Margin="0,10,0,0" />
+                                                    <Metro:MetroTextBox Margin="0,10,0,0" />
+                                                    <Metro:MetroTextBox Title="Default Title" InputHint="InputHint..." PopupHint="This is TextBox!" Margin="0,10,0,0" />
+                                                    <Metro:MetroTextBox x:Name="check" Title="Default Title" InputHint="InputHint..." ButtonTitle="Button" PopupHint="Length is more than 10!" Margin="0,10,0,0" Icon="Resources/editIcon.png" />
+                                                    <Metro:MetroTextBox x:Name="check1" Text="0123456789" Title="Default Title" InputHint="InputHint..." ButtonTitle="Button" PopupHint="Length is more than 10!" Margin="0,10,0,0" Icon="Resources/editIcon.png" />
+                                                    <Metro:MetroTextBox Title="Default Title" InputHint="InputHint..." Text="This is Content!" ButtonTitle="Button" PopupHint="这是一个多行编辑框!" Margin="0,10,0,0" Icon="Resources/editIcon.png" MultipleLine="True" />
+                                                    <Metro:MetroTextBox Title="Default Title" InputHint="InputHint..." ButtonTitle="Button" PopupHint="Length is more than 10!" Margin="0,10,0,0" Icon="Resources/editIcon.png" IsEnabled="False" />
+                                                    <Metro:MetroTextBox Title="Default Title" InputHint="InputHint..." Text="已经输入内容且禁用" ButtonTitle="Button" PopupHint="Length is more than 10!" Margin="0,10,0,0" Icon="Resources/editIcon.png" IsEnabled="False" />
+                                                </StackPanel>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                        <Grid>
+                                            <Metro:MetroGroupBox Header="按钮">
+                                                <StackPanel HorizontalAlignment="Center">
+                                                    <StackPanel Orientation="Horizontal">
+                                                        <Metro:MetroButton MetroButtonState="None" Content="默认颜色" IsEnabled="False" Margin="10" />
+                                                        <Metro:MetroButton MetroButtonState="None" Content="默认颜色" Command="{Binding CmdSample}" IsEnabled="{Binding BtnEnabled}" Margin="10" />
+                                                    </StackPanel>
+                                                    <StackPanel Orientation="Horizontal">
+                                                        <Metro:MetroButton MetroButtonState="Red" Content="错误颜色" IsEnabled="False" Margin="10" />
+                                                        <Metro:MetroButton MetroButtonState="Red" Content="错误颜色" Command="{Binding CmdSampleWithParam}" CommandParameter="Bad" IsEnabled="{Binding BtnEnabled}" Margin="10" />
+                                                    </StackPanel>
+                                                    <StackPanel Orientation="Horizontal">
+                                                        <Metro:MetroButton MetroButtonState="Green" Content="正确颜色" IsEnabled="False" Margin="10" />
+                                                        <Metro:MetroButton MetroButtonState="Green" Content="正确颜色" Command="{Binding CmdSampleWithParam}" CommandParameter="Good" IsEnabled="{Binding BtnEnabled}" Margin="10" />
+                                                    </StackPanel>
+                                                </StackPanel>
+                                            </Metro:MetroGroupBox>
+                                        </Grid>
+                                    </Metro:MetroWaterfallFlow>
+                                </Metro:MetroScrollViewer>
+                            </Grid>
+                        </Metro:MetroTabItem>
+                        <Metro:MetroTabItem Header="测试标签" />
+                    </Metro:MetroTabControl>
+                </Grid>
+            </Metro:MetroMenuTabItem>
+            <Metro:MetroMenuTabItem Header="瀑布流控件" Icon="Resources/icon.png" IconMove="Resources/iconMove.png">
+                <Grid>
+                    <Metro:MetroScrollViewer>
+                        <Metro:MetroWaterfallFlow ListWidth="180">
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="500">
+                                    <Metro:MetroTextBlock FontSize="30" Text="1" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="100">
+                                    <Metro:MetroTextBlock FontSize="30" Text="2" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="200">
+                                    <Metro:MetroTextBlock FontSize="30" Text="3" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="300">
+                                    <Metro:MetroTextBlock FontSize="30" Text="4" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="400">
+                                    <Metro:MetroTextBlock FontSize="30" Text="5" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="300">
+                                    <Metro:MetroTextBlock FontSize="30" Text="6" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="200">
+                                    <Metro:MetroTextBlock FontSize="30" Text="7" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="100">
+                                    <Metro:MetroTextBlock FontSize="30" Text="8" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="300">
+                                    <Metro:MetroTextBlock FontSize="30" Text="9" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="200">
+                                    <Metro:MetroTextBlock FontSize="30" Text="10" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="500">
+                                    <Metro:MetroTextBlock FontSize="30" Text="11" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="400">
+                                    <Metro:MetroTextBlock FontSize="30" Text="12" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="200">
+                                    <Metro:MetroTextBlock FontSize="30" Text="13" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="100">
+                                    <Metro:MetroTextBlock FontSize="30" Text="14" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="50">
+                                    <Metro:MetroTextBlock FontSize="30" Text="15" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="50">
+                                    <Metro:MetroTextBlock FontSize="30" Text="16" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="80">
+                                    <Metro:MetroTextBlock FontSize="30" Text="17" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="90">
+                                    <Metro:MetroTextBlock FontSize="30" Text="18" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="40">
+                                    <Metro:MetroTextBlock FontSize="30" Text="19" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                            <Grid>
+                                <Border BorderBrush="#33000000" BorderThickness="1" Height="200">
+                                    <Metro:MetroTextBlock FontSize="30" Text="20" Margin="7,0,0,0" Opacity="0.65" />
+                                </Border>
+                            </Grid>
+                        </Metro:MetroWaterfallFlow>
+                    </Metro:MetroScrollViewer>
+                </Grid>
+            </Metro:MetroMenuTabItem>
+            <Metro:MetroMenuTabItem Header="滚动框" Icon="Resources/icon.png" IconMove="Resources/iconMove.png" Height="40" VerticalAlignment="Top">
+                <Grid>
+                    <Metro:MetroScrollViewer>
+                        <Grid Width="2000" Height="2000">
+                            <Grid Opacity="0.2" Width="600" Height="600">
+                                <Grid.Background>
+                                    <RadialGradientBrush>
+                                        <GradientStop Color="Black" Offset="0" />
+                                        <GradientStop Color="Black" Offset="1" />
+                                        <GradientStop Color="#00000000" Offset="1" />
+                                    </RadialGradientBrush>
+                                </Grid.Background>
+                            </Grid>
+                        </Grid>
+                    </Metro:MetroScrollViewer>
+                    <StackPanel Margin="0,-200,0,0" VerticalAlignment="Center">
+                        <Metro:MetroTextBlock Text="按住左Ctrl并滚动,可以横向滚动视图" HorizontalAlignment="Center" Opacity="0.65" FontSize="18" />
+                        <Metro:MetroTextBlock Text="鼠标移动到滚动条,出现操作区域" HorizontalAlignment="Center" Opacity="0.65" FontSize="18" Margin="0,10,0,0" />
+                    </StackPanel>
+                </Grid>
+            </Metro:MetroMenuTabItem>
+        </Metro:MetroMenuTabControl>
+    </Grid>
+</Metro:MetroWindow>

+ 121 - 0
Arthas-WPFUI/Arthas.Demo/MainWindow.xaml.cs

@@ -0,0 +1,121 @@
+using Arthas.Controls;
+using Arthas.Utility.Media;
+using System;
+using System.Windows;
+using System.Windows.Threading;
+
+namespace Arthas.Demo
+{
+    public partial class MainWindow : MetroWindow
+    {
+        public MainWindow()
+        {
+            InitializeComponent();
+
+            color1.ColorChange += delegate
+            {
+                // 不要通过XAML来绑定颜色,无法获取到通知
+                BorderBrush = color1.CurrentColor.OpaqueSolidColorBrush;
+            };
+
+            ts.IsChecked = true;
+
+            exit.Click += delegate { Close(); };
+
+            treeView.SizeChanged += delegate { waterfallFlow.Refresh(); };
+
+            rt1.Clear();
+
+            rt1.AddLine("阅读模式");
+            rt1.AddLine();
+            rt1.AddLine("添加正常内容");
+            rt1.AddLine("添加正常内容可点击", delegate { MessageBox.Show("你点击了我!"); });
+            rt1.AddLine("添加自定义颜色内容", new RgbaColor(255, 0, 0, 255));
+            rt1.AddLine("添加自定义颜色内容可点击", new RgbaColor(255, 0, 0, 255), delegate { MessageBox.Show("你点击了我!"); });
+
+            rt3.Clear();
+
+            rt3.AddLine("内容追加测试(不换行添加)");
+            rt3.AddLine("http://www.baidu.com", "http://www.baidu.com");
+            rt3.AddLine("中间的间距是Add(\"  \");方法添加的两个空格");
+            rt3.AddLine();
+
+            rt3.AddLine("追加正常内容");
+            rt3.AddLine();
+            rt3.Add("正常1");
+            rt3.Add("   ");
+            rt3.Add("正常2");
+            rt3.Add("   ");
+            rt3.Add("正常3");
+            rt3.AddLine();
+
+            rt3.AddLine("追加正常内容可点击");
+            rt3.AddLine();
+            rt3.Add("正常1", delegate { MessageBox.Show("你点击了我!"); });
+            rt3.Add("   ");
+            rt3.Add("正常2", delegate { MessageBox.Show("你点击了我!"); });
+            rt3.Add("   ");
+            rt3.Add("正常3", delegate { MessageBox.Show("你点击了我!"); });
+            rt3.AddLine();
+
+            rt3.AddLine("追加自定义颜色内容");
+            rt3.AddLine();
+            rt3.Add("颜色1", new RgbaColor(255, 0, 0, 255));
+            rt3.Add("   ");
+            rt3.Add("颜色2", new RgbaColor(0, 255, 0, 255));
+            rt3.Add("   ");
+            rt3.Add("颜色3", new RgbaColor(0, 0, 255, 255));
+            rt3.AddLine();
+
+            rt3.AddLine("追加自定义颜色内容可点击");
+            rt3.AddLine();
+            rt3.Add("颜色1", new RgbaColor(255, 0, 0, 255), delegate { MessageBox.Show("你点击了我!"); });
+            rt3.Add("   ");
+            rt3.Add("颜色2", new RgbaColor(0, 255, 0, 255), delegate { MessageBox.Show("你点击了我!"); });
+            rt3.Add("   ");
+            rt3.Add("颜色3", new RgbaColor(0, 0, 255, 255), delegate { MessageBox.Show("你点击了我!"); });
+            rt3.AddLine();
+
+            DispatcherTimer timer = new DispatcherTimer();
+            timer.Tick += delegate
+            {
+                pb1.Value = pb1.Value + 1 > pb1.Maximum ? 0 : pb1.Value + 1;
+                pb2.Value = pb2.Value + 1 > pb2.Maximum ? 0 : pb2.Value + 1;
+                pb2.Title = pb2.Hint;
+                pb2.Hint = null;
+            };
+            timer.Interval = new TimeSpan(0, 0, 0, 0, 20);
+            timer.Start();
+
+            foreach (FrameworkElement fe in lists.Children)
+            {
+                if (fe is MetroExpander)
+                {
+                    (fe as MetroExpander).Click += delegate (object sender, EventArgs e)
+                    {
+                        if ((fe as MetroExpander).CanHide)
+                        {
+                            foreach (FrameworkElement fe1 in lists.Children)
+                            {
+                                if (fe1 is MetroExpander && fe1 != sender)
+                                {
+                                    (fe1 as MetroExpander).IsExpanded = false;
+                                }
+                            }
+                        }
+                    };
+                }
+            }
+
+            /*
+            // Chrome 浏览器封装
+            ChromeBrowser chrome = new ChromeBrowser();
+            chromeGrid.Children.Add(chrome);
+            chromeText.Text = chrome.Address;
+            chromeText.ButtonClick += delegate { chrome.Load(chromeText.Text); };
+            chromeText.KeyUp += delegate (object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { chrome.Load(chromeText.Text); } };
+            chrome.Load("http://ie.icoa.cn/");
+            */
+        }
+    }
+}

+ 118 - 0
Arthas-WPFUI/Arthas.Demo/MainWindow_Model.cs

@@ -0,0 +1,118 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace Arthas.Demo
+{
+    public class MainWindow_Model : INotifyPropertyChanged
+    {
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+        }
+
+        private string _title = "Arthas.Demo";
+
+        public string Title
+        {
+            get { return _title; }
+            set { _title = value; OnPropertyChanged(); }
+        }
+
+        private bool _btnEnabled = true;
+
+        public bool BtnEnabled
+        {
+            get { return _btnEnabled; }
+            set { _btnEnabled = value; OnPropertyChanged(); }
+        }
+
+        private ICommand _cmdSample;
+
+        public ICommand CmdSample => _cmdSample ?? (_cmdSample = new AsyncCommand(async () =>
+        {
+            Title = "Busy...";
+            BtnEnabled = false;
+            //do something
+            await Task.Delay(2000);
+            Title = "Arthas.Demo";
+            BtnEnabled = true;
+        }));
+
+        private ICommand _cmdSampleWithParam;
+
+        public ICommand CmdSampleWithParam => _cmdSampleWithParam ?? (_cmdSampleWithParam = new AsyncCommand<string>(async str =>
+        {
+            Title = $"Hello I'm {str} currently";
+            BtnEnabled = false;
+            //do something
+            await Task.Delay(2000);
+            Title = "Arthas.Demo";
+            BtnEnabled = true;
+        }));
+    }
+
+    #region Command
+
+    public class AsyncCommand : ICommand
+    {
+        protected readonly Predicate<object> _canExecute;
+        protected Func<Task> _asyncExecute;
+
+        public AsyncCommand(Func<Task> asyncExecute, Predicate<object> canExecute = null)
+        {
+            _asyncExecute = asyncExecute;
+            _canExecute = canExecute;
+        }
+
+        public bool CanExecute(object parameter)
+        {
+            return _canExecute == null || _canExecute(parameter);
+        }
+
+        public event EventHandler CanExecuteChanged
+        {
+            add { CommandManager.RequerySuggested += value; }
+            remove { CommandManager.RequerySuggested -= value; }
+        }
+
+        public async void Execute(object parameter)
+        {
+            await _asyncExecute();
+        }
+    }
+
+    public class AsyncCommand<T> : ICommand
+    {
+        protected readonly Predicate<T> _canExecute;
+        protected Func<T, Task> _asyncExecute;
+
+        public event EventHandler CanExecuteChanged
+        {
+            add { CommandManager.RequerySuggested += value; }
+            remove { CommandManager.RequerySuggested -= value; }
+        }
+
+        public AsyncCommand(Func<T, Task> asyncExecute, Predicate<T> canExecute = null)
+        {
+            _asyncExecute = asyncExecute;
+            _canExecute = canExecute;
+        }
+
+        public bool CanExecute(object parameter)
+        {
+            return _canExecute == null || _canExecute((T)parameter);
+        }
+
+        public async void Execute(object parameter)
+        {
+            await _asyncExecute((T)parameter);
+        }
+    }
+
+    #endregion Command
+}

+ 3 - 0
Arthas-WPFUI/Arthas.Demo/Properties/AssemblyInfo.cs

@@ -0,0 +1,3 @@
+using System.Windows;
+
+[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

二進制
Arthas-WPFUI/Arthas.Demo/Resources/editIcon.png


二進制
Arthas-WPFUI/Arthas.Demo/Resources/icon.png


二進制
Arthas-WPFUI/Arthas.Demo/Resources/iconMove.png


二進制
Arthas-WPFUI/Arthas.Demo/Resources/pic.jpg


二進制
Arthas-WPFUI/Arthas.Demo/Resources/tabIcon.png


二進制
Arthas-WPFUI/Arthas.Demo/Resources/titleMuenIcon.png


+ 41 - 0
Arthas-WPFUI/Arthas.sln

@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28516.95
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arthas.Demo", "Arthas.Demo\Arthas.Demo.csproj", "{20827429-E998-4EA3-BB34-DB49CBD0FCC0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arthas", "Arthas\Arthas.csproj", "{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Debug|x86.Build.0 = Debug|Any CPU
+		{20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Release|x86.ActiveCfg = Release|Any CPU
+		{20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Release|x86.Build.0 = Release|Any CPU
+		{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Debug|x86.Build.0 = Debug|Any CPU
+		{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Release|x86.ActiveCfg = Release|Any CPU
+		{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Release|x86.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {7C504695-968E-4B6B-9812-AD4D7B1EB6EC}
+	EndGlobalSection
+EndGlobal

+ 8 - 0
Arthas-WPFUI/Arthas/Arthas.csproj

@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
+    <PropertyGroup>
+        <TargetFrameworks>net452</TargetFrameworks>
+        <LangVersion>latest</LangVersion>
+        <UseWPF>true</UseWPF>
+        <UseWindowsForms>true</UseWindowsForms>
+    </PropertyGroup>
+</Project>

+ 5 - 0
Arthas-WPFUI/Arthas/Controls/MetroBase.xaml

@@ -0,0 +1,5 @@
+<ResourceDictionary
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+    <SolidColorBrush x:Key="Brush" Color="#FF6D819A" />
+</ResourceDictionary>

+ 29 - 0
Arthas-WPFUI/Arthas/Controls/MetroBorder.cs

@@ -0,0 +1,29 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroBorder : Border
+    {
+        public static readonly DependencyProperty AutoCornerRadiusProperty = ElementBase.Property<MetroBorder, bool>(nameof(AutoCornerRadiusProperty));
+        public bool AutoCornerRadius { get { return (bool)GetValue(AutoCornerRadiusProperty); } set { SetValue(AutoCornerRadiusProperty, value); } }
+
+        public MetroBorder()
+        {
+            Loaded += delegate { SizeChang(); };
+            SizeChanged += delegate { SizeChang(); };
+        }
+
+        void SizeChang()
+        {
+            if (AutoCornerRadius)
+            {
+                if (IsLoaded)
+                {
+                    CornerRadius = new CornerRadius(ActualWidth >= ActualHeight ? ActualHeight / 2 : ActualWidth / 2);
+                }
+            }
+        }
+    }
+}

+ 30 - 0
Arthas-WPFUI/Arthas/Controls/MetroButton.cs

@@ -0,0 +1,30 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public enum ButtonState
+    {
+        None,
+        Red,
+        Green
+    }
+
+    public class MetroButton : Button
+    {
+        public static readonly DependencyProperty MetroButtonStateProperty = ElementBase.Property<MetroButton, ButtonState>(nameof(MetroButtonStateProperty), ButtonState.None);
+
+        public ButtonState MetroButtonState { get { return (ButtonState)GetValue(MetroButtonStateProperty); } set { SetValue(MetroButtonStateProperty, value); } }
+
+        public MetroButton()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroButton()
+        {
+            ElementBase.DefaultStyle<MetroButton>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 75 - 0
Arthas-WPFUI/Arthas/Controls/MetroButton.xaml

@@ -0,0 +1,75 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroButton}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="Foreground" Value="#FFFFFFFF" />
+        <Setter Property="Background" Value="{StaticResource Brush}" />
+        <Setter Property="MinWidth" Value="100" />
+        <Setter Property="MinHeight" Value="40" />
+        <Setter Property="FontSize" Value="14" />
+        <Setter Property="Padding" Value="8,6" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroButton}">
+                    <Grid Background="#00000000">
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="move" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="move" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.2" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="move" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.03" />
+                                        <DoubleAnimation Storyboard.TargetName="back" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.7" Duration="0:0:0.03" />
+                                        <ThicknessAnimation Storyboard.TargetName="back" Storyboard.TargetProperty="(Margin)" To="0,2,0,0" Duration="0:0:0.03" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Disabled" />
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Border x:Name="border" CornerRadius="3" Background="{TemplateBinding Background}">
+                            <Grid>
+                                <Border CornerRadius="3" Background="#000000" Opacity="0.2" />
+                                <Border x:Name="back" CornerRadius="3" Background="{TemplateBinding Background}" Margin="0,0,0,3">
+                                    <Grid>
+                                        <Border x:Name="move" Background="#FFFFFFFF" CornerRadius="3" Opacity="0" />
+                                        <ContentPresenter Margin="{TemplateBinding Padding}" HorizontalAlignment="Center" VerticalAlignment="Center" />
+                                    </Grid>
+                                </Border>
+                            </Grid>
+                        </Border>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsEnabled" Value="false">
+                            <Setter Property="Opacity" Value="0.5" />
+                            <Setter TargetName="border" Property="Opacity" Value="0.5" />
+                            <Setter TargetName="back" Property="Margin" Value="0" />
+                        </Trigger>
+                        <Trigger Property="MetroButtonState" Value="Green">
+                            <Setter TargetName="border" Property="Background" Value="#99cb8a" />
+                            <Setter TargetName="back" Property="Background" Value="#99cb8a" />
+                        </Trigger>
+                        <Trigger Property="MetroButtonState" Value="Red">
+                            <Setter TargetName="border" Property="Background" Value="#e99595" />
+                            <Setter TargetName="back" Property="Background" Value="#e99595" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 31 - 0
Arthas-WPFUI/Arthas/Controls/MetroCanvasGrid.cs

@@ -0,0 +1,31 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroCanvasGrid : ContentControl
+    {
+        public static readonly DependencyProperty ViewportProperty = ElementBase.Property<MetroCanvasGrid, Rect>(nameof(ViewportProperty));
+        public Rect Viewport { get { return (Rect)GetValue(ViewportProperty); } set { SetValue(ViewportProperty, value); } }
+
+        public static readonly DependencyProperty GridOpacityProperty = ElementBase.Property<MetroCanvasGrid, double>(nameof(GridOpacityProperty));
+        public static readonly DependencyProperty GridSizeProperty = ElementBase.Property<MetroCanvasGrid, double>(nameof(GridSizeProperty));
+        public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property<MetroCanvasGrid, CornerRadius>(nameof(CornerRadiusProperty));
+
+        public double GridOpacity { get { return (double)GetValue(GridOpacityProperty); } set { SetValue(GridOpacityProperty, value); } }
+        public CornerRadius CornerRadius { get { return (CornerRadius)GetValue(CornerRadiusProperty); } set { SetValue(CornerRadiusProperty, value); } }
+
+        public bool IsApplyTheme { get; set; } = true;
+
+        public MetroCanvasGrid()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroCanvasGrid()
+        {
+            ElementBase.DefaultStyle<MetroCanvasGrid>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 51 - 0
Arthas-WPFUI/Arthas/Controls/MetroCanvasGrid.xaml

@@ -0,0 +1,51 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroCanvasGrid}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="Background" Value="{StaticResource Brush}" />
+        <Setter Property="GridOpacity" Value="0.2" />
+        <Setter Property="Viewport" Value="0 0 10 10" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroCanvasGrid}">
+                    <Grid>
+                        <Border CornerRadius="{TemplateBinding CornerRadius}">
+                            <Border.Background>
+                                <VisualBrush Viewport="{Binding Viewport, RelativeSource={RelativeSource TemplatedParent}}" TileMode="Tile" ViewportUnits="Absolute" Opacity="{Binding GridOpacity, RelativeSource={RelativeSource TemplatedParent}}">
+                                    <VisualBrush.Visual>
+                                        <Grid Width="1" Height="1">
+                                            <Grid.ColumnDefinitions>
+                                                <ColumnDefinition />
+                                                <ColumnDefinition />
+                                            </Grid.ColumnDefinitions>
+                                            <Grid.RowDefinitions>
+                                                <RowDefinition />
+                                                <RowDefinition />
+                                            </Grid.RowDefinitions>
+                                            <Rectangle Grid.Column="0" Grid.Row="0" Fill="{TemplateBinding Background}" />
+                                            <Rectangle Grid.Column="1" Grid.Row="0" />
+                                            <Rectangle Grid.Column="0" Grid.Row="1" />
+                                            <Rectangle Grid.Column="1" Grid.Row="1" Fill="{TemplateBinding Background}" />
+                                        </Grid>
+                                    </VisualBrush.Visual>
+                                </VisualBrush>
+                            </Border.Background>
+                        </Border>
+                        <ContentPresenter />
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsEnabled" Value="False">
+                            <Setter Property="Opacity" Value="0.5" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 240 - 0
Arthas-WPFUI/Arthas/Controls/MetroColorPicker.xaml

@@ -0,0 +1,240 @@
+<UserControl x:Class="Arthas.Controls.MetroColorPicker"
+             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"
+             xmlns:local="clr-namespace:Arthas.Controls"
+             mc:Ignorable="d" Style="{DynamicResource UserControlStyle}" x:Name="root" FontSize="12">
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+            </ResourceDictionary.MergedDictionaries>
+            <Style x:Key="UserControlStyle" TargetType="{x:Type UserControl}">
+                <Setter Property="BorderBrush" Value="{StaticResource Brush}" />
+                <Setter Property="SnapsToDevicePixels" Value="True" />
+                <Setter Property="Template">
+                    <Setter.Value>
+                        <ControlTemplate TargetType="{x:Type UserControl}">
+                            <Grid Background="#00000000" Margin="{TemplateBinding Padding}">
+                                <ContentPresenter />
+                            </Grid>
+                        </ControlTemplate>
+                    </Setter.Value>
+                </Setter>
+            </Style>
+        </ResourceDictionary>
+    </UserControl.Resources>
+    <Grid>
+        <local:MetroCanvasGrid />
+        <local:MetroFocusButton x:Name="button" Background="{Binding Background,ElementName=root}" />
+        <Popup x:Name="popup" PlacementTarget="{Binding ElementName=root}" AllowsTransparency="True" HorizontalOffset="-20" Focusable="False" VerticalOffset="-10" PopupAnimation="Fade" StaysOpen="False" Placement="Bottom">
+            <Grid Background="#00000000">
+                <Border Grid.Row="1" Background="{Binding ElementName=root,Path=BorderBrush}" BorderBrush="#99FFFFFF" BorderThickness="1" CornerRadius="3" Margin="20">
+                    <Border.Effect>
+                        <DropShadowEffect BlurRadius="20" Direction="0" Opacity="0.2" ShadowDepth="0" />
+                    </Border.Effect>
+                    <Grid>
+                        <Polygon x:Name="polygon" HorizontalAlignment="Left" Fill="{Binding ElementName=root,Path=BorderBrush}" Points="0,5 5,0 10,5 0,5" Margin="13,-5,0,0" />
+                        <Grid Margin="10">
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="Auto" />
+                                <ColumnDefinition Width="Auto" />
+                                <ColumnDefinition Width="Auto" />
+                                <ColumnDefinition Width="Auto" />
+                            </Grid.ColumnDefinitions>
+                            <Border Grid.Column="0" Margin="0,0,5,0" Width="214" Height="214" Background="#FFFFFF" CornerRadius="2">
+                                <local:MetroCanvasGrid IsApplyTheme="False" CornerRadius="2">
+                                    <Grid>
+                                        <Rectangle x:Name="viewSelectColor" RadiusX="2" RadiusY="2" />
+                                        <Rectangle x:Name="viewSelectColor1" RadiusX="2" RadiusY="2">
+                                            <Rectangle.Fill>
+                                                <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
+                                                    <GradientStop Offset="0" Color="#FFFFFFFF" />
+                                                    <GradientStop Offset="1" Color="#00FFFFFF" />
+                                                </LinearGradientBrush>
+                                            </Rectangle.Fill>
+                                        </Rectangle>
+                                        <Rectangle x:Name="viewSelectColor2" RadiusX="2" RadiusY="2">
+                                            <Rectangle.Fill>
+                                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
+                                                    <GradientStop Offset="0" Color="#00000000" />
+                                                    <GradientStop Offset="1" Color="#FF000000" />
+                                                </LinearGradientBrush>
+                                            </Rectangle.Fill>
+                                        </Rectangle>
+                                        <local:MetroThumb x:Name="thumbSB" OffsetX="-7" OffsetY="-7">
+                                            <Thumb.Resources>
+                                                <Style TargetType="{x:Type local:MetroThumb}">
+                                                    <Setter Property="BorderBrush" Value="#FF000000" />
+                                                    <Setter Property="Template">
+                                                        <Setter.Value>
+                                                            <ControlTemplate TargetType="{x:Type local:MetroThumb}">
+                                                                <Canvas Background="#00000000">
+                                                                    <Grid Width="14" Height="14" Canvas.Left="{TemplateBinding X}" Canvas.Top="{TemplateBinding Y}">
+                                                                        <Border BorderThickness="1" BorderBrush="{TemplateBinding Background}" CornerRadius="100" />
+                                                                        <Border BorderThickness="1" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="100" Margin="1" />
+                                                                    </Grid>
+                                                                </Canvas>
+                                                            </ControlTemplate>
+                                                        </Setter.Value>
+                                                    </Setter>
+                                                </Style>
+                                            </Thumb.Resources>
+                                        </local:MetroThumb>
+                                    </Grid>
+                                </local:MetroCanvasGrid>
+                            </Border>
+                            <Border Grid.Column="1" Margin="5,0,5,0" CornerRadius="2">
+                                <Grid>
+                                    <Border Margin="10,0" Width="24" Background="#FFFFFF" CornerRadius="2">
+                                        <local:MetroCanvasGrid IsApplyTheme="False" CornerRadius="2">
+                                            <Grid>
+                                                <Rectangle RadiusX="2" RadiusY="2">
+                                                    <Rectangle.Fill>
+                                                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
+                                                            <GradientStop x:Name="viewLine1" Color="Red" Offset="0" />
+                                                            <GradientStop x:Name="viewLine2" Color="Yellow" Offset="0.1667" />
+                                                            <GradientStop x:Name="viewLine3" Color="Lime" Offset="0.3334" />
+                                                            <GradientStop x:Name="viewLine4" Color="Cyan" Offset="0.5001" />
+                                                            <GradientStop x:Name="viewLine5" Color="Blue" Offset="0.6668" />
+                                                            <GradientStop x:Name="viewLine6" Color="Magenta" Offset="0.8335" />
+                                                            <GradientStop x:Name="viewLine7" Color="Red" Offset="1" />
+                                                        </LinearGradientBrush>
+                                                    </Rectangle.Fill>
+                                                </Rectangle>
+                                            </Grid>
+                                        </local:MetroCanvasGrid>
+                                    </Border>
+                                    <local:MetroThumb x:Name="thumbH" OffsetX="-20" OffsetY="-5">
+                                        <Thumb.Resources>
+                                            <Style TargetType="{x:Type local:MetroThumb}">
+                                                <Setter Property="SnapsToDevicePixels" Value="False" />
+                                                <Setter Property="Background" Value="#FFDEDEDE" />
+                                                <Setter Property="BorderBrush" Value="#99000000" />
+                                                <Setter Property="Template">
+                                                    <Setter.Value>
+                                                        <ControlTemplate TargetType="{x:Type local:MetroThumb}">
+                                                            <Canvas Background="#00000000">
+                                                                <Grid Canvas.Left="0" Canvas.Top="{TemplateBinding Y}">
+                                                                    <Grid.ColumnDefinitions>
+                                                                        <ColumnDefinition Width="10" />
+                                                                        <ColumnDefinition Width="24" />
+                                                                        <ColumnDefinition Width="10" />
+                                                                    </Grid.ColumnDefinitions>
+                                                                    <Grid.RowDefinitions>
+                                                                        <RowDefinition Height="8" />
+                                                                    </Grid.RowDefinitions>
+                                                                    <Grid Grid.Column="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ClipToBounds="True">
+                                                                        <Polygon Points="0,0 6,0 10,4 6,8 0,8" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}" StrokeThickness="1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
+                                                                    </Grid>
+                                                                    <Grid Grid.Column="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ClipToBounds="True">
+                                                                        <Polygon Points="0,4 4,0 10,0 10,8 4,8" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}" StrokeThickness="1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
+                                                                    </Grid>
+                                                                </Grid>
+                                                            </Canvas>
+                                                        </ControlTemplate>
+                                                    </Setter.Value>
+                                                </Setter>
+                                            </Style>
+                                        </Thumb.Resources>
+                                    </local:MetroThumb>
+                                </Grid>
+                            </Border>
+                            <Border x:Name="alpha1" Grid.Column="2" Margin="5,0,5,0" CornerRadius="2">
+                                <Grid>
+                                    <Border Margin="10,0" Width="24" Background="#FFFFFF" CornerRadius="2">
+                                        <local:MetroCanvasGrid IsApplyTheme="False" CornerRadius="2">
+                                            <Grid>
+                                                <Rectangle RadiusX="2" RadiusY="2">
+                                                    <Rectangle.Fill>
+                                                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
+                                                            <GradientStop x:Name="viewAlpha" Color="#FFFFFF" Offset="0" />
+                                                            <GradientStop Color="#00FFFFFF" Offset="1" />
+                                                        </LinearGradientBrush>
+                                                    </Rectangle.Fill>
+                                                </Rectangle>
+                                            </Grid>
+                                        </local:MetroCanvasGrid>
+                                    </Border>
+                                    <local:MetroThumb x:Name="thumbA" OffsetX="-20" OffsetY="-5">
+                                        <Thumb.Resources>
+                                            <Style TargetType="{x:Type local:MetroThumb}">
+                                                <Setter Property="SnapsToDevicePixels" Value="False" />
+                                                <Setter Property="Background" Value="#FFDEDEDE" />
+                                                <Setter Property="BorderBrush" Value="#99000000" />
+                                                <Setter Property="Template">
+                                                    <Setter.Value>
+                                                        <ControlTemplate TargetType="{x:Type local:MetroThumb}">
+                                                            <Canvas Background="#00000000">
+                                                                <Grid Canvas.Left="0" Canvas.Top="{TemplateBinding Y}">
+                                                                    <Grid.ColumnDefinitions>
+                                                                        <ColumnDefinition Width="10" />
+                                                                        <ColumnDefinition Width="24" />
+                                                                        <ColumnDefinition Width="10" />
+                                                                    </Grid.ColumnDefinitions>
+                                                                    <Grid.RowDefinitions>
+                                                                        <RowDefinition Height="8" />
+                                                                    </Grid.RowDefinitions>
+                                                                    <Grid Grid.Column="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ClipToBounds="True">
+                                                                        <Polygon Points="0,0 6,0 10,4 6,8 0,8" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}" StrokeThickness="1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
+                                                                    </Grid>
+                                                                    <Grid Grid.Column="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ClipToBounds="True">
+                                                                        <Polygon Points="0,4 4,0 10,0 10,8 4,8" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}" StrokeThickness="1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
+                                                                    </Grid>
+                                                                </Grid>
+                                                            </Canvas>
+                                                        </ControlTemplate>
+                                                    </Setter.Value>
+                                                </Setter>
+                                            </Style>
+                                        </Thumb.Resources>
+                                    </local:MetroThumb>
+                                </Grid>
+                            </Border>
+                            <Grid Grid.Column="3" Margin="5,0,0,0">
+                                <Grid.ColumnDefinitions>
+                                    <ColumnDefinition Width="82" />
+                                    <ColumnDefinition Width="82" />
+                                </Grid.ColumnDefinitions>
+                                <Grid.RowDefinitions>
+                                    <RowDefinition />
+                                    <RowDefinition />
+                                    <RowDefinition />
+                                    <RowDefinition />
+                                    <RowDefinition />
+                                    <RowDefinition />
+                                </Grid.RowDefinitions>
+                                <Grid Grid.ColumnSpan="2">
+                                    <Grid.ColumnDefinitions>
+                                        <ColumnDefinition Width="30" />
+                                        <ColumnDefinition Width="10" />
+                                        <ColumnDefinition />
+                                    </Grid.ColumnDefinitions>
+                                    <local:MetroTextBlock x:Name="drfault" Text="默认" Foreground="#ffffff" HorizontalAlignment="Right" VerticalAlignment="Center" />
+                                    <Border Grid.Column="2" Background="White" CornerRadius="2" BorderThickness="1">
+                                        <local:MetroCanvasGrid IsApplyTheme="False" CornerRadius="2">
+                                            <local:MetroFocusButton x:Name="viewDefColor" CornerRadius="2" BorderThickness="0" MouseMoveBorderThickness="0" />
+                                        </local:MetroCanvasGrid>
+                                    </Border>
+                                    <Border Grid.Column="2" CornerRadius="2" BorderThickness="1" BorderBrush="White" Opacity="0.2" />
+                                </Grid>
+                                <local:MetroTextBox x:Name="rgbaR" Grid.Column="0" Grid.Row="1" Title="R" TitleMinWidth="30" BorderThickness="0" CornerRadius="2" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+                                <local:MetroTextBox x:Name="rgbaG" Grid.Column="0" Grid.Row="2" Title="G" TitleMinWidth="30" BorderThickness="0" CornerRadius="2" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+                                <local:MetroTextBox x:Name="rgbaB" Grid.Column="0" Grid.Row="3" Title="B" TitleMinWidth="30" BorderThickness="0" CornerRadius="2" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+                                <local:MetroTextBox x:Name="rgbaA" Grid.Column="0" Grid.Row="4" Title="A" TitleMinWidth="30" BorderThickness="0" CornerRadius="2" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+
+                                <local:MetroTextBox x:Name="hsbaH" Grid.Column="1" Grid.Row="1" Title="H" TitleMinWidth="30" BorderThickness="0" CornerRadius="2" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+                                <local:MetroTextBox x:Name="hsbaS" Grid.Column="1" Grid.Row="2" Title="S" TitleMinWidth="30" BorderThickness="0" CornerRadius="2" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+                                <local:MetroTextBox x:Name="hsbaB" Grid.Column="1" Grid.Row="3" Title="B" TitleMinWidth="30" BorderThickness="0" CornerRadius="2" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+                                <local:MetroTextBox x:Name="hsbaA" Grid.Column="1" Grid.Row="4" Title="O" TitleMinWidth="30" BorderThickness="0" CornerRadius="2" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+
+                                <local:MetroTextBox x:Name="hex" Grid.ColumnSpan="2" Grid.Row="5" Title="Hex" ButtonTitle="复制" TitleMinWidth="30" BorderThickness="0" CornerRadius="3" TitleForeground="#FFFFFF" Margin="0,8,0,0" MaxLength="9" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
+                            </Grid>
+                        </Grid>
+                    </Grid>
+                </Border>
+            </Grid>
+        </Popup>
+    </Grid>
+</UserControl>

+ 233 - 0
Arthas-WPFUI/Arthas/Controls/MetroColorPicker.xaml.cs

@@ -0,0 +1,233 @@
+using Arthas.Utility.Media;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public partial class MetroColorPicker : UserControl
+    {
+        public event EventHandler ColorChange;
+
+        public Brush DefaultColor { get { return defaultColor.SolidColorBrush; } set { defaultColor = new HsbaColor(value); } }
+        public RgbaColor CurrentColor { get { return currentColor.RgbaColor; } }
+
+        private HsbaColor currentColor { get; set; }
+        private RgbaColor currentRgbaColor { get; set; }
+        private HsbaColor defaultColor { get; set; } = new HsbaColor(0.0, 0.0, 0.0, 1.0);
+        private HsbaColor selectColor { get; set; } = new HsbaColor(0, 1.0, 1.0, 1.0);
+
+        public double ButtonBorderThickness
+        {
+            get { return button.BorderThickness; }
+            set { button.BorderThickness = button.MouseMoveBorderThickness = value; }
+        }
+
+        public Brush ButtonBorderBrush
+        {
+            get { return button.BorderBrush; }
+            set { button.BorderBrush = button.MouseMoveBorderBrush = value; }
+        }
+
+        private bool canTransparent = true;
+
+        public bool CanTransparent
+        {
+            get { return canTransparent; }
+            set
+            {
+                canTransparent = value;
+                alpha1.IsEnabled = rgbaA.IsEnabled = hsbaA.IsEnabled = value;
+                if (!value)
+                {
+                    rgbaA.Text = "255";
+                    hex.MaxLength = 7;
+                }
+                else
+                {
+                    hex.MaxLength = 9;
+                }
+            }
+        }
+
+        public MetroColorPicker()
+        {
+            InitializeComponent();
+            Loaded += delegate { Initialize(Background == null ? new HsbaColor(0.0, 1.0, 1.0, 1.0) : new HsbaColor(Background)); };
+        }
+
+        public MetroColorPicker(string hexColor)
+        {
+            InitializeComponent();
+            Loaded += delegate { Initialize(new HsbaColor(hexColor)); };
+        }
+
+        public MetroColorPicker(int r, int g, int b, int a)
+        {
+            InitializeComponent();
+            Loaded += delegate { Initialize(new HsbaColor(r, g, b, a)); };
+        }
+
+        public Action ColorPickerClosed { get; set; }
+
+        private void Initialize(HsbaColor hsbaColor)
+        {
+            // 绑定主题
+            Utility.Refresh(this);
+
+            // 设置当前初始颜色
+            currentColor = hsbaColor;
+            // defaultColor = currentColor;
+
+            // 界面初始化
+            viewDefColor.Background = defaultColor.SolidColorBrush;
+            viewLine1.Offset = 1.0 / 6.0 * 0.0;
+            viewLine2.Offset = 1.0 / 6.0 * 1.0;
+            viewLine3.Offset = 1.0 / 6.0 * 2.0;
+            viewLine4.Offset = 1.0 / 6.0 * 3.0;
+            viewLine5.Offset = 1.0 / 6.0 * 4.0;
+            viewLine6.Offset = 1.0 / 6.0 * 5.0;
+            viewLine7.Offset = 1.0 / 6.0 * 6.0;
+
+            // 按钮事件
+            bool start = true;
+            button.Click += delegate
+            {
+                polygon.Margin = new Thickness(ActualWidth / 2 - 5, -5.0, 0.0, 0.0);
+                popup.IsOpen = true;
+                if (start)
+                {
+                    ApplyColor(currentColor);
+                    start = false;
+                }
+            };
+            popup.Closed += delegate { if (ColorPickerClosed != null) ColorPickerClosed(); };
+            viewDefColor.Click += delegate { ApplyColor(new HsbaColor(viewDefColor.Background)); };
+            hex.ButtonClick += delegate { Clipboard.SetText(hex.Text); };
+
+            // 视图被改变事件
+            thumbSB.ValueChange += delegate { if (thumbSB.IsDragging) ViewChange(); };
+            thumbH.ValueChange += delegate { if (thumbH.IsDragging) ViewChange(); };
+            thumbA.ValueChange += delegate { if (thumbA.IsDragging) ViewChange(); };
+
+            // RGBA操作事件
+            rgbaR.TextChanged += delegate { if (rgbaR.IsSelectionActive) RgbaChange(); };
+            rgbaG.TextChanged += delegate { if (rgbaG.IsSelectionActive) RgbaChange(); };
+            rgbaB.TextChanged += delegate { if (rgbaB.IsSelectionActive) RgbaChange(); };
+            rgbaA.TextChanged += delegate { if (rgbaA.IsSelectionActive) RgbaChange(); };
+
+            // HSBA操作事件
+            hsbaH.TextChanged += delegate { if (hsbaH.IsSelectionActive) HsbaChange(); };
+            hsbaS.TextChanged += delegate { if (hsbaS.IsSelectionActive) HsbaChange(); };
+            hsbaB.TextChanged += delegate { if (hsbaB.IsSelectionActive) HsbaChange(); };
+            hsbaA.TextChanged += delegate { if (hsbaA.IsSelectionActive) HsbaChange(); };
+
+            // HEX操作事件
+            hex.TextChanged += delegate { if (hex.IsSelectionActive) HexChange(); };
+        }
+
+        private void ViewChange()
+        {
+            ApplyColor(new HsbaColor(360.0 * thumbH.YPercent, thumbSB.XPercent, Math.Abs(1 - thumbSB.YPercent), Math.Abs(1 - thumbA.YPercent)));
+        }
+
+        private void RgbaChange()
+        {
+            var doubleRgbaR = ConvertDouble(rgbaR.Text);
+            var doubleRgbaG = ConvertDouble(rgbaG.Text);
+            var doubleRgbaB = ConvertDouble(rgbaB.Text);
+            var doubleRgbaA = ConvertDouble(rgbaA.Text);
+            if (doubleRgbaR > 255) { rgbaR.Text = "255"; } else if (doubleRgbaR == -1) { rgbaR.Text = "0"; };
+            if (doubleRgbaG > 255) { rgbaG.Text = "255"; } else if (doubleRgbaG == -1) { rgbaG.Text = "0"; };
+            if (doubleRgbaB > 255) { rgbaB.Text = "255"; } else if (doubleRgbaB == -1) { rgbaB.Text = "0"; };
+            if (doubleRgbaA > 255) { rgbaA.Text = "255"; } else if (doubleRgbaA == -1) { rgbaA.Text = "0"; };
+
+            ApplyColor(new HsbaColor(ConvertInt(rgbaR.Text), ConvertInt(rgbaG.Text), ConvertInt(rgbaB.Text), ConvertInt(rgbaA.Text)));
+        }
+
+        private void HsbaChange()
+        {
+            var doubleHsbaH = ConvertDouble(hsbaH.Text);
+            var doubleHsbaS = ConvertDouble(hsbaS.Text);
+            var doubleHsbaB = ConvertDouble(hsbaB.Text);
+            var doubleHsbaA = ConvertDouble(hsbaA.Text);
+            if (doubleHsbaH > 100) { hsbaH.Text = "100"; } else if (doubleHsbaH == -1) { hsbaH.Text = "0"; };
+            if (doubleHsbaS > 100) { hsbaS.Text = "100"; } else if (doubleHsbaS == -1) { hsbaS.Text = "0"; };
+            if (doubleHsbaB > 100) { hsbaB.Text = "100"; } else if (doubleHsbaB == -1) { hsbaB.Text = "0"; };
+            if (doubleHsbaA > 100) { hsbaA.Text = "100"; } else if (doubleHsbaA == -1) { hsbaA.Text = "0"; };
+
+            ApplyColor(new HsbaColor(ConvertDouble(hsbaH.Text) * 3.6, ConvertDouble(hsbaS.Text) / 100.0, ConvertDouble(hsbaB.Text) / 100.0, ConvertDouble(hsbaA.Text) / 100.0));
+        }
+
+        private void HexChange()
+        {
+            ApplyColor(new HsbaColor(hex.Text));
+        }
+
+        private void ApplyColor(HsbaColor hsba)
+        {
+            currentColor = hsba;
+            currentRgbaColor = currentColor.RgbaColor;
+
+            if (!rgbaR.IsSelectionActive) { rgbaR.Text = currentRgbaColor.R.ToString(); }
+            if (!rgbaG.IsSelectionActive) { rgbaG.Text = currentRgbaColor.G.ToString(); }
+            if (!rgbaB.IsSelectionActive) { rgbaB.Text = currentRgbaColor.B.ToString(); }
+            if (!rgbaA.IsSelectionActive) { rgbaA.Text = currentRgbaColor.A.ToString(); }
+
+            if (!hsbaH.IsSelectionActive) { hsbaH.Text = ((int)(currentColor.H / 3.6)).ToString(); }
+            if (!hsbaS.IsSelectionActive) { hsbaS.Text = ((int)(currentColor.S * 100)).ToString(); }
+            if (!hsbaB.IsSelectionActive) { hsbaB.Text = ((int)(currentColor.B * 100)).ToString(); }
+            if (!hsbaA.IsSelectionActive) { hsbaA.Text = ((int)(currentColor.A * 100)).ToString(); }
+
+            if (!hex.IsSelectionActive) { if (canTransparent) { hex.Text = currentColor.HexString; } else { hex.Text = string.Format("#{0:X2}{1:X2}{2:X2}", currentRgbaColor.R, currentRgbaColor.G, currentRgbaColor.B); } }
+
+            if (!thumbH.IsDragging) { thumbH.YPercent = currentColor.H / 360.0; }
+            if (!thumbSB.IsDragging) { thumbSB.XPercent = currentColor.S; thumbSB.YPercent = 1 - currentColor.B; }
+            if (!thumbA.IsDragging) { thumbA.YPercent = Math.Abs(1 - currentColor.A); }
+
+            selectColor.H = currentColor.H;
+            selectColor.A = currentColor.A;
+            viewSelectColor.Fill = selectColor.OpaqueSolidColorBrush;
+            if (canTransparent)
+            {
+                viewSelectColor.Opacity = viewSelectColor1.Opacity = viewSelectColor2.Opacity = 1 - thumbA.YPercent;
+            }
+            viewAlpha.Color = selectColor.OpaqueColor;
+            if (canTransparent)
+            {
+                Background = currentColor.SolidColorBrush;
+            }
+            else
+            {
+                Background = currentColor.OpaqueSolidColorBrush;
+            }
+
+            ColorChange?.Invoke(this, null);
+        }
+
+        private double ConvertDouble(string text)
+        {
+            try
+            {
+                return Convert.ToDouble(text);
+            }
+            catch
+            {
+                return -1;
+            }
+        }
+
+        private int ConvertInt(string text)
+        {
+            try
+            {
+                return Convert.ToInt32(text);
+            }
+            catch
+            {
+                return -1;
+            }
+        }
+    }
+}

+ 26 - 0
Arthas-WPFUI/Arthas/Controls/MetroComboBox.cs

@@ -0,0 +1,26 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroComboBox : ComboBox
+    {
+        public static readonly DependencyProperty TitleProperty = ElementBase.Property<MetroComboBox, string>(nameof(TitleProperty), "");
+        public static readonly DependencyProperty IconProperty = ElementBase.Property<MetroComboBox, ImageSource>(nameof(IconProperty), null);
+
+        public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } }
+        public ImageSource Icon { get { return (ImageSource)GetValue(IconProperty); } set { SetValue(IconProperty, value); } }
+
+        public MetroComboBox()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroComboBox()
+        {
+            ElementBase.DefaultStyle<MetroComboBox>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 37 - 0
Arthas-WPFUI/Arthas/Controls/MetroComboBox.xaml

@@ -0,0 +1,37 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroComboBox}">
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroComboBox}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="*" />
+                            <ColumnDefinition Width="0" />
+                        </Grid.ColumnDefinitions>
+                        <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
+                            <Border x:Name="dropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
+                                <ScrollViewer x:Name="DropDownScrollViewer">
+                                    <Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
+                                        <Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
+                                            <Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}" />
+                                        </Canvas>
+                                        <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
+                                    </Grid>
+                                </ScrollViewer>
+                            </Border>
+                        </Popup>
+                        <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 18 - 0
Arthas-WPFUI/Arthas/Controls/MetroComboBoxItem.cs

@@ -0,0 +1,18 @@
+using Arthas.Utility.Element;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroComboBoxItem : ComboBoxItem
+    {
+        public MetroComboBoxItem()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroComboBoxItem()
+        {
+            ElementBase.DefaultStyle<MetroComboBoxItem>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 7 - 0
Arthas-WPFUI/Arthas/Controls/MetroComboBoxItem.xaml

@@ -0,0 +1,7 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+</ResourceDictionary>

+ 18 - 0
Arthas-WPFUI/Arthas/Controls/MetroContextMenu.cs

@@ -0,0 +1,18 @@
+using Arthas.Utility.Element;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroContextMenu : ContextMenu
+    {
+        public MetroContextMenu()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroContextMenu()
+        {
+            ElementBase.DefaultStyle<MetroContextMenu>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 30 - 0
Arthas-WPFUI/Arthas/Controls/MetroContextMenu.xaml

@@ -0,0 +1,30 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroContextMenu}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="VerticalOffset" Value="-20" />
+        <Setter Property="HorizontalOffset" Value="-20" />
+        <Setter Property="Background" Value="{StaticResource Brush}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroContextMenu}">
+                    <Grid Background="#00000000">
+                        <Border BorderBrush="#99FFFFFF" BorderThickness="1" Background="{TemplateBinding Background}" CornerRadius="3" Margin="20">
+                            <Border.Effect>
+                                <DropShadowEffect BlurRadius="20" Direction="0" Opacity="0.2" ShadowDepth="0" />
+                            </Border.Effect>
+                            <ItemsPresenter />
+                        </Border>
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 94 - 0
Arthas-WPFUI/Arthas/Controls/MetroExpander.cs

@@ -0,0 +1,94 @@
+using Arthas.Utility.Element;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroExpander : ContentControl
+    {
+        public static readonly DependencyProperty IsExpandedProperty = ElementBase.Property<MetroExpander, bool>(nameof(IsExpandedProperty));
+        public static readonly DependencyProperty CanHideProperty = ElementBase.Property<MetroExpander, bool>(nameof(CanHideProperty));
+        public static readonly DependencyProperty HeaderProperty = ElementBase.Property<MetroExpander, string>(nameof(HeaderProperty));
+        public static readonly DependencyProperty HintProperty = ElementBase.Property<MetroExpander, string>(nameof(HintProperty));
+        public static readonly DependencyProperty HintBackgroundProperty = ElementBase.Property<MetroExpander, Brush>(nameof(HintBackgroundProperty));
+        public static readonly DependencyProperty HintForegroundProperty = ElementBase.Property<MetroExpander, Brush>(nameof(HintForegroundProperty));
+        public static readonly DependencyProperty IconProperty = ElementBase.Property<MetroExpander, ImageSource>(nameof(IconProperty), null);
+
+        public static RoutedUICommand ButtonClickCommand = ElementBase.Command<MetroExpander>(nameof(ButtonClickCommand));
+
+        public bool IsExpanded { get { return (bool)GetValue(IsExpandedProperty); } set { SetValue(IsExpandedProperty, value); ElementBase.GoToState(this, IsExpanded ? "Expand" : "Normal"); } }
+        public bool CanHide { get { return (bool)GetValue(CanHideProperty); } set { SetValue(CanHideProperty, value); } }
+        public string Header { get { return (string)GetValue(HeaderProperty); } set { SetValue(HeaderProperty, value); } }
+        public string Hint { get { return (string)GetValue(HintProperty); } set { SetValue(HintProperty, value); } }
+        public Brush HintBackground { get { return (Brush)GetValue(HintBackgroundProperty); } set { SetValue(HintBackgroundProperty, value); } }
+        public Brush HintForeground { get { return (Brush)GetValue(HintForegroundProperty); } set { SetValue(HintForegroundProperty, value); } }
+        public ImageSource Icon { get { return (ImageSource)GetValue(IconProperty); } set { SetValue(IconProperty, value); } }
+
+        public event EventHandler Click;
+
+        public MetroExpander()
+        {
+            Utility.Refresh(this);
+
+            Loaded += delegate
+            {
+                if (Content == null)
+                {
+                    IsExpanded = false;
+                }
+                else if (!CanHide)
+                {
+                    IsExpanded = true;
+                }
+                ElementBase.GoToState(this, IsExpanded ? "StartExpand" : "StartNormal");
+            };
+
+            CommandBindings.Add(new CommandBinding(ButtonClickCommand, delegate
+            {
+                if (CanHide && Content != null)
+                {
+                    IsExpanded = !IsExpanded;
+                }
+                if (Click != null) { Click(this, null); }
+            }));
+        }
+
+        public void Clear()
+        {
+            Content = new StackPanel();
+        }
+
+        public UIElementCollection Children
+        {
+            get
+            {
+                if ((Content is StackPanel))
+                {
+                    return (Content as StackPanel).Children;
+                }
+                else if ((Content is Grid))
+                {
+                    return (Content as Grid).Children;
+                }
+                return null;
+            }
+        }
+
+        public void Add(FrameworkElement element)
+        {
+            if (!(Content is StackPanel))
+            {
+                Content = new StackPanel();
+            }
+            (Content as StackPanel).Children.Add(element);
+        }
+
+        static MetroExpander()
+        {
+            ElementBase.DefaultStyle<MetroExpander>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 146 - 0
Arthas-WPFUI/Arthas/Controls/MetroExpander.xaml

@@ -0,0 +1,146 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroExpander}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="MinWidth" Value="180" />
+        <Setter Property="CanHide" Value="True" />
+        <Setter Property="IsExpanded" Value="False" />
+        <Setter Property="Hint" Value="{x:Null}" />
+        <Setter Property="HintBackground" Value="#7F000000" />
+        <Setter Property="HintForeground" Value="#FFFFFF" />
+
+        <Style.Triggers>
+            <Trigger Property="CanHide" Value="True">
+                <Setter Property="Template">
+                    <Setter.Value>
+                        <ControlTemplate TargetType="{x:Type Metro:MetroExpander}">
+                            <Grid Background="#7FFFFFFF">
+                                <VisualStateManager.VisualStateGroups>
+                                    <VisualStateGroup>
+                                        <VisualState x:Name="Normal">
+                                            <Storyboard>
+                                                <DoubleAnimation Storyboard.TargetName="height" Storyboard.TargetProperty="(Height)" To="0" Duration="0:0:0.15" />
+                                                <DoubleAnimation Storyboard.TargetName="angle" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0.15" />
+                                            </Storyboard>
+                                        </VisualState>
+                                        <VisualState x:Name="StartNormal">
+                                            <Storyboard>
+                                                <DoubleAnimation Storyboard.TargetName="height" Storyboard.TargetProperty="(Height)" To="0" Duration="0:0:0" />
+                                                <DoubleAnimation Storyboard.TargetName="angle" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0" />
+                                            </Storyboard>
+                                        </VisualState>
+                                        <VisualState x:Name="Expand">
+                                            <Storyboard>
+                                                <DoubleAnimation Storyboard.TargetName="height" Storyboard.TargetProperty="(Height)" To="{Binding ElementName=content,Path=ActualHeight}" Duration="0:0:0.15" />
+                                                <DoubleAnimation Storyboard.TargetName="angle" Storyboard.TargetProperty="(Angle)" To="90" Duration="0:0:0.15" />
+                                            </Storyboard>
+                                        </VisualState>
+                                        <VisualState x:Name="StartExpand">
+                                            <Storyboard>
+                                                <DoubleAnimation Storyboard.TargetName="height" Storyboard.TargetProperty="(Height)" To="{Binding ElementName=content,Path=ActualHeight}" Duration="0:0:0" />
+                                                <DoubleAnimation Storyboard.TargetName="angle" Storyboard.TargetProperty="(Angle)" To="90" Duration="0:0:0" />
+                                            </Storyboard>
+                                        </VisualState>
+                                    </VisualStateGroup>
+                                </VisualStateManager.VisualStateGroups>
+                                <Grid.RowDefinitions>
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                </Grid.RowDefinitions>
+                                <Border BorderBrush="#e6e6e6" BorderThickness="0,0,0,1">
+                                    <Grid>
+                                        <Grid.ColumnDefinitions>
+                                            <ColumnDefinition x:Name="iconWidth" Width="Auto" />
+                                            <ColumnDefinition />
+                                            <ColumnDefinition x:Name="hintWidth" Width="Auto" />
+                                            <ColumnDefinition x:Name="algleWidth" Width="Auto" />
+                                        </Grid.ColumnDefinitions>
+                                        <Image Width="12" Height="12" Margin="10,0,0,0" VerticalAlignment="Center" Source="{TemplateBinding Icon}" Opacity="0.7" />
+                                        <Metro:MetroTextBlock Grid.Column="1" Text="{TemplateBinding Header}" Margin="10,8,5,8" VerticalAlignment="Center" HorizontalAlignment="Left" Opacity="0.65" />
+                                        <Metro:MetroBorder    Grid.Column="2" AutoCornerRadius="True" Margin="0,0,5,0" VerticalAlignment="Center" Background="{TemplateBinding HintBackground}">
+                                            <Metro:MetroTextBlock VerticalAlignment="Center" Margin="8,1" Text="{TemplateBinding Hint}" Foreground="{TemplateBinding HintForeground}" />
+                                        </Metro:MetroBorder>
+                                        <Grid Grid.Column="3" Margin="10,0" VerticalAlignment="Center">
+                                            <Polyline Points="0,0 5,5 0,10" Stroke="#000000" RenderTransformOrigin="0.5,0.5" Opacity="0.65">
+                                                <Polyline.RenderTransform>
+                                                    <TransformGroup>
+                                                        <RotateTransform x:Name="angle" Angle="0" />
+                                                    </TransformGroup>
+                                                </Polyline.RenderTransform>
+                                            </Polyline>
+                                        </Grid>
+                                        <Metro:MetroFocusButton Grid.ColumnSpan="4" Foreground="#00000000" MouseMoveForeground="#0C000000" BorderThickness="0" MouseMoveBorderThickness="0" Command="Metro:MetroExpander.ButtonClickCommand" />
+                                    </Grid>
+                                </Border>
+                                <Grid x:Name="height" Grid.Row="1" Background="#00000000" Height="{Binding ActualHeight,ElementName=content}" ClipToBounds="True">
+                                    <Canvas x:Name="canvas" Height="{Binding ActualHeight,ElementName=content}" MinWidth="{Binding ActualWidth,ElementName=content}">
+                                        <Grid x:Name="content" ClipToBounds="True" MinWidth="{Binding ActualWidth,ElementName=canvas}">
+                                            <ContentPresenter />
+                                        </Grid>
+                                    </Canvas>
+                                </Grid>
+                            </Grid>
+                            <ControlTemplate.Triggers>
+                                <Trigger Property="Hint" Value="{x:Null}">
+                                    <Setter TargetName="hintWidth" Property="Width" Value="0" />
+                                </Trigger>
+                                <Trigger Property="Icon" Value="{x:Null}">
+                                    <Setter TargetName="iconWidth" Property="Width" Value="0" />
+                                </Trigger>
+                                <Trigger Property="Content" Value="{x:Null}">
+                                    <Setter TargetName="algleWidth" Property="MaxWidth" Value="0" />
+                                </Trigger>
+                            </ControlTemplate.Triggers>
+                        </ControlTemplate>
+                    </Setter.Value>
+                </Setter>
+            </Trigger>
+            <Trigger Property="CanHide" Value="False">
+                <Setter Property="Template">
+                    <Setter.Value>
+                        <ControlTemplate TargetType="{x:Type Metro:MetroExpander}">
+                            <Grid Background="#7FFFFFFF">
+                                <Grid.RowDefinitions>
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                </Grid.RowDefinitions>
+                                <Border BorderBrush="#e6e6e6" BorderThickness="0,0,0,1">
+                                    <Grid>
+                                        <Grid.ColumnDefinitions>
+                                            <ColumnDefinition x:Name="iconWidth" Width="Auto" />
+                                            <ColumnDefinition />
+                                            <ColumnDefinition x:Name="hintWidth" Width="Auto" />
+                                        </Grid.ColumnDefinitions>
+                                        <Image Width="12" Height="12" Margin="10,0,0,0" VerticalAlignment="Center" Source="{TemplateBinding Icon}" Opacity="0.7" />
+                                        <Metro:MetroTextBlock Grid.Column="1" Text="{TemplateBinding Header}" Margin="10,8,5,8" VerticalAlignment="Center" HorizontalAlignment="Left" Opacity="0.65" />
+                                        <Metro:MetroBorder    Grid.Column="2" AutoCornerRadius="True" Margin="0,0,5,0" VerticalAlignment="Center" Background="{TemplateBinding HintBackground}">
+                                            <Metro:MetroTextBlock VerticalAlignment="Center" Margin="8,1" Text="{TemplateBinding Hint}" Foreground="{TemplateBinding HintForeground}" />
+                                        </Metro:MetroBorder>
+                                    </Grid>
+                                </Border>
+                                <Border Grid.Row="1" Background="#7FFFFFFF" BorderBrush="#e6e6e6" BorderThickness="0,0,0,1">
+                                    <ContentPresenter />
+                                </Border>
+                            </Grid>
+                            <ControlTemplate.Triggers>
+                                <Trigger Property="Hint" Value="{x:Null}">
+                                    <Setter TargetName="hintWidth" Property="Width" Value="0" />
+                                </Trigger>
+                                <Trigger Property="Icon" Value="{x:Null}">
+                                    <Setter TargetName="iconWidth" Property="Width" Value="0" />
+                                </Trigger>
+                            </ControlTemplate.Triggers>
+                        </ControlTemplate>
+                    </Setter.Value>
+                </Setter>
+            </Trigger>
+        </Style.Triggers>
+    </Style>
+</ResourceDictionary>

+ 31 - 0
Arthas-WPFUI/Arthas/Controls/MetroFocusButton.cs

@@ -0,0 +1,31 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroFocusButton : Button
+    {
+        public static readonly DependencyProperty MouseMoveForegroundProperty = ElementBase.Property<MetroFocusButton, Brush>(nameof(MouseMoveForegroundProperty));
+        public static readonly DependencyProperty MouseMoveBorderBrushProperty = ElementBase.Property<MetroFocusButton, Brush>(nameof(MouseMoveBorderBrushProperty));
+        public static readonly new DependencyProperty BorderThicknessProperty = ElementBase.Property<MetroFocusButton, double>(nameof(BorderThicknessProperty));
+        public static readonly DependencyProperty MouseMoveBorderThicknessProperty = ElementBase.Property<MetroFocusButton, double>(nameof(MouseMoveBorderThicknessProperty));
+        public static readonly DependencyProperty StrokeDashArrayProperty = ElementBase.Property<MetroFocusButton, DoubleCollection>(nameof(StrokeDashArrayProperty));
+        public static readonly DependencyProperty MouseMoveStrokeDashArrayProperty = ElementBase.Property<MetroFocusButton, DoubleCollection>(nameof(MouseMoveStrokeDashArrayProperty));
+        public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property<MetroFocusButton, double>(nameof(CornerRadiusProperty));
+
+        public Brush MouseMoveForeground { get { return (Brush)GetValue(MouseMoveForegroundProperty); } set { SetValue(MouseMoveForegroundProperty, value); } }
+        public Brush MouseMoveBorderBrush { get { return (Brush)GetValue(MouseMoveBorderBrushProperty); } set { SetValue(MouseMoveBorderBrushProperty, value); } }
+        public new double BorderThickness { get { return (double)GetValue(BorderThicknessProperty); } set { SetValue(BorderThicknessProperty, value); } }
+        public double MouseMoveBorderThickness { get { return (double)GetValue(MouseMoveBorderThicknessProperty); } set { SetValue(MouseMoveBorderThicknessProperty, value); } }
+        public DoubleCollection StrokeDashArray { get { return (DoubleCollection)GetValue(StrokeDashArrayProperty); } set { SetValue(StrokeDashArrayProperty, value); } }
+        public DoubleCollection MouseMoveStrokeDashArray { get { return (DoubleCollection)GetValue(MouseMoveStrokeDashArrayProperty); } set { SetValue(MouseMoveStrokeDashArrayProperty, value); } }
+        public double CornerRadius { get { return (double)GetValue(CornerRadiusProperty); } set { SetValue(CornerRadiusProperty, value); } }
+
+        static MetroFocusButton()
+        {
+            ElementBase.DefaultStyle<MetroFocusButton>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 75 - 0
Arthas-WPFUI/Arthas/Controls/MetroFocusButton.xaml

@@ -0,0 +1,75 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Converter="clr-namespace:Arthas.Controls.Converter"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Converter:DoubleToThickness x:Key="DoubleToThickness" />
+    <Converter:DoubleToCornerRadius x:Key="DoubleToCornerRadius" />
+
+    <Style TargetType="{x:Type Metro:MetroFocusButton}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="Background" Value="#00000000" />
+        <Setter Property="Padding" Value="0" />
+
+        <Setter Property="Foreground" Value="#00ffffff" />
+        <Setter Property="MouseMoveForeground" Value="#4CFFFFFF" />
+
+        <Setter Property="BorderBrush" Value="#ffffff" />
+        <Setter Property="MouseMoveBorderBrush" Value="#ffffff" />
+
+        <Setter Property="BorderThickness" Value="1" />
+        <Setter Property="MouseMoveBorderThickness" Value="1" />
+
+        <Setter Property="StrokeDashArray" Value="1 0" />
+        <Setter Property="MouseMoveStrokeDashArray" Value="1 0" />
+
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroFocusButton}">
+                    <Grid Background="#00000000">
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="normal" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="mouse" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="mouse" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="normal" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="mouse" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="normal" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)" To="0.7" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Disabled" />
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Border Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding CornerRadius,Converter={StaticResource DoubleToCornerRadius}}" BorderThickness="{TemplateBinding BorderThickness,Converter={StaticResource DoubleToThickness}}" />
+                        <ContentPresenter />
+                        <Rectangle x:Name="normal" Fill="{TemplateBinding Foreground}" RadiusX="{TemplateBinding CornerRadius}" RadiusY="{TemplateBinding CornerRadius}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}" StrokeDashArray="{TemplateBinding StrokeDashArray}" Opacity="1" />
+                        <Rectangle x:Name="mouse" Fill="{TemplateBinding MouseMoveForeground}" RadiusX="{TemplateBinding CornerRadius}" RadiusY="{TemplateBinding CornerRadius}" Stroke="{TemplateBinding MouseMoveBorderBrush}" StrokeThickness="{TemplateBinding MouseMoveBorderThickness}" StrokeDashArray="{TemplateBinding MouseMoveStrokeDashArray}" Opacity="0" />
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsEnabled" Value="false">
+                            <Setter Property="Opacity" Value="0.5" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 13 - 0
Arthas-WPFUI/Arthas/Controls/MetroGroupBox.cs

@@ -0,0 +1,13 @@
+using Arthas.Utility.Element;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroGroupBox : GroupBox
+    {
+        static MetroGroupBox()
+        {
+            ElementBase.DefaultStyle<MetroGroupBox>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 31 - 0
Arthas-WPFUI/Arthas/Controls/MetroGroupBox.xaml

@@ -0,0 +1,31 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroGroupBox}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="Padding" Value="10" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroGroupBox}">
+                    <Grid>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="16" />
+                            <RowDefinition />
+                        </Grid.RowDefinitions>
+                        <Border Grid.RowSpan="2" Margin="0,8,0,0" BorderBrush="#FF000000" BorderThickness="1" CornerRadius="3" Opacity="0.1" />
+                        <Grid Margin="15,0,0,0" HorizontalAlignment="Left">
+                            <Rectangle Fill="#FFF3F3F3" Height="1" Margin="-5,0" />
+                            <Metro:MetroTextBlock Text="{TemplateBinding Header}" Opacity="0.65" />
+                        </Grid>
+                        <ContentPresenter Grid.Row="1" Margin="{TemplateBinding Padding}" />
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 40 - 0
Arthas-WPFUI/Arthas/Controls/MetroImage.cs

@@ -0,0 +1,40 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroImage : ContentControl
+    {
+        public static readonly DependencyProperty SourceProperty = ElementBase.Property<MetroImage, ImageSource>(nameof(SourceProperty));
+        public static readonly DependencyProperty StretchProperty = ElementBase.Property<MetroImage, Stretch>(nameof(StretchProperty));
+        public static readonly DependencyProperty StretchDirectionProperty = ElementBase.Property<MetroImage, StretchDirection>(nameof(StretchDirectionProperty));
+        public static readonly DependencyProperty ImageWidthProperty = ElementBase.Property<MetroImage, double>(nameof(ImageWidthProperty));
+        public static readonly DependencyProperty ImageHeightProperty = ElementBase.Property<MetroImage, double>(nameof(ImageHeightProperty));
+        public static readonly DependencyProperty ImageVerticalAlignmentProperty = ElementBase.Property<MetroImage, VerticalAlignment>(nameof(ImageVerticalAlignmentProperty));
+        public static readonly DependencyProperty ImageHorizontalAlignmentProperty = ElementBase.Property<MetroImage, HorizontalAlignment>(nameof(ImageHorizontalAlignmentProperty));
+
+        public ImageSource Source { get { return (ImageSource)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } }
+        public Stretch Stretch { get { return (Stretch)GetValue(StretchProperty); } set { SetValue(StretchProperty, value); } }
+        public StretchDirection StretchDirection { get { return (StretchDirection)GetValue(StretchDirectionProperty); } set { SetValue(StretchDirectionProperty, value); } }
+        public double ImageWidth { get { return (double)GetValue(ImageWidthProperty); } set { SetValue(ImageWidthProperty, value); } }
+        public double ImageHeight { get { return (double)GetValue(ImageHeightProperty); } set { SetValue(ImageHeightProperty, value); } }
+        public VerticalAlignment ImageVerticalAlignment { get { return (VerticalAlignment)GetValue(ImageVerticalAlignmentProperty); } set { SetValue(ImageVerticalAlignmentProperty, value); } }
+        public HorizontalAlignment ImageHorizontalAlignment { get { return (HorizontalAlignment)GetValue(ImageHorizontalAlignmentProperty); } set { SetValue(ImageHorizontalAlignmentProperty, value); } }
+
+        static MetroImage()
+        {
+            ElementBase.DefaultStyle<MetroImage>(DefaultStyleKeyProperty);
+        }
+
+        public MetroImage()
+        {
+        }
+
+        public MetroImage(ImageSource image)
+        {
+            Source = image;
+        }
+    }
+}

+ 27 - 0
Arthas-WPFUI/Arthas/Controls/MetroImage.xaml

@@ -0,0 +1,27 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroImage}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="Stretch" Value="Uniform" />
+        <Setter Property="StretchDirection" Value="DownOnly" />
+        <Setter Property="ImageWidth" Value="-1" />
+        <Setter Property="ImageHeight" Value="-1" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroImage}">
+                    <Grid Background="#00000000">
+                        <Viewbox Stretch="{TemplateBinding Stretch}" StretchDirection="{TemplateBinding StretchDirection}">
+                            <Image Source="{TemplateBinding Source}" MinWidth="{TemplateBinding ImageWidth}" MinHeight="{TemplateBinding ImageHeight}" MaxWidth="{TemplateBinding ImageWidth}" MaxHeight="{TemplateBinding ImageHeight}" VerticalAlignment="{TemplateBinding ImageVerticalAlignment}" HorizontalAlignment="{TemplateBinding ImageHorizontalAlignment}" Width="{Binding Source.PixelWidth, Mode=OneWay, RelativeSource={RelativeSource Self}}" Height="{Binding Source.PixelHeight, Mode=OneWay, RelativeSource={RelativeSource Self}}" />
+                        </Viewbox>
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 24 - 0
Arthas-WPFUI/Arthas/Controls/MetroMenuItem.cs

@@ -0,0 +1,24 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroMenuItem : MenuItem
+    {
+        public static readonly new DependencyProperty IconProperty = ElementBase.Property<MetroMenuItem, ImageSource>(nameof(IconProperty), null);
+
+        public new ImageSource Icon { get { return (ImageSource)GetValue(IconProperty); } set { SetValue(IconProperty, value); } }
+
+        public MetroMenuItem()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroMenuItem()
+        {
+            ElementBase.DefaultStyle<MetroMenuItem>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 73 - 0
Arthas-WPFUI/Arthas/Controls/MetroMenuItem.xaml

@@ -0,0 +1,73 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroMenuItem}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="MinWidth" Value="120" />
+        <Setter Property="Background" Value="{StaticResource Brush}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroMenuItem}">
+                    <Grid>
+                        <Grid Margin="3">
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="Auto" />
+                                <ColumnDefinition />
+                                <ColumnDefinition Width="0" x:Name="subWidth" />
+                            </Grid.ColumnDefinitions>
+                            <Rectangle x:Name="backRectangle" Grid.ColumnSpan="3" Fill="#ffffff" Opacity="0" RadiusX="2" RadiusY="2" />
+                            <Image     Grid.Column="0" x:Name="icon" Source="{TemplateBinding Icon}" Width="12" Height="12" Margin="5,3,0,3" />
+                            <Metro:MetroTextBlock x:Name="title" Grid.Column="1" Text="{TemplateBinding Header}" Foreground="#ffffff" Margin="8,3,10,3" />
+                            <Polyline Grid.Column="2" Points="0,0 5,5 0,10" Stroke="#ffffff" VerticalAlignment="Center" Margin="5,0,8,0" />
+                        </Grid>
+                        <Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" HorizontalOffset="-10" VerticalOffset="-20" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="Fade" Placement="Right">
+                            <Grid RenderOptions.ClearTypeHint="Enabled" Background="#00000000">
+                                <Border Grid.Row="1" BorderBrush="#99FFFFFF" BorderThickness="1" Background="{TemplateBinding Background}" CornerRadius="3" Margin="20">
+                                    <Border.Effect>
+                                        <DropShadowEffect BlurRadius="20" Direction="0" Opacity="0.2" ShadowDepth="0" />
+                                    </Border.Effect>
+                                    <Grid>
+                                        <Polyline Points="5,0 0,5 5,10" Fill="{TemplateBinding Background}" Margin="-5,10,0,0" />
+                                        <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="True" KeyboardNavigation.TabNavigation="Cycle" />
+                                    </Grid>
+                                </Border>
+                            </Grid>
+                        </Popup>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsEnabled" Value="False">
+                            <Setter TargetName="icon" Property="Opacity" Value="0.5" />
+                            <Setter TargetName="title" Property="Opacity" Value="0.5" />
+                        </Trigger>
+                        <Trigger Property="Role" Value="SubmenuHeader">
+                            <Setter TargetName="subWidth" Property="Width" Value="Auto" />
+                        </Trigger>
+                        <Trigger Property="IsMouseOver" Value="True">
+                            <Trigger.EnterActions>
+                                <BeginStoryboard>
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="backRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.15" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </BeginStoryboard>
+                            </Trigger.EnterActions>
+                            <Trigger.ExitActions>
+                                <BeginStoryboard>
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="backRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </BeginStoryboard>
+                            </Trigger.ExitActions>
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 13 - 0
Arthas-WPFUI/Arthas/Controls/MetroMenuSeparator.cs

@@ -0,0 +1,13 @@
+using Arthas.Utility.Element;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroMenuSeparator : Separator
+    {
+        static MetroMenuSeparator()
+        {
+            ElementBase.DefaultStyle<MetroMenuSeparator>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 17 - 0
Arthas-WPFUI/Arthas/Controls/MetroMenuSeparator.xaml

@@ -0,0 +1,17 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroMenuSeparator}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="Focusable" Value="false" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="Background" Value="#ffffff" />
+        <Setter Property="Opacity" Value="0.3" />
+        <Setter Property="Margin" Value="-30,2,0,2" />
+    </Style>
+</ResourceDictionary>

+ 53 - 0
Arthas-WPFUI/Arthas/Controls/MetroMenuTabControl.cs

@@ -0,0 +1,53 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace Arthas.Controls
+{
+    public class MetroMenuTabControl : TabControl
+    {
+        public static readonly DependencyProperty TabPanelVerticalAlignmentProperty = ElementBase.Property<MetroMenuTabControl, VerticalAlignment>(nameof(TabPanelVerticalAlignmentProperty), VerticalAlignment.Top);
+        public static readonly DependencyProperty OffsetProperty = ElementBase.Property<MetroMenuTabControl, Thickness>(nameof(OffsetProperty), new Thickness(0));
+        public static readonly DependencyProperty IconModeProperty = ElementBase.Property<MetroMenuTabControl, bool>(nameof(IconModeProperty), false);
+
+        public static RoutedUICommand IconModeClickCommand = ElementBase.Command<MetroMenuTabControl>(nameof(IconModeClickCommand));
+
+        public VerticalAlignment TabPanelVerticalAlignment { get { return (VerticalAlignment)GetValue(TabPanelVerticalAlignmentProperty); } set { SetValue(TabPanelVerticalAlignmentProperty, value); } }
+        public Thickness Offset { get { return (Thickness)GetValue(OffsetProperty); } set { SetValue(OffsetProperty, value); } }
+        public bool IconMode { get { return (bool)GetValue(IconModeProperty); } set { SetValue(IconModeProperty, value); GoToState(); } }
+
+        void GoToState()
+        {
+            ElementBase.GoToState(this, IconMode ? "EnterIconMode" : "ExitIconMode");
+        }
+
+        void SelectionState()
+        {
+            if (IconMode)
+            {
+                ElementBase.GoToState(this, "SelectionStartIconMode");
+                ElementBase.GoToState(this, "SelectionEndIconMode");
+            }
+            else
+            {
+                ElementBase.GoToState(this, "SelectionStart");
+                ElementBase.GoToState(this, "SelectionEnd");
+            }
+        }
+
+        public MetroMenuTabControl()
+        {
+            Loaded += delegate { GoToState(); ElementBase.GoToState(this, IconMode ? "SelectionLoadedIconMode" : "SelectionLoaded"); };
+            SelectionChanged += delegate (object sender, SelectionChangedEventArgs e) { if (e.Source is MetroMenuTabControl) { SelectionState(); } };
+            CommandBindings.Add(new CommandBinding(IconModeClickCommand, delegate { IconMode = !IconMode; GoToState(); }));
+
+            Utility.Refresh(this);
+        }
+
+        static MetroMenuTabControl()
+        {
+            ElementBase.DefaultStyle<MetroMenuTabControl>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 186 - 0
Arthas-WPFUI/Arthas/Controls/MetroMenuTabControl.xaml

@@ -0,0 +1,186 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroMenuTabControl}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="TabStripPlacement" Value="Left" />
+        <Setter Property="BorderBrush" Value="{StaticResource Brush}" />
+        <Setter Property="Padding" Value="0" />
+        <Setter Property="SelectedIndex" Value="0" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroMenuTabControl}">
+                    <Grid Background="#00000000" KeyboardNavigation.TabNavigation="Local">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition x:Name="column1" Width="Auto" />
+                            <ColumnDefinition x:Name="column2" />
+                        </Grid.ColumnDefinitions>
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup>
+                                <VisualState x:Name="ExitIconMode">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="tab" Storyboard.TargetProperty="(Width)" To="{Binding ActualWidth,ElementName=tabWidth}" Duration="0:0:0.2" />
+
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle3" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0.1" />
+                                        <DoubleAnimationUsingKeyFrames  Storyboard.TargetName="angle1" Storyboard.TargetProperty="(Angle)">
+                                            <SplineDoubleKeyFrame Value="0" KeyTime="0:0:0" />
+                                            <SplineDoubleKeyFrame Value="0" KeyTime="0:0:0.1" />
+                                            <SplineDoubleKeyFrame Value="45" KeyTime="0:0:0.3" />
+                                        </DoubleAnimationUsingKeyFrames>
+                                        <DoubleAnimationUsingKeyFrames  Storyboard.TargetName="angle2" Storyboard.TargetProperty="(Angle)">
+                                            <SplineDoubleKeyFrame Value="0" KeyTime="0:0:0" />
+                                            <SplineDoubleKeyFrame Value="0" KeyTime="0:0:0.1" />
+                                            <SplineDoubleKeyFrame Value="-45" KeyTime="0:0:0.3" />
+                                        </DoubleAnimationUsingKeyFrames>
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="EnterIconMode">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="tab" Storyboard.TargetProperty="(Width)" To="44" Duration="0:0:0.2" />
+
+                                        <DoubleAnimation Storyboard.TargetName="angle1" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0.2" />
+                                        <DoubleAnimation Storyboard.TargetName="angle2" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0.2" />
+                                        <ThicknessAnimationUsingKeyFrames Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="(Margin)">
+                                            <SplineThicknessKeyFrame Value="0" KeyTime="0:0:0" />
+                                            <SplineThicknessKeyFrame Value="0" KeyTime="0:0:0.1" />
+                                            <SplineThicknessKeyFrame Value="0,0,0,11" KeyTime="0:0:0.3" />
+                                        </ThicknessAnimationUsingKeyFrames>
+                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="(UIElement.Opacity)">
+                                            <SplineDoubleKeyFrame Value="0" KeyTime="0:0:0" />
+                                            <SplineDoubleKeyFrame Value="0" KeyTime="0:0:0.1" />
+                                            <SplineDoubleKeyFrame Value="1" KeyTime="0:0:0.3" />
+                                        </DoubleAnimationUsingKeyFrames>
+                                        <ThicknessAnimationUsingKeyFrames Storyboard.TargetName="rectangle3" Storyboard.TargetProperty="(Margin)">
+                                            <SplineThicknessKeyFrame Value="0" KeyTime="0:0:0" />
+                                            <SplineThicknessKeyFrame Value="0" KeyTime="0:0:0.1" />
+                                            <SplineThicknessKeyFrame Value="0,11,0,0" KeyTime="0:0:0.3" />
+                                        </ThicknessAnimationUsingKeyFrames>
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="SelectionStart" />
+                                <VisualState x:Name="SelectionStartIconMode">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="tab" Storyboard.TargetProperty="(Width)" To="44" Duration="0:0:0" />
+
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="(Margin)" To="0,0,0,11" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0" />
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle3" Storyboard.TargetProperty="(Margin)" To="0,11,0,0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle1" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle2" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="SelectionEnd">
+                                    <Storyboard>
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="30,0,-30,0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.0" />
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0.3" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.3" />
+
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0" />
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle3" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle1" Storyboard.TargetProperty="(Angle)" To="45" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle2" Storyboard.TargetProperty="(Angle)" To="-45" Duration="0:0:0" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="SelectionEndIconMode">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="tab" Storyboard.TargetProperty="(Width)" To="44" Duration="0:0:0" />
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="30,0,-30,0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.0" />
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0.3" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.3" />
+
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="(Margin)" To="0,0,0,11" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0" />
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle3" Storyboard.TargetProperty="(Margin)" To="0,11,0,0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle1" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle2" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="SelectionLoaded">
+                                    <Storyboard>
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0" />
+
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0" />
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle3" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle1" Storyboard.TargetProperty="(Angle)" To="45" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle2" Storyboard.TargetProperty="(Angle)" To="-45" Duration="0:0:0" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="SelectionLoadedIconMode">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="tab" Storyboard.TargetProperty="(Width)" To="44" Duration="0:0:0" />
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0" />
+
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="(Margin)" To="0,0,0,11" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0" />
+                                        <ThicknessAnimation Storyboard.TargetName="rectangle3" Storyboard.TargetProperty="(Margin)" To="0,11,0,0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle1" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="angle2" Storyboard.TargetProperty="(Angle)" To="0" Duration="0:0:0" />
+                                    </Storyboard>
+                                </VisualState>
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Grid x:Name="tab" MinWidth="44" Width="{Binding ActualWidth,ElementName=tabWidth}" Grid.Column="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1" Background="{TemplateBinding BorderBrush}">
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition />
+                            </Grid.RowDefinitions>
+                            <Rectangle Fill="#000000" Grid.RowSpan="2" Opacity="0.06" />
+                            <Metro:MetroFocusButton BorderThickness="0" MouseMoveBorderThickness="0" Command="Metro:MetroMenuTabControl.IconModeClickCommand" />
+                            <Grid Width="44" Height="40" HorizontalAlignment="Left" IsHitTestVisible="False">
+                                <Grid VerticalAlignment="Center" HorizontalAlignment="Center" Width="23" Height="23" Opacity="0.9">
+                                    <Rectangle x:Name="rectangle1" Width="22" Height="1" VerticalAlignment="Center" HorizontalAlignment="Center" Fill="#FFFFFF" Margin="0,0,0,11" RenderTransformOrigin="0.5,0.5">
+                                        <Rectangle.RenderTransform>
+                                            <TransformGroup>
+                                                <RotateTransform x:Name="angle1" Angle="0" />
+                                            </TransformGroup>
+                                        </Rectangle.RenderTransform>
+                                    </Rectangle>
+                                    <Rectangle x:Name="rectangle2" Width="22" Height="1" VerticalAlignment="Center" HorizontalAlignment="Center" Fill="#FFFFFF" />
+                                    <Rectangle x:Name="rectangle3" Width="22" Height="1" VerticalAlignment="Center" HorizontalAlignment="Center" Fill="#FFFFFF" Margin="0,11,0,0" RenderTransformOrigin="0.5,0.5">
+                                        <Rectangle.RenderTransform>
+                                            <TransformGroup>
+                                                <RotateTransform x:Name="angle2" Angle="0" />
+                                            </TransformGroup>
+                                        </Rectangle.RenderTransform>
+                                    </Rectangle>
+                                </Grid>
+                            </Grid>
+                            <Metro:MetroScrollViewer Grid.Row="1" BorderBrush="White" VerticalAlignment="{TemplateBinding TabPanelVerticalAlignment}" Margin="{TemplateBinding Padding}">
+                                <Canvas x:Name="canvas" Height="{Binding ActualHeight,ElementName=tabWidth}">
+                                    <Grid x:Name="tabWidth">
+                                        <TabPanel x:Name="headerPanel" IsItemsHost="true" />
+                                    </Grid>
+                                </Canvas>
+                            </Metro:MetroScrollViewer>
+                        </Grid>
+                        <Border x:Name="contentPanel" Background="#f3f3f3" Grid.Column="1" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
+                            <ContentPresenter x:Name="content" ContentSource="SelectedContent" />
+                        </Border>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="TabStripPlacement" Value="Right">
+                            <Setter TargetName="column1" Property="Width" Value="*" />
+                            <Setter TargetName="column2" Property="Width" Value="Auto" />
+                            <Setter TargetName="tab" Property="Grid.Column" Value="1" />
+                            <Setter TargetName="contentPanel" Property="Grid.Column" Value="0" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 23 - 0
Arthas-WPFUI/Arthas/Controls/MetroMenuTabItem.cs

@@ -0,0 +1,23 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroMenuTabItem : TabItem
+    {
+        public static readonly DependencyProperty IconProperty = ElementBase.Property<MetroMenuTabItem, ImageSource>(nameof(IconProperty), null);
+        public static readonly DependencyProperty IconMoveProperty = ElementBase.Property<MetroMenuTabItem, ImageSource>(nameof(IconMoveProperty), null);
+        public static readonly DependencyProperty TextHorizontalAlignmentProperty = ElementBase.Property<MetroMenuTabItem, HorizontalAlignment>(nameof(TextHorizontalAlignmentProperty), HorizontalAlignment.Right);
+
+        public ImageSource Icon { get { return (ImageSource)GetValue(IconProperty); } set { SetValue(IconProperty, value); } }
+        public ImageSource IconMove { get { return (ImageSource)GetValue(IconMoveProperty); } set { SetValue(IconMoveProperty, value); } }
+        public HorizontalAlignment TextHorizontalAlignment { get { return (HorizontalAlignment)GetValue(TextHorizontalAlignmentProperty); } set { SetValue(TextHorizontalAlignmentProperty, value); } }
+
+        static MetroMenuTabItem()
+        {
+            ElementBase.DefaultStyle<MetroMenuTabItem>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 60 - 0
Arthas-WPFUI/Arthas/Controls/MetroMenuTabItem.xaml

@@ -0,0 +1,60 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroMenuTabItem}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="MinWidth" Value="150" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroMenuTabItem}">
+                    <Grid Background="#00000000">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition x:Name="iconWidth" Width="Auto" />
+                            <ColumnDefinition x:Name="contentWidth" />
+                        </Grid.ColumnDefinitions>
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal" />
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="back" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.2" />
+                                        <ColorAnimation Storyboard.TargetName="title" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" To="#A5000000" Duration="0:0:0.2" />
+                                        <DoubleAnimation Storyboard.TargetName="icon" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.2" />
+                                        <DoubleAnimation Storyboard.TargetName="iconMove" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.2" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed" />
+                                <VisualState x:Name="Disabled" />
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Rectangle x:Name="back" Grid.ColumnSpan="2" Fill="#f3f3f3" Opacity="0" />
+                        <Image x:Name="iconMove" Width="24" Height="24" Margin="10,8" Source="{TemplateBinding IconMove}" Opacity="0" />
+                        <Image x:Name="icon" Width="24" Height="24" Margin="10,8" Source="{TemplateBinding Icon}" />
+                        <Metro:MetroTextBlock x:Name="title" Grid.Column="2" Text="{TemplateBinding Header}" Foreground="#E5FFFFFF" Margin="0,0,15,0" VerticalAlignment="Center" HorizontalAlignment="{TemplateBinding TextHorizontalAlignment}" />
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="Selector.IsSelected" Value="True">
+                            <Setter TargetName="back" Property="Opacity" Value="1" />
+                            <Setter TargetName="title" Property="Foreground" Value="#A5000000" />
+                            <Setter TargetName="icon" Property="Opacity" Value="0" />
+                            <Setter TargetName="iconMove" Property="Opacity" Value="1" />
+                        </Trigger>
+                        <!-- Icon 已经列为必须存在项,所以不隐藏区域 -->
+                        <!--
+                        <Trigger Property="Icon" Value="{x:Null}">
+                            <Setter TargetName="iconWidth" Property="Width" Value="0" />
+                            <Setter TargetName="title" Property="Margin" Value="15,0" />
+                        </Trigger>
+                        -->
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 19 - 0
Arthas-WPFUI/Arthas/Controls/MetroPath.cs

@@ -0,0 +1,19 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroPath : ContentControl
+    {
+        public static readonly DependencyProperty DataProperty = ElementBase.Property<MetroPath, Geometry>(nameof(DataProperty));
+
+        public Geometry Data { get { return (Geometry)GetValue(DataProperty); } set { SetValue(DataProperty, value); } }
+
+        static MetroPath()
+        {
+            ElementBase.DefaultStyle<MetroPath>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 25 - 0
Arthas-WPFUI/Arthas/Controls/MetroPath.xaml

@@ -0,0 +1,25 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroPath}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="Foreground" Value="#FF000000" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroPath}">
+                    <Viewbox>
+                        <Canvas Width="24" Height="24">
+                            <Path Data="{TemplateBinding Data}" Fill="{TemplateBinding Foreground}" />
+                        </Canvas>
+                    </Viewbox>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 47 - 0
Arthas-WPFUI/Arthas/Controls/MetroProgressBar.cs

@@ -0,0 +1,47 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public enum ProgressBarState
+    {
+        None,
+        Error,
+        Wait
+    }
+
+    public class MetroProgressBar : ProgressBar
+    {
+        public static readonly DependencyProperty ProgressBarStateProperty = ElementBase.Property<MetroProgressBar, ProgressBarState>(nameof(ProgressBarStateProperty));
+        public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property<MetroProgressBar, CornerRadius>(nameof(CornerRadiusProperty));
+        public static readonly DependencyProperty TitleProperty = ElementBase.Property<MetroProgressBar, string>(nameof(TitleProperty));
+        public static readonly DependencyProperty HintProperty = ElementBase.Property<MetroProgressBar, string>(nameof(HintProperty));
+        public static readonly DependencyProperty ProgressBarHeightProperty = ElementBase.Property<MetroProgressBar, double>(nameof(ProgressBarHeightProperty));
+        public static readonly DependencyProperty TextHorizontalAlignmentProperty = ElementBase.Property<MetroProgressBar, HorizontalAlignment>(nameof(TextHorizontalAlignmentProperty));
+
+        public ProgressBarState ProgressBarState { get { return (ProgressBarState)GetValue(ProgressBarStateProperty); } set { SetValue(ProgressBarStateProperty, value); } }
+        public CornerRadius CornerRadius { get { return (CornerRadius)GetValue(CornerRadiusProperty); } set { SetValue(CornerRadiusProperty, value); } }
+        public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } }
+        public string Hint { get { return (string)GetValue(HintProperty); } set { SetValue(HintProperty, value); } }
+        public double ProgressBarHeight { get { return (double)GetValue(ProgressBarHeightProperty); } set { SetValue(ProgressBarHeightProperty, value); } }
+        public HorizontalAlignment TextHorizontalAlignment { get { return (HorizontalAlignment)GetValue(TextHorizontalAlignmentProperty); } set { SetValue(TextHorizontalAlignmentProperty, value); } }
+
+        public MetroProgressBar()
+        {
+            Utility.Refresh(this);
+            ValueChanged += delegate
+            {
+                if (Hint == null || Hint.EndsWith(" %"))
+                {
+                    Hint = ((int)(Value / Maximum * 100)).ToString() + " %";
+                }
+            };
+        }
+
+        static MetroProgressBar()
+        {
+            ElementBase.DefaultStyle<MetroProgressBar>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 110 - 0
Arthas-WPFUI/Arthas/Controls/MetroProgressBar.xaml

@@ -0,0 +1,110 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls"
+                    xmlns:Converter="clr-namespace:Arthas.Controls.Converter">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Converter:CornerRadiusToDouble x:Key="CornerRadiusToDouble" />
+
+    <Style TargetType="{x:Type Metro:MetroProgressBar}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="ProgressBarHeight" Value="15" />
+        <Setter Property="CornerRadius" Value="7.5" />
+        <Setter Property="ProgressBarState" Value="None" />
+        <Setter Property="Background" Value="#6fae5f" />
+        <Setter Property="FontSize" Value="10" />
+        <Setter Property="Padding" Value="5,0" />
+        <Setter Property="TextHorizontalAlignment" Value="Left" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroProgressBar}">
+                    <Grid Background="#00000000">
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="Auto" x:Name="height1" />
+                            <RowDefinition Height="Auto" />
+                        </Grid.RowDefinitions>
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Determinate" />
+                                <VisualState x:Name="Indeterminate">
+                                    <Storyboard RepeatBehavior="Forever">
+                                        <PointAnimationUsingKeyFrames Storyboard.TargetName="Animation" Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)">
+                                            <EasingPointKeyFrame KeyTime="0:0:0" Value="0.5,0.5" />
+                                            <EasingPointKeyFrame KeyTime="0:0:1.5" Value="1.95,0.5" />
+                                            <EasingPointKeyFrame KeyTime="0:0:3" Value="0.5,0.5" />
+                                        </PointAnimationUsingKeyFrames>
+                                    </Storyboard>
+                                </VisualState>
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Metro:MetroTextBlock Text="{TemplateBinding Title}" FontSize="12" Opacity="0.65" Margin="0,0,0,10" HorizontalAlignment="{TemplateBinding TextHorizontalAlignment}" />
+                        <Grid Grid.Row="1" Height="{TemplateBinding ProgressBarHeight}">
+                            <Border Background="#000000" CornerRadius="{TemplateBinding CornerRadius}" Opacity="0.05" />
+                            <Border BorderBrush="#000000" BorderThickness="1" CornerRadius="{TemplateBinding CornerRadius}" Opacity="0.1" />
+                            <Grid Margin="{TemplateBinding BorderThickness}">
+                                <Border x:Name="PART_Track" />
+                                <Grid x:Name="PART_Indicator" ClipToBounds="True" HorizontalAlignment="Left" MinWidth="{TemplateBinding CornerRadius,Converter={StaticResource CornerRadiusToDouble},ConverterParameter=2}">
+                                    <Grid.ColumnDefinitions>
+                                        <ColumnDefinition x:Name="width1" />
+                                        <ColumnDefinition x:Name="width2" Width="0" />
+                                    </Grid.ColumnDefinitions>
+                                    <Grid x:Name="Animation"  RenderTransformOrigin="0.5,0.5">
+                                        <Grid.RenderTransform>
+                                            <TransformGroup>
+                                                <ScaleTransform ScaleY="-1" ScaleX="1" />
+                                                <SkewTransform AngleY="0" AngleX="0" />
+                                                <RotateTransform Angle="180" />
+                                                <TranslateTransform />
+                                            </TransformGroup>
+                                        </Grid.RenderTransform>
+                                        <Border Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding CornerRadius}">
+                                            <Viewbox HorizontalAlignment="Left" StretchDirection="DownOnly" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="True">
+                                                <Metro:MetroTextBlock Foreground="#ffffff" SnapsToDevicePixels="True" FontSize="{TemplateBinding FontSize}" VerticalAlignment="Center" Text="{TemplateBinding Hint}" RenderTransformOrigin="0.5,0.5">
+                                                    <Metro:MetroTextBlock.RenderTransform>
+                                                        <TransformGroup>
+                                                            <ScaleTransform ScaleY="1" ScaleX="-1" />
+                                                            <SkewTransform AngleY="0" AngleX="0" />
+                                                            <RotateTransform Angle="0" />
+                                                            <TranslateTransform />
+                                                        </TransformGroup>
+                                                    </Metro:MetroTextBlock.RenderTransform>
+                                                </Metro:MetroTextBlock>
+                                            </Viewbox>
+                                        </Border>
+                                        <Border BorderBrush="#000000" BorderThickness="1" CornerRadius="{TemplateBinding CornerRadius}" Opacity="0.1" />
+                                    </Grid>
+                                </Grid>
+                            </Grid>
+                        </Grid>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="ProgressBarState" Value="Wait">
+                            <Setter Property="IsIndeterminate" Value="true" />
+                            <Setter Property="Background" Value="#edb15a" />
+                        </Trigger>
+                        <Trigger Property="Title" Value="{x:Null}">
+                            <Setter TargetName="height1" Property="Height" Value="0" />
+                        </Trigger>
+                        <Trigger Property="Title" Value="">
+                            <Setter TargetName="height1" Property="Height" Value="0" />
+                        </Trigger>
+                        <Trigger Property="ProgressBarState" Value="Error">
+                            <Setter Property="Background" Value="#e67979" />
+                        </Trigger>
+                        <Trigger Property="IsEnabled" Value="False">
+                            <Setter Property="Background" Value="#c5c5c5" />
+                        </Trigger>
+                        <Trigger Property="IsIndeterminate" Value="true">
+                            <Setter TargetName="width1" Property="Width" Value="0.25*" />
+                            <Setter TargetName="width2" Property="Width" Value="0.725*" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 224 - 0
Arthas-WPFUI/Arthas/Controls/MetroRichTextBox.cs

@@ -0,0 +1,224 @@
+using Arthas.Utility.Element;
+using Arthas.Utility.Media;
+using System;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroRichTextBox : RichTextBox
+    {
+        public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property<MetroRichTextBox, CornerRadius>(nameof(CornerRadiusProperty));
+        public static readonly new DependencyProperty BorderBrushProperty = ElementBase.Property<MetroRichTextBox, Brush>(nameof(ForegroundProperty));
+        public static readonly DependencyProperty MouseMoveBorderBrushProperty = ElementBase.Property<MetroRichTextBox, Brush>(nameof(MouseMoveBorderBrushProperty));
+        public static readonly DependencyProperty MouseMoveThemeBorderBrushProperty = ElementBase.Property<MetroRichTextBox, Brush>(nameof(MouseMoveThemeBorderBrushProperty));
+        public static readonly DependencyProperty AutoLimitMouseProperty = ElementBase.Property<MetroRichTextBox, bool>(nameof(AutoLimitMouseProperty), false);
+
+        public CornerRadius CornerRadius { get { return (CornerRadius)GetValue(CornerRadiusProperty); } set { SetValue(CornerRadiusProperty, value); } }
+        public new Brush BorderBrush { get { return (Brush)GetValue(BorderBrushProperty); } set { SetValue(BorderBrushProperty, value); } }
+        public Brush MouseMoveBorderBrush { get { return (Brush)GetValue(MouseMoveBorderBrushProperty); } set { SetValue(MouseMoveBorderBrushProperty, value); } }
+        public Brush MouseMoveThemeBorderBrush { get { return (Brush)GetValue(MouseMoveThemeBorderBrushProperty); } set { SetValue(MouseMoveThemeBorderBrushProperty, value); } }
+        public bool AutoLimitMouse { get { return (bool)GetValue(AutoLimitMouseProperty); } set { SetValue(AutoLimitMouseProperty, value); } }
+
+        void SetColor()
+        {
+            CaretBrush = Foreground;
+            SelectionBrush = Foreground;
+        }
+
+        void SetSize()
+        {
+            var w = ActualWidth - BorderThickness.Left - BorderThickness.Right - Padding.Left - Padding.Right - 2;
+            Document.MaxPageWidth = w > 0 ? w : Document.MaxPageWidth;
+        }
+
+        static MetroRichTextBox()
+        {
+            ElementBase.DefaultStyle<MetroRichTextBox>(DefaultStyleKeyProperty);
+        }
+
+        public MetroRichTextBox()
+        {
+            ContextMenu = null;
+            Utility.Refresh(this);
+            Loaded += delegate
+            {
+                SetColor();
+                SetSize();
+            };
+            SizeChanged += delegate
+            {
+                SetSize();
+            };
+        }
+
+        public void Clear()
+        {
+            Document.Blocks.Clear();
+        }
+
+        public string Text
+        {
+            get
+            {
+                var sb = new StringBuilder();
+                var isFirst = true;
+                foreach (var block in Document.Blocks)
+                {
+                    if (isFirst)
+                        isFirst = false;
+                    else
+                        sb.AppendLine();
+
+                    if (block is Paragraph)
+                        foreach (var inline in ((Paragraph)block).Inlines)
+                        {
+                            if (inline is Run)
+                                sb.Append(((Run)inline).Text);
+                            else if (inline is LineBreak)
+                                sb.AppendLine();
+                        }
+                }
+                return sb.ToString();
+            }
+        }
+
+        public void AddLine(string content, RgbaColor rgba, Action action)
+        {
+            Run run = new Run(content);
+            if (action == null)
+            {
+                if (rgba != null) { run.Foreground = rgba.SolidColorBrush; }
+                Document.Blocks.Add(new Paragraph(run));
+            }
+            else
+            {
+                Hyperlink hl = new Hyperlink(run);
+                if (rgba != null) { hl.Foreground = rgba.SolidColorBrush; }
+                hl.Click += delegate { action(); };
+                hl.MouseLeftButtonDown += delegate { action(); };
+                Document.Blocks.Add(new Paragraph(hl));
+            }
+            ScrollToEnd();
+        }
+
+        public void AddLine(ImageSource image, Action action)
+        {
+            if (action == null)
+            {
+                Document.Blocks.Add(new Paragraph(new InlineUIContainer(new MetroImage(image))));
+            }
+            else
+            {
+                Hyperlink hl = new Hyperlink(new InlineUIContainer(new MetroImage(image)));
+                hl.Foreground = null;
+                hl.Click += delegate { action(); };
+                hl.MouseLeftButtonDown += delegate { action(); };
+                Document.Blocks.Add(new Paragraph(hl));
+            }
+            ScrollToEnd();
+        }
+
+        public void AddLine()
+        {
+            AddLine("", (Action)null);
+        }
+
+        public void AddLine(string content)
+        {
+            AddLine(content, (Action)null);
+        }
+
+        public void AddLine(string content, RgbaColor rgba)
+        {
+            AddLine(content, rgba, null);
+        }
+
+        public void AddLine(ImageSource image)
+        {
+            AddLine(image, (Action)null);
+        }
+
+        public void AddLine(string content, Action action)
+        {
+            AddLine(content, null, action);
+        }
+
+        public void AddLine(string title, string url)
+        {
+            AddLine(title, () => System.Diagnostics.Process.Start(url));
+        }
+
+        public void Add(string title, string url)
+        {
+            Add(title, () => System.Diagnostics.Process.Start(url));
+        }
+
+        public void Add(string content, RgbaColor rgba, Action action)
+        {
+            if (Document.Blocks.Count <= 0)
+            {
+                Document.Blocks.Add(new Paragraph());
+            }
+            Run run = new Run(content);
+            if (action == null)
+            {
+                if (rgba != null) { run.Foreground = rgba.SolidColorBrush; }
+                (Document.Blocks.LastBlock as Paragraph).Inlines.Add(run);
+            }
+            else
+            {
+                Hyperlink hl = new Hyperlink(run);
+                if (rgba != null) { hl.Foreground = rgba.SolidColorBrush; }
+                hl.Click += delegate { action(); };
+                hl.MouseLeftButtonDown += delegate { action(); };
+                (Document.Blocks.LastBlock as Paragraph).Inlines.Add(hl);
+            }
+            ScrollToEnd();
+        }
+
+        public void Add(ImageSource image, Action action)
+        {
+            if (Document.Blocks.Count <= 0)
+            {
+                Document.Blocks.Add(new Paragraph());
+            }
+            if (action == null)
+            {
+                (Document.Blocks.LastBlock as Paragraph).Inlines.Add(new InlineUIContainer(new MetroImage(image)));
+            }
+            else
+            {
+                Hyperlink hl = new Hyperlink(new InlineUIContainer(new MetroImage(image)));
+                hl.Foreground = null;
+                hl.Click += delegate { action(); };
+                hl.MouseLeftButtonDown += delegate { action(); };
+                (Document.Blocks.LastBlock as Paragraph).Inlines.Add(hl);
+            }
+            ScrollToEnd();
+        }
+
+        public void Add(string content)
+        {
+            Add(content, null, (Action)null);
+        }
+
+        public void Add(string content, RgbaColor rgba)
+        {
+            Add(content, rgba, null);
+        }
+
+        public void Add(ImageSource image)
+        {
+            Add(image, (Action)null);
+        }
+
+        public void Add(string content, Action action)
+        {
+            Add(content, null, action);
+        }
+    }
+}

+ 103 - 0
Arthas-WPFUI/Arthas/Controls/MetroRichTextBox.xaml

@@ -0,0 +1,103 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroRichTextBox}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="BorderThickness" Value="1" />
+        <Setter Property="CornerRadius" Value="2" />
+        <Setter Property="Background" Value="#ffffff" />
+        <!--
+        <Setter Property="CaretBrush" Value="{StaticResource Brush}" />
+        <Setter Property="SelectionBrush" Value="{StaticResource Brush}" />
+        -->
+        <Setter Property="Foreground" Value="#BF000000" />
+        <Setter Property="Padding" Value="1,3" />
+        <Setter Property="SelectionOpacity" Value="0.2" />
+        <Setter Property="BorderBrush" Value="#26000000" />
+        <Setter Property="MouseMoveBorderBrush" Value="{x:Null}" />
+        <Setter Property="MouseMoveThemeBorderBrush" Value="{StaticResource Brush}" />
+        <Setter Property="IsDocumentEnabled" Value="True" />
+
+        <Setter Property="AcceptsReturn" Value="True" />
+        <Setter Property="AcceptsTab" Value="True" />
+
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroRichTextBox}">
+                    <Grid>
+                        <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" />
+                        <Border x:Name="border" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="{TemplateBinding BorderBrush}" />
+                        <Border x:Name="bordermove" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="{TemplateBinding MouseMoveBorderBrush}" Opacity="0" />
+                        <Border x:Name="themebordermove" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="{TemplateBinding MouseMoveThemeBorderBrush}" Opacity="0" />
+                        <Metro:MetroScrollViewer BorderBrush="{TemplateBinding Foreground}" Margin="{TemplateBinding BorderThickness}" Focusable="False" AutoLimitMouse="{TemplateBinding AutoLimitMouse}">
+                            <ScrollViewer x:Name="PART_ContentHost" MinHeight="0" MinWidth="0" Margin="{TemplateBinding Padding}" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" />
+                        </Metro:MetroScrollViewer>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsEnabled" Value="false">
+                            <Setter TargetName="PART_ContentHost" Property="Opacity" Value="0.5" />
+                            <Setter Property="Background" Value="#fafafa" />
+                        </Trigger>
+                        <Trigger Property="IsKeyboardFocused" Value="true">
+                            <Setter TargetName="border" Property="Opacity" Value="0" />
+                            <Setter TargetName="bordermove" Property="Opacity" Value="1" />
+                        </Trigger>
+                        <Trigger Property="IsMouseOver" Value="true">
+                            <Setter TargetName="border" Property="Opacity" Value="0" />
+                            <Setter TargetName="bordermove" Property="Opacity" Value="1" />
+                        </Trigger>
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="IsMouseOver" Value="true" />
+                                <Condition Property="MouseMoveBorderBrush" Value="{x:Null}" />
+                            </MultiTrigger.Conditions>
+                            <Setter TargetName="border" Property="Opacity" Value="0" />
+                            <Setter TargetName="themebordermove" Property="Opacity" Value="1" />
+                        </MultiTrigger>
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="IsKeyboardFocused" Value="true" />
+                                <Condition Property="MouseMoveBorderBrush" Value="{x:Null}" />
+                            </MultiTrigger.Conditions>
+                            <Setter TargetName="border" Property="Opacity" Value="0" />
+                            <Setter TargetName="themebordermove" Property="Opacity" Value="1" />
+                        </MultiTrigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+        <Style.Resources>
+            <Style TargetType="{x:Type FlowDocument}">
+                <Setter Property="OverridesDefaultStyle" Value="true" />
+                <Setter Property="PagePadding" Value="0" />
+                <Setter Property="LineHeight" Value="20" />
+            </Style>
+            <Style TargetType="{x:Type Paragraph}">
+                <Setter Property="Margin" Value="0" />
+            </Style>
+            <Style TargetType="{x:Type Hyperlink}">
+                <Setter Property="Foreground" Value="#5599f8" />
+                <Setter Property="ForceCursor" Value="True" />
+                <Setter Property="Cursor" Value="Hand" />
+                <Setter Property ="TextBlock.TextDecorations" Value ="{x:Null}" />
+                <Style.Triggers>
+                    <Trigger Property="IsMouseOver" Value="true">
+                        <Setter Property ="TextBlock.TextDecorations">
+                            <Setter.Value>
+                                <TextDecorationCollection>
+                                    <TextDecoration  Location ="Underline" />
+                                </TextDecorationCollection>
+                            </Setter.Value>
+                        </Setter>
+                    </Trigger>
+                </Style.Triggers>
+            </Style>
+        </Style.Resources>
+    </Style>
+</ResourceDictionary>

+ 29 - 0
Arthas-WPFUI/Arthas/Controls/MetroScrollViewer.cs

@@ -0,0 +1,29 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroScrollViewer : ScrollViewer
+    {
+        public static readonly DependencyProperty FloatProperty = ElementBase.Property<MetroScrollViewer, bool>(nameof(FloatProperty));
+        public static readonly DependencyProperty AutoLimitMouseProperty = ElementBase.Property<MetroScrollViewer, bool>(nameof(AutoLimitMouseProperty));
+        public static readonly DependencyProperty VerticalMarginProperty = ElementBase.Property<MetroScrollViewer, Thickness>(nameof(VerticalMarginProperty));
+        public static readonly DependencyProperty HorizontalMarginProperty = ElementBase.Property<MetroScrollViewer, Thickness>(nameof(HorizontalMarginProperty));
+
+        public bool Float { get { return (bool)GetValue(FloatProperty); } set { SetValue(FloatProperty, value); } }
+        public bool AutoLimitMouse { get { return (bool)GetValue(AutoLimitMouseProperty); } set { SetValue(AutoLimitMouseProperty, value); } }
+        public Thickness VerticalMargin { get { return (Thickness)GetValue(VerticalMarginProperty); } set { SetValue(VerticalMarginProperty, value); } }
+        public Thickness HorizontalMargin { get { return (Thickness)GetValue(HorizontalMarginProperty); } set { SetValue(HorizontalMarginProperty, value); } }
+
+        public MetroScrollViewer()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroScrollViewer()
+        {
+            ElementBase.DefaultStyle<MetroScrollViewer>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 229 - 0
Arthas-WPFUI/Arthas/Controls/MetroScrollViewer.xaml

@@ -0,0 +1,229 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style x:Key="repeatButtonStyle" TargetType="{x:Type RepeatButton}">
+        <Setter Property="SnapsToDevicePixels" Value="true" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type RepeatButton}">
+                    <Rectangle Fill="#00000000" />
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style x:Key="thumbStyle" TargetType="{x:Type Thumb}">
+        <Setter Property="SnapsToDevicePixels" Value="true" />
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Thumb}">
+                    <Grid Background="#00000000">
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.3" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(Rectangle.Width)" To="10" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.3" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(Rectangle.Width)" To="10" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.1" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(Rectangle.Width)" To="10" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Disabled">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.2" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(Rectangle.Width)" To="3" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Rectangle x:Name="rect" Fill="{TemplateBinding BorderBrush}" Opacity="0.2" Width="0" HorizontalAlignment="Right" />
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style x:Key="thumbStyle1" TargetType="{x:Type Thumb}">
+        <Setter Property="SnapsToDevicePixels" Value="true" />
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Thumb}">
+                    <Grid Background="#00000000">
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.3" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(Rectangle.Height)" To="10" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.3" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(Rectangle.Height)" To="10" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.1" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(Rectangle.Height)" To="10" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Disabled">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.2" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="(Rectangle.Height)" To="3" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Rectangle x:Name="rect" Fill="{TemplateBinding BorderBrush}" Opacity="0.2" Height="0" VerticalAlignment="Bottom" />
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style x:Key="scrollBarStyle" TargetType="{x:Type ScrollBar}">
+        <Setter Property="SnapsToDevicePixels" Value="true" />
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="ContextMenu" Value="{x:Null}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type ScrollBar}">
+                    <Grid SnapsToDevicePixels="true">
+                        <Track x:Name="PART_Track" IsDirectionReversed="true" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Row="1">
+                            <Track.DecreaseRepeatButton>
+                                <RepeatButton Command="{x:Static ScrollBar.PageUpCommand}" Style="{StaticResource repeatButtonStyle}" />
+                            </Track.DecreaseRepeatButton>
+                            <Track.IncreaseRepeatButton>
+                                <RepeatButton Command="{x:Static ScrollBar.PageDownCommand}" Style="{StaticResource repeatButtonStyle}" />
+                            </Track.IncreaseRepeatButton>
+                            <Track.Thumb>
+                                <Thumb Style="{StaticResource thumbStyle}" BorderBrush="{TemplateBinding BorderBrush}" />
+                            </Track.Thumb>
+                        </Track>
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style x:Key="scrollBarStyle1" TargetType="{x:Type ScrollBar}">
+        <Setter Property="SnapsToDevicePixels" Value="true" />
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="ContextMenu" Value="{x:Null}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type ScrollBar}">
+                    <Grid SnapsToDevicePixels="true">
+                        <Track x:Name="PART_Track" IsDirectionReversed="true" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Row="1">
+                            <Track.DecreaseRepeatButton>
+                                <RepeatButton Command="{x:Static ScrollBar.PageLeftCommand}" Style="{StaticResource repeatButtonStyle}" />
+                            </Track.DecreaseRepeatButton>
+                            <Track.IncreaseRepeatButton>
+                                <RepeatButton Command="{x:Static ScrollBar.PageRightCommand}" Style="{StaticResource repeatButtonStyle}" />
+                            </Track.IncreaseRepeatButton>
+                            <Track.Thumb>
+                                <Thumb Style="{StaticResource thumbStyle1}" BorderBrush="{TemplateBinding BorderBrush}" />
+                            </Track.Thumb>
+                        </Track>
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
+    <Style TargetType="{x:Type Metro:MetroScrollViewer}">
+        <Setter Property="Background" Value="#00000000" />
+        <Setter Property="BorderBrush" Value="#000000" />
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="Padding" Value="0" />
+        <Setter Property="VerticalScrollBarVisibility" Value="Auto" />
+        <Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
+
+        <Setter Property="Float" Value="True" />
+        <Setter Property="AutoLimitMouse" Value="False" />
+        <Setter Property="VerticalMargin" Value="0" />
+        <Setter Property="HorizontalMargin" Value="0" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroScrollViewer}">
+                    <Grid Background="{TemplateBinding Background}">
+                        <Grid.RowDefinitions>
+                            <RowDefinition />
+                            <RowDefinition x:Name="height" Height="0" />
+                        </Grid.RowDefinitions>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition />
+                            <ColumnDefinition x:Name="width" Width="0" />
+                        </Grid.ColumnDefinitions>
+                        <ScrollContentPresenter Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}" />
+                        <!--
+                        <Rectangle VerticalAlignment="Top" Height="5" IsHitTestVisible="False">
+                            <Rectangle.Fill>
+                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
+                                    <GradientStop Color="#f3f3f3" />
+                                    <GradientStop Color="#00f3f3f3" Offset="1" />
+                                </LinearGradientBrush>
+                            </Rectangle.Fill>
+                        </Rectangle>
+                        <Rectangle VerticalAlignment="Bottom" Height="5" IsHitTestVisible="False">
+                            <Rectangle.Fill>
+                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
+                                    <GradientStop Color="#00f3f3f3" />
+                                    <GradientStop Color="#f3f3f3" Offset="1" />
+                                </LinearGradientBrush>
+                            </Rectangle.Fill>
+                        </Rectangle>
+                        -->
+                        <ScrollBar x:Name="PART_VerticalScrollBar"   Margin="{TemplateBinding VerticalMargin}" MinWidth="10" MaxWidth="10"  BorderBrush="{TemplateBinding BorderBrush}" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" Style="{StaticResource scrollBarStyle}" HorizontalAlignment="Right" />
+                        <ScrollBar x:Name="PART_HorizontalScrollBar" Margin="{TemplateBinding HorizontalMargin}" MinHeight="10" MaxHeight="10" BorderBrush="{TemplateBinding BorderBrush}" AutomationProperties.AutomationId="HorizontalScrollBar" Grid.Column="0" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" Style="{StaticResource scrollBarStyle1}" FlowDirection="RightToLeft" Orientation="Horizontal" VerticalAlignment="Bottom" />
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="Float" Value="true">
+                            <Setter Property="Grid.Column" TargetName="PART_VerticalScrollBar" Value="0" />
+                            <Setter Property="Grid.Row" TargetName="PART_VerticalScrollBar" Value="0" />
+                            <Setter Property="Grid.Column" TargetName="PART_HorizontalScrollBar" Value="0" />
+                            <Setter Property="Grid.Row" TargetName="PART_HorizontalScrollBar" Value="0" />
+                        </Trigger>
+                        <Trigger Property="ComputedVerticalScrollBarVisibility" Value="Visible">
+                            <Setter Property="Width" TargetName="width" Value="10" />
+                        </Trigger>
+                        <Trigger Property="ComputedHorizontalScrollBarVisibility" Value="Visible">
+                            <Setter Property="Height" TargetName="height" Value="10" />
+                        </Trigger>
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="Float" Value="true" />
+                                <Condition Property="ComputedHorizontalScrollBarVisibility" Value="Visible" />
+                            </MultiTrigger.Conditions>
+                            <Setter Property="Margin" TargetName="PART_VerticalScrollBar" Value="0,0,0,10" />
+                            <Setter Property="Height" TargetName="height" Value="0" />
+                        </MultiTrigger>
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="Float" Value="true" />
+                                <Condition Property="ComputedVerticalScrollBarVisibility" Value="Visible" />
+                            </MultiTrigger.Conditions>
+                            <Setter Property="Margin" TargetName="PART_HorizontalScrollBar" Value="0,0,10,0" />
+                            <Setter Property="Width" TargetName="width" Value="0" />
+                        </MultiTrigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 39 - 0
Arthas-WPFUI/Arthas/Controls/MetroSwitch.cs

@@ -0,0 +1,39 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls.Primitives;
+
+namespace Arthas.Controls
+{
+    public class MetroSwitch : ToggleButton
+    {
+        public static readonly DependencyProperty TextHorizontalAlignmentProperty = ElementBase.Property<MetroSwitch, HorizontalAlignment>(nameof(TextHorizontalAlignmentProperty), HorizontalAlignment.Left);
+        public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property<MetroSwitch, CornerRadius>(nameof(CornerRadiusProperty), new CornerRadius(10));
+        public static readonly DependencyProperty BorderCornerRadiusProperty = ElementBase.Property<MetroSwitch, CornerRadius>(nameof(BorderCornerRadiusProperty), new CornerRadius(12));
+
+        public HorizontalAlignment TextHorizontalAlignment { get { return (HorizontalAlignment)GetValue(TextHorizontalAlignmentProperty); } set { SetValue(TextHorizontalAlignmentProperty, value); } }
+        public CornerRadius CornerRadius { get { return (CornerRadius)GetValue(CornerRadiusProperty); } set { SetValue(CornerRadiusProperty, value); } }
+        public CornerRadius BorderCornerRadius { get { return (CornerRadius)GetValue(BorderCornerRadiusProperty); } set { SetValue(BorderCornerRadiusProperty, value); } }
+
+        public MetroSwitch()
+        {
+            Loaded += delegate { ElementBase.GoToState(this, (bool)IsChecked ? "OpenLoaded" : "CloseLoaded"); };
+        }
+
+        protected override void OnChecked(RoutedEventArgs e)
+        {
+            base.OnChecked(e);
+            ElementBase.GoToState(this, "Open");
+        }
+
+        protected override void OnUnchecked(RoutedEventArgs e)
+        {
+            base.OnChecked(e);
+            ElementBase.GoToState(this, "Close");
+        }
+
+        static MetroSwitch()
+        {
+            ElementBase.DefaultStyle<MetroSwitch>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 73 - 0
Arthas-WPFUI/Arthas/Controls/MetroSwitch.xaml

@@ -0,0 +1,73 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroSwitch}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="Height" Value="24" />
+        <Setter Property="HorizontalAlignment" Value="Stretch" />
+        <Setter Property="CornerRadius" Value="10" />
+        <Setter Property="BorderCornerRadius" Value="12" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroSwitch}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition x:Name="width1" />
+                            <ColumnDefinition Width="10" x:Name="width2" />
+                            <ColumnDefinition Width="45" />
+                        </Grid.ColumnDefinitions>
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup>
+                                <VisualState x:Name="Open">
+                                    <Storyboard>
+                                        <ThicknessAnimation Storyboard.TargetName="yuan" Storyboard.TargetProperty="(Margin)" To="2,2,2,2" Duration="0:0:0.2" />
+                                        <ThicknessAnimation Storyboard.TargetName="yuan" Storyboard.TargetProperty="(Margin)" To="23,2,2,2" Duration="0:0:0.4" />
+                                        <ColorAnimation Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="#99cb8a" Duration="0:0:0.4" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="OpenLoaded">
+                                    <Storyboard>
+                                        <ThicknessAnimation Storyboard.TargetName="yuan" Storyboard.TargetProperty="(Margin)" To="23,2,2,2" Duration="0:0:0" />
+                                        <ColorAnimation Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="#99cb8a" Duration="0:0:0" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Close">
+                                    <Storyboard>
+                                        <ThicknessAnimation Storyboard.TargetName="yuan" Storyboard.TargetProperty="(Margin)" To="2,2,2,2" Duration="0:0:0.2" />
+                                        <ThicknessAnimation Storyboard.TargetName="yuan" Storyboard.TargetProperty="(Margin)" To="2,2,23,2" Duration="0:0:0.4" />
+                                        <ColorAnimation Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="#e99595" Duration="0:0:0.4" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="CloseLoaded">
+                                    <Storyboard>
+                                        <ThicknessAnimation Storyboard.TargetName="yuan" Storyboard.TargetProperty="(Margin)" To="2,2,23,2" Duration="0:0:0" />
+                                        <ColorAnimation Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="#e99595" Duration="0:0:0" />
+                                    </Storyboard>
+                                </VisualState>
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Metro:MetroTextBlock x:Name="title" Text="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="{TemplateBinding TextHorizontalAlignment}" Opacity="0.65" />
+                        <Border x:Name="back" Grid.Column="2" CornerRadius="{TemplateBinding BorderCornerRadius}" Background="#e99595" />
+                        <Border x:Name="backFalse" Grid.Column="2" CornerRadius="{TemplateBinding BorderCornerRadius}" />
+                        <Border x:Name="yuan" Grid.Column="2" Background="#ffffff" CornerRadius="{TemplateBinding CornerRadius}" Margin="2" />
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsEnabled" Value="false">
+                            <Setter Property="Opacity" TargetName="title" Value="0.35" />
+                            <Setter Property="Opacity" TargetName="back" Value="0" />
+                            <Setter Property="Background" TargetName="backFalse" Value="#d7d7d7" />
+                        </Trigger>
+                        <Trigger Property="Content" Value="{x:Null}">
+                            <Setter Property="Width" TargetName="width2" Value="0" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 26 - 0
Arthas-WPFUI/Arthas/Controls/MetroTabControl.cs

@@ -0,0 +1,26 @@
+using Arthas.Utility.Element;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroTabControl : TabControl
+    {
+        void SelectionState()
+        {
+            ElementBase.GoToState(this, "SelectionStart");
+            ElementBase.GoToState(this, "SelectionEnd");
+        }
+
+        public MetroTabControl()
+        {
+            Loaded += delegate { ElementBase.GoToState(this, "SelectionLoaded"); };
+            SelectionChanged += delegate (object sender, SelectionChangedEventArgs e) { if (e.Source is MetroTabControl) { SelectionState(); } };
+            Utility.Refresh(this);
+        }
+
+        static MetroTabControl()
+        {
+            ElementBase.DefaultStyle<MetroTabControl>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 69 - 0
Arthas-WPFUI/Arthas/Controls/MetroTabControl.xaml

@@ -0,0 +1,69 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls"
+                    xmlns:Converter="clr-namespace:Arthas.Controls.Converter">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Converter:DoubleToThickness x:Key="DoubleToThickness" />
+
+    <Style TargetType="{x:Type Metro:MetroTabControl}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="SelectedIndex" Value="0" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroTabControl}">
+                    <Grid ClipToBounds="true" Background="#00000000" KeyboardNavigation.TabNavigation="Local">
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="Auto" />
+                            <RowDefinition />
+                        </Grid.RowDefinitions>
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup>
+                                <VisualState x:Name="SelectionStart" />
+                                <VisualState x:Name="SelectionEnd">
+                                    <Storyboard>
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="0,20,0,-20" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.0" />
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0.2" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.2" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="SelectionLoaded">
+                                    <Storyboard>
+                                        <ThicknessAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(Margin)" To="0" Duration="0:0:0" />
+                                        <DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0" />
+                                    </Storyboard>
+                                </VisualState>
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <!-- 标题栏模糊效果,自带滚动条(如果内容不需要滚动的时候就用不了了) -->
+                        <!--
+                        <Border x:Name="contentPanel" Grid.RowSpan="2" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
+                            <Metro:MetroScrollViewer x:Name="content" VerticalMargin="{Binding ActualHeight,ElementName=headerPanel,Converter={StaticResource DoubleToThickness},ConverterParameter=Top}">
+                                <Grid Margin="{Binding ActualHeight,ElementName=headerPanel,Converter={StaticResource DoubleToThickness},ConverterParameter=Top}">
+                                    <ContentPresenter ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" />
+                                </Grid>
+                            </Metro:MetroScrollViewer>
+                        </Border>
+                        -->
+                        <!-- 正常模式 -->
+                        <Border x:Name="contentPanel" Grid.Row="1" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
+                            <ContentPresenter x:Name="content" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" />
+                        </Border>
+                        <Rectangle Fill="#f3f3f3" />
+                        <!--
+                        <Metro:MetroVisualElement Visual="{Binding ElementName=contentPanel}" VisualOpacity="0.5" VisualBlurRadius="30" ClipToBounds="True" />
+                        -->
+                        <Rectangle Height="1" Fill="#000000" Opacity="0.1" VerticalAlignment="Bottom" />
+                        <Rectangle Fill="#ffffff" Opacity="0.5" Margin="0,0,0,1" />
+                        <TabPanel x:Name="headerPanel" IsItemsHost="true" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1" Margin="10,0" />
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 19 - 0
Arthas-WPFUI/Arthas/Controls/MetroTabItem.cs

@@ -0,0 +1,19 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroTabItem : TabItem
+    {
+        public static readonly DependencyProperty IconProperty = ElementBase.Property<MetroTabItem, ImageSource>(nameof(IconProperty), null);
+
+        public ImageSource Icon { get { return (ImageSource)GetValue(IconProperty); } set { SetValue(IconProperty, value); } }
+
+        static MetroTabItem()
+        {
+            ElementBase.DefaultStyle<MetroTabItem>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 59 - 0
Arthas-WPFUI/Arthas/Controls/MetroTabItem.xaml

@@ -0,0 +1,59 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroTabItem}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="Margin" Value="-1,0,0,0" />
+        <Setter Property="MinWidth" Value="80" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroTabItem}">
+                    <Grid Height="38" Background="#00000000">
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal" />
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="#f3f3f3" Duration="0:0:0.1" />
+                                        <ThicknessAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="(Margin)" To="0,7,0,0" Duration="0:0:0.1" />
+                                        <ThicknessAnimation Storyboard.TargetName="border1" Storyboard.TargetProperty="(Margin)" To="0,0,0,-1" Duration="0:0:0.1" />
+                                        <DoubleAnimation Storyboard.TargetName="title" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.65" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed" />
+                                <VisualState x:Name="Disabled" />
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Border x:Name="border" Margin="0,13,0,1" Background="#e7e7e7" BorderThickness="1,1,1,0" BorderBrush="#dadada">
+                            <Grid x:Name="border1" HorizontalAlignment="Center">
+                                <Grid.ColumnDefinitions>
+                                    <ColumnDefinition x:Name="iconWidth" Width="Auto" />
+                                    <ColumnDefinition Width="Auto" />
+                                </Grid.ColumnDefinitions>
+                                <Image x:Name="icon" Grid.Column="0" Width="12" Height="12" Margin="10,0,-5,0" VerticalAlignment="Center" Source="{TemplateBinding Icon}" Opacity="0.7" />
+                                <Metro:MetroTextBlock x:Name="title" Grid.Column="1" Text="{TemplateBinding Header}" VerticalAlignment="Center" Margin="10,0" Opacity="0.5" />
+                            </Grid>
+                        </Border>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="Selector.IsSelected" Value="True">
+                            <Setter Property="Background" TargetName="border" Value="#f3f3f3" />
+                            <Setter Property="Margin" TargetName="border" Value="0,7,0,0" />
+                            <Setter Property="Margin" TargetName="border1" Value="0,0,0,-1" />
+                            <Setter Property="Opacity" TargetName="title" Value="0.65" />
+                            <Setter Property="Opacity" TargetName="icon" Value="1" />
+                        </Trigger>
+                        <Trigger Property="Icon" Value="{x:Null}">
+                            <Setter Property="Width" TargetName="iconWidth" Value="0" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 30 - 0
Arthas-WPFUI/Arthas/Controls/MetroTextBlock.cs

@@ -0,0 +1,30 @@
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    /*
+    public class MetroTextBlock : ContentControl
+    {
+        public static readonly DependencyProperty SpacingProperty = ElementBase.Property<MetroTextBlock, Thickness>(nameof(SpacingProperty), new Thickness(0.25));
+        public Thickness Spacing
+        {
+            get { return (Thickness)GetValue(SpacingProperty); }
+            set { SetValue(SpacingProperty, value); }
+        }
+        public static readonly DependencyProperty TextProperty = ElementBase.Property<MetroTextBlock, string>(nameof(TextProperty), "");
+        public string Text
+        {
+            get { return (string)GetValue(TextProperty); }
+            set { SetValue(TextProperty, value); }
+        }
+        static MetroTextBlock()
+        {
+            ElementBase.DefaultStyle<MetroTextBlock>(DefaultStyleKeyProperty);
+        }
+    }
+    */
+
+    public class MetroTextBlock : TextBlock
+    {
+    }
+}

+ 42 - 0
Arthas-WPFUI/Arthas/Controls/MetroTextBlock.xaml

@@ -0,0 +1,42 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <!--
+    <Style TargetType="{x:Type Metro:MetroTextBlock}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="Foreground" Value="#FF000000" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroTextBlock}">
+                    <Grid>
+                        <ItemsControl x:Name="content" ItemsSource="{TemplateBinding Text}" Padding="{TemplateBinding Spacing}">
+                            <ItemsControl.ItemsPanel>
+                                <ItemsPanelTemplate>
+                                    <WrapPanel />
+                                </ItemsPanelTemplate>
+                            </ItemsControl.ItemsPanel>
+                            <ItemsControl.ItemTemplate>
+                                <DataTemplate>
+                                    <Border Margin="{Binding Padding,ElementName=content}">
+                                        <ContentPresenter Content="{Binding}" Margin="0,0,0,0" />
+                                    </Border>
+                                </DataTemplate>
+                            </ItemsControl.ItemTemplate>
+                        </ItemsControl>
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    -->
+    <Style TargetType="{x:Type Metro:MetroTextBlock}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="Foreground" Value="#FF000000" />
+    </Style>
+</ResourceDictionary>

+ 64 - 0
Arthas-WPFUI/Arthas/Controls/MetroTextBox.cs

@@ -0,0 +1,64 @@
+using Arthas.Utility.Element;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroTextBox : TextBox
+    {
+        public static readonly DependencyProperty TitleProperty = ElementBase.Property<MetroTextBox, string>(nameof(TitleProperty), "");
+        public static readonly DependencyProperty TitleMinWidthProperty = ElementBase.Property<MetroTextBox, double>(nameof(TitleMinWidthProperty));
+        public static readonly DependencyProperty TitleForegroundProperty = ElementBase.Property<MetroTextBox, Brush>(nameof(TitleForegroundProperty));
+        public static readonly DependencyProperty MouseMoveBackgroundProperty = ElementBase.Property<MetroTextBox, Brush>(nameof(MouseMoveBackgroundProperty));
+        public static readonly DependencyProperty InputHintProperty = ElementBase.Property<MetroTextBox, string>(nameof(InputHintProperty), "");
+        public static readonly DependencyProperty PopupHintProperty = ElementBase.Property<MetroTextBox, string>(nameof(PopupHintProperty), "");
+        public static readonly DependencyProperty ButtonTitleProperty = ElementBase.Property<MetroTextBox, string>(nameof(ButtonTitleProperty), "");
+        public static readonly DependencyProperty IconProperty = ElementBase.Property<MetroTextBox, ImageSource>(nameof(IconProperty), null);
+        public static readonly DependencyProperty StateProperty = ElementBase.Property<MetroTextBox, string>(nameof(StateProperty), "");
+        public static readonly DependencyProperty MultipleLineProperty = ElementBase.Property<MetroTextBox, bool>(nameof(MultipleLineProperty), false);
+        public static readonly DependencyProperty IsPassWordBoxProperty = ElementBase.Property<MetroTextBox, bool>(nameof(IsPassWordBoxProperty), false);
+        public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property<MetroTextBox, CornerRadius>(nameof(CornerRadiusProperty));
+
+        public static RoutedUICommand ButtonClickCommand = ElementBase.Command<MetroTextBox>(nameof(ButtonClickCommand));
+
+        public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } }
+        public double TitleMinWidth { get { return (double)GetValue(TitleMinWidthProperty); } set { SetValue(TitleMinWidthProperty, value); } }
+        public Brush TitleForeground { get { return (Brush)GetValue(TitleForegroundProperty); } set { SetValue(TitleForegroundProperty, value); } }
+        public Brush MouseMoveBackground { get { return (Brush)GetValue(MouseMoveBackgroundProperty); } set { SetValue(MouseMoveBackgroundProperty, value); } }
+        public string InputHint { get { return (string)GetValue(InputHintProperty); } set { SetValue(InputHintProperty, value); } }
+        public string PopupHint { get { return (string)GetValue(PopupHintProperty); } set { SetValue(PopupHintProperty, value); } }
+        public string ButtonTitle { get { return (string)GetValue(ButtonTitleProperty); } set { SetValue(ButtonTitleProperty, value); } }
+        public ImageSource Icon { get { return (ImageSource)GetValue(IconProperty); } set { SetValue(IconProperty, value); } }
+        public string State { get { return (string)GetValue(StateProperty); } set { SetValue(StateProperty, value); } }
+        public bool MultipleLine { get { return (bool)GetValue(MultipleLineProperty); } set { SetValue(MultipleLineProperty, value); } }
+        public bool IsPassWordBox { get { return (bool)GetValue(IsPassWordBoxProperty); } set { SetValue(IsPassWordBoxProperty, value); } }
+        public CornerRadius CornerRadius { get { return (CornerRadius)GetValue(CornerRadiusProperty); } set { SetValue(CornerRadiusProperty, value); } }
+
+        public Func<string, bool> ErrorCheckAction { get; set; }
+
+        public event EventHandler ButtonClick;
+
+        public MetroTextBox()
+        {
+            ContextMenu = null;
+            Loaded += delegate { ErrorCheck(); };
+            TextChanged += delegate { ErrorCheck(); };
+            CommandBindings.Add(new CommandBinding(ButtonClickCommand, delegate { if (ButtonClick != null) { ButtonClick(this, null); } }));
+            Utility.Refresh(this);
+        }
+
+        void ErrorCheck()
+        {
+            // if (PopupHint == null || PopupHint == "") { PopupHint = InputHint; }
+            if (ErrorCheckAction != null) { State = ErrorCheckAction(Text) ? "true" : "false"; }
+        }
+
+        static MetroTextBox()
+        {
+            ElementBase.DefaultStyle<MetroTextBox>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 178 - 0
Arthas-WPFUI/Arthas/Controls/MetroTextBox.xaml

@@ -0,0 +1,178 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls"
+                    xmlns:Converter="clr-namespace:Arthas.Controls.Converter">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Converter:StringToVisibility x:Key="StringToVisibility" />
+
+    <Style x:Key="buttonStyle" TargetType="{x:Type Button}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Button}">
+                    <Grid>
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal" />
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="title" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.9" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="title" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.5" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Disabled" />
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <TextBlock x:Name="title" Text="{TemplateBinding Content}" Opacity="0.65" VerticalAlignment="Center" Margin="8,0" />
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
+    <Style TargetType="{x:Type Metro:MetroTextBox}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="AcceptsReturn" Value="False" />
+        <Setter Property="TextWrapping" Value="NoWrap" />
+
+        <Setter Property="Background" Value="#FFFFFFFF" />
+        <Setter Property="MouseMoveBackground" Value="#FFFFFFFF" />
+        <Setter Property="BorderBrush" Value="{StaticResource Brush}" />
+        <Setter Property="Foreground" Value="#A5000000" />
+        <Setter Property="TitleForeground" Value="#A5000000" />
+        <Setter Property="TitleMinWidth" Value="80" />
+        <Setter Property="BorderThickness" Value="1" />
+        <Setter Property="CornerRadius" Value="2" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroTextBox}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition MinWidth="{TemplateBinding TitleMinWidth}" Width="Auto" x:Name="titleWidth1" />
+                            <ColumnDefinition Width="10" x:Name="titleWidth2" />
+                            <ColumnDefinition />
+                        </Grid.ColumnDefinitions>
+                        <Metro:MetroTextBlock x:Name="title" Grid.Column="0" Foreground="{TemplateBinding TitleForeground}" Text="{TemplateBinding Title}" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,6" />
+                        <Border x:Name="back" Grid.Column="2" CornerRadius="{TemplateBinding CornerRadius}" Background="{TemplateBinding Background}">
+                            <Grid>
+                                <Border x:Name="border" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="#FF000000" Opacity="0.15" />
+                                <Border x:Name="bordermove" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="{TemplateBinding BorderBrush}" Opacity="0" />
+                                <Border x:Name="bordertrue" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="#FF99cb8a" Visibility="Hidden" />
+                                <Border x:Name="borderfalse" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="#FFe99595" Visibility="Hidden" />
+                                <Grid x:Name="content">
+                                    <Grid.ColumnDefinitions>
+                                        <ColumnDefinition Width="Auto" x:Name="iconWidth" />
+                                        <ColumnDefinition />
+                                        <ColumnDefinition Width="Auto" x:Name="buttonWidth1" />
+                                        <ColumnDefinition Width="Auto" x:Name="buttonWidth2" />
+                                    </Grid.ColumnDefinitions>
+                                    <Image Grid.Column="0" Width="16" Height="16" Margin="6,6,0,6" Source="{TemplateBinding Icon}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
+                                    <Grid x:Name="hideInputHint" Opacity="0" Grid.Column="1">
+                                        <Metro:MetroTextBlock x:Name="inputHint" Margin="6,5,5,5" Foreground="{TemplateBinding Foreground}" Text="{TemplateBinding InputHint}" HorizontalAlignment="Left" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0" IsHitTestVisible="False" />
+                                    </Grid>
+                                    <ScrollViewer Grid.Column="1" x:Name="PART_ContentHost" Margin="5" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
+
+                                    <Rectangle Grid.Column="2" Width="1" Height="11" Margin="5,9,0,0" Fill="#FF000000" Opacity="0.15" VerticalAlignment="Top" />
+                                    <Button x:Name="button" Focusable="False" Grid.Column="3" Content="{TemplateBinding ButtonTitle}" Margin="0,6" Style="{StaticResource buttonStyle}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Command="Metro:MetroTextBox.ButtonClickCommand" />
+                                </Grid>
+                            </Grid>
+                        </Border>
+                        <Popup x:Name="popupHint" PlacementTarget="{Binding ElementName=PART_ContentHost}" AllowsTransparency="True" Focusable="False" Placement="RelativePoint" VerticalOffset="-42" HorizontalOffset="-14" PopupAnimation="Fade">
+                            <Grid>
+                                <StackPanel Visibility="{TemplateBinding PopupHint, Converter={StaticResource StringToVisibility}}">
+                                    <Border x:Name="popupborder" CornerRadius="2" Background="{TemplateBinding BorderBrush}">
+                                        <Metro:MetroTextBlock x:Name="popupText" Text="{TemplateBinding PopupHint}" Margin="8,6" Foreground="#FFFFFFFF" HorizontalAlignment="Center" VerticalAlignment="Center" />
+                                    </Border>
+                                    <Polygon x:Name="popuppolygon" Points="0,0 10,0 5,5 0,0" Fill="{TemplateBinding BorderBrush}" Margin="10,0,0,0" />
+                                </StackPanel>
+                            </Grid>
+                        </Popup>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsEnabled" Value="false">
+                            <Setter Property="Opacity" TargetName="content" Value="0.5" />
+                            <Setter Property="Opacity" TargetName="title" Value="0.35" />
+                            <Setter Property="Background" TargetName="back" Value="#FFFAFAFA" />
+                            <Setter Property="Opacity" TargetName="inputHint" Value="0.5" />
+                        </Trigger>
+                        <Trigger Property="IsMouseOver" Value="true">
+                            <Setter Property="Opacity" TargetName="border" Value="0" />
+                            <Setter Property="Opacity" TargetName="bordermove" Value="1" />
+                            <Setter Property="BorderBrush" TargetName="bordertrue" Value="#ff6fae5f" />
+                            <Setter Property="BorderBrush" TargetName="borderfalse" Value="#ffe67979" />
+
+                            <Setter Property="Background" TargetName="back" Value="{Binding MouseMoveBackground, RelativeSource={RelativeSource TemplatedParent}}" />
+                        </Trigger>
+                        <Trigger Property="IsPassWordBox" Value="true">
+                            <Setter Property="Visibility" TargetName="PART_ContentHost" Value="Hidden" />
+                            <Setter Property="InputMethod.PreferredImeState" Value="Off" />
+                        </Trigger>
+                        <Trigger Property="MultipleLine" Value="true">
+                            <Setter Property="AcceptsReturn" Value="true" />
+                            <Setter Property="TextWrapping" Value="Wrap" />
+                        </Trigger>
+                        <Trigger Property="IsKeyboardFocused" Value="true">
+                            <Setter Property="Opacity" TargetName="border" Value="0" />
+                            <Setter Property="Opacity" TargetName="bordermove" Value="1" />
+                            <Setter Property="IsOpen" TargetName="popupHint" Value="true" />
+                            <Setter Property="BorderBrush" TargetName="bordertrue" Value="#ff6fae5f" />
+                            <Setter Property="BorderBrush" TargetName="borderfalse" Value="#ffe67979" />
+                            <Setter Property="Opacity" TargetName="inputHint" Value="0" />
+
+                            <Setter Property="Background" TargetName="back" Value="{Binding MouseMoveBackground, RelativeSource={RelativeSource TemplatedParent}}" />
+                        </Trigger>
+                        <Trigger Property="IsKeyboardFocused" Value="false">
+                            <Setter Property="IsOpen" TargetName="popupHint" Value="false" />
+                        </Trigger>
+                        <Trigger Property="Title" Value="">
+                            <Setter Property="MinWidth" TargetName="titleWidth1" Value="0" />
+                            <Setter Property="Width" TargetName="titleWidth2" Value="0" />
+                        </Trigger>
+                        <Trigger Property="Text" Value="">
+                            <Setter Property="Opacity" TargetName="hideInputHint" Value="1" />
+                        </Trigger>
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="Text" Value="" />
+                                <Condition Property="IsEnabled" Value="true" />
+                                <Condition Property="IsKeyboardFocused" Value="false" />
+                            </MultiTrigger.Conditions>
+                            <Setter Property="Opacity" TargetName="inputHint" Value="0.25" />
+                        </MultiTrigger>
+                        <Trigger Property="State" Value="true">
+                            <Setter Property="Visibility" TargetName="border" Value="Hidden" />
+                            <Setter Property="Visibility" TargetName="bordertrue" Value="Visible" />
+
+                            <Setter Property="Background" TargetName="popupborder" Value="#FF99cb8a" />
+                            <Setter Property="Fill" TargetName="popuppolygon" Value="#FF99cb8a" />
+                        </Trigger>
+                        <Trigger Property="State" Value="false">
+                            <Setter Property="Visibility" TargetName="border" Value="Hidden" />
+                            <Setter Property="Visibility" TargetName="borderfalse" Value="Visible" />
+
+                            <Setter Property="Background" TargetName="popupborder" Value="#FFe99595" />
+                            <Setter Property="Fill" TargetName="popuppolygon" Value="#FFe99595" />
+                        </Trigger>
+                        <Trigger Property="Icon" Value="{x:Null}">
+                            <Setter Property="Width" TargetName="iconWidth" Value="0" />
+                        </Trigger>
+                        <Trigger Property="ButtonTitle" Value="">
+                            <Setter Property="Width" TargetName="buttonWidth1" Value="0" />
+                            <Setter Property="Width" TargetName="buttonWidth2" Value="0" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 13 - 0
Arthas-WPFUI/Arthas/Controls/MetroTextButton.cs

@@ -0,0 +1,13 @@
+using Arthas.Utility.Element;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroTextButton : Button
+    {
+        static MetroTextButton()
+        {
+            ElementBase.DefaultStyle<MetroTextButton>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 48 - 0
Arthas-WPFUI/Arthas/Controls/MetroTextButton.xaml

@@ -0,0 +1,48 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroTextButton}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="Foreground" Value="#000000" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroTextButton}">
+                    <Grid Background="#00000000">
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="text" Storyboard.TargetProperty="(UIElement.Opacity)" To="1" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="text" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.8" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="text" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.5" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Disabled" />
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Metro:MetroTextBlock x:Name="text" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" />
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsEnabled" Value="false">
+                            <Setter Property="Opacity" Value="0.5" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 66 - 0
Arthas-WPFUI/Arthas/Controls/MetroThumb.cs

@@ -0,0 +1,66 @@
+using Arthas.Utility.Element;
+using System;
+using System.Windows;
+using System.Windows.Controls.Primitives;
+
+namespace Arthas.Controls
+{
+    public class MetroThumb : Thumb
+    {
+        public double OldX { get; set; } = 0.0;
+        public double OldY { get; set; } = 0.0;
+        public double OffsetX { get; set; } = 0.0;
+        public double OffsetY { get; set; } = 0.0;
+
+        public static readonly DependencyProperty XProperty = ElementBase.Property<MetroThumb, double>(nameof(XProperty), -1);
+        public static readonly DependencyProperty YProperty = ElementBase.Property<MetroThumb, double>(nameof(YProperty), -1);
+
+        public double X { get { return (double)GetValue(XProperty) - OffsetX; } set { SetValue(XProperty, value + OffsetX); Change(); } }
+        public double Y { get { return (double)GetValue(YProperty) - OffsetY; } set { SetValue(YProperty, value + OffsetY); Change(); } }
+
+        public event EventHandler ValueChange;
+
+        public MetroThumb()
+        {
+            Focusable = true;
+            FocusVisualStyle = null;
+
+            Loaded += delegate
+            {
+                X = (double)GetValue(XProperty) == -1 ? 0 : X;
+                Y = (double)GetValue(YProperty) == -1 ? 0 : Y;
+            };
+            DragStarted += delegate (object sender, DragStartedEventArgs e)
+            {
+                Focus();
+
+                OldX = e.HorizontalOffset;
+                OldY = e.VerticalOffset;
+
+                X = OldX;
+                Y = OldY;
+            };
+            DragDelta += delegate (object sender, DragDeltaEventArgs e)
+            {
+                double x = OldX + e.HorizontalChange;
+                double y = OldY + e.VerticalChange;
+
+                if (x < 0) X = 0;
+                else if (x > ActualWidth) X = ActualWidth;
+                else X = x;
+
+                if (y < 0) Y = 0;
+                else if (y > ActualHeight) Y = ActualHeight;
+                else Y = y;
+            };
+        }
+
+        public double XPercent { get { return X / ActualWidth; } set { X = ActualWidth * value; } }
+        public double YPercent { get { return Y / ActualHeight; } set { Y = ActualHeight * value; } }
+
+        void Change()
+        {
+            if (ValueChange != null) { ValueChange(this, null); }
+        }
+    }
+}

+ 18 - 0
Arthas-WPFUI/Arthas/Controls/MetroTitleMenu.cs

@@ -0,0 +1,18 @@
+using Arthas.Utility.Element;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroTitleMenu : Menu
+    {
+        public MetroTitleMenu()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroTitleMenu()
+        {
+            ElementBase.DefaultStyle<MetroTitleMenu>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 28 - 0
Arthas-WPFUI/Arthas/Controls/MetroTitleMenu.xaml

@@ -0,0 +1,28 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroTitleMenu}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="VerticalAlignment" Value="Top" />
+        <Setter Property="Margin" Value="0,-32,120,0" />
+        <Setter Property="Height" Value="32" />
+        <Setter Property="Background" Value="{StaticResource Brush}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroTitleMenu}">
+                    <Grid Background="#ffffff">
+                        <Grid Background="{TemplateBinding Background}" ClipToBounds="True">
+                            <ItemsPresenter HorizontalAlignment="Right" />
+                        </Grid>
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 24 - 0
Arthas-WPFUI/Arthas/Controls/MetroTitleMenuItem.cs

@@ -0,0 +1,24 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroTitleMenuItem : MenuItem
+    {
+        public static readonly new DependencyProperty IconProperty = ElementBase.Property<MetroTitleMenuItem, ImageSource>(nameof(IconProperty), null);
+
+        public new ImageSource Icon { get { return (ImageSource)GetValue(IconProperty); } set { SetValue(IconProperty, value); } }
+
+        public MetroTitleMenuItem()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroTitleMenuItem()
+        {
+            ElementBase.DefaultStyle<MetroTitleMenuItem>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 82 - 0
Arthas-WPFUI/Arthas/Controls/MetroTitleMenuItem.xaml

@@ -0,0 +1,82 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
+                    xmlns:Metro="clr-namespace:Arthas.Controls"
+                    xmlns:Converter="clr-namespace:Arthas.Controls.Converter">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroTitleMenuItem}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="Height" Value="32" />
+        <Setter Property="Background" Value="{StaticResource Brush}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroTitleMenuItem}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" />
+                            <ColumnDefinition Width="0" />
+                        </Grid.ColumnDefinitions>
+                        <Rectangle x:Name="backRectangle" Fill="#ffffff" Opacity="0" />
+                        <Grid x:Name="title" Background="#00000000" VerticalAlignment="Center" Shell:WindowChrome.IsHitTestVisibleInChrome="True">
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="Auto" x:Name="iconWidth" />
+                                <ColumnDefinition Width="Auto" />
+                                <ColumnDefinition Width="0" x:Name="subWidth" />
+                            </Grid.ColumnDefinitions>
+                            <Image x:Name="icon" Source="{TemplateBinding Icon}" Width="12" Height="12" Margin="10,0,0,0" />
+                            <Metro:MetroTextBlock Grid.Column="1" Text="{TemplateBinding Header}" Foreground="#ffffff" Margin="10,0" />
+                            <Polyline Grid.Column="2" Points="0,0 5,5 10,0" Stroke="#ffffff" VerticalAlignment="Center"  Margin="0,0,10,0" />
+                        </Grid>
+                        <Rectangle Grid.Column="3" Fill="#ffffff" Opacity="0.2" Height="12" />
+                        <Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" HorizontalOffset="-20" VerticalOffset="-10" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="Fade" Placement="Bottom">
+                            <Grid RenderOptions.ClearTypeHint="Enabled" Background="#00000000">
+                                <Border Grid.Row="1" BorderBrush="#99FFFFFF" BorderThickness="1" Background="{TemplateBinding Background}" CornerRadius="3" Margin="20">
+                                    <Border.Effect>
+                                        <DropShadowEffect BlurRadius="20" Direction="0" Opacity="0.2" ShadowDepth="0" />
+                                    </Border.Effect>
+                                    <Grid>
+                                        <Polyline HorizontalAlignment="Left" Points="0,5 5,0 10,5" Fill="{TemplateBinding Background}" Margin="10,-5,0,0" />
+                                        <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="True" KeyboardNavigation.TabNavigation="Cycle" />
+                                    </Grid>
+                                </Border>
+                            </Grid>
+                        </Popup>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="Icon" Value="{x:Null}">
+                            <Setter TargetName="iconWidth" Property="Width" Value="0" />
+                        </Trigger>
+                        <Trigger Property="IsEnabled" Value="False">
+                            <Setter TargetName="icon" Property="Opacity" Value="0.5" />
+                            <Setter TargetName="title" Property="Opacity" Value="0.5" />
+                        </Trigger>
+                        <Trigger Property="Role" Value="TopLevelHeader">
+                            <Setter TargetName="subWidth" Property="Width" Value="Auto" />
+                        </Trigger>
+                        <Trigger Property="IsMouseOver" Value="True">
+                            <Trigger.EnterActions>
+                                <BeginStoryboard>
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="backRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.15" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </BeginStoryboard>
+                            </Trigger.EnterActions>
+                            <Trigger.ExitActions>
+                                <BeginStoryboard>
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="backRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </BeginStoryboard>
+                            </Trigger.ExitActions>
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 32 - 0
Arthas-WPFUI/Arthas/Controls/MetroVisualElement.cs

@@ -0,0 +1,32 @@
+using Arthas.Utility.Element;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroVisualElement : ContentControl
+    {
+        public static readonly DependencyProperty VisualProperty = ElementBase.Property<MetroVisualElement, Visual>(nameof(VisualProperty));
+        public static readonly DependencyProperty VisualOpacityProperty = ElementBase.Property<MetroVisualElement, double>(nameof(VisualOpacityProperty));
+        public static readonly DependencyProperty VisualBlurRadiusProperty = ElementBase.Property<MetroVisualElement, double>(nameof(VisualBlurRadiusProperty));
+        public static readonly DependencyProperty LeftProperty = ElementBase.Property<MetroVisualElement, double>(nameof(LeftProperty));
+        public static readonly DependencyProperty TopProperty = ElementBase.Property<MetroVisualElement, double>(nameof(TopProperty));
+
+        public Visual Visual { get { return (Visual)GetValue(VisualProperty); } set { SetValue(VisualProperty, value); } }
+        public new double VisualOpacity { get { return (double)GetValue(VisualOpacityProperty); } set { SetValue(VisualOpacityProperty, value); } }
+        public double VisualBlurRadius { get { return (double)GetValue(VisualBlurRadiusProperty); } set { SetValue(VisualBlurRadiusProperty, value); } }
+        public double Left { get { return (double)GetValue(LeftProperty); } set { SetValue(LeftProperty, value); } }
+        public double Top { get { return (double)GetValue(TopProperty); } set { SetValue(TopProperty, value); } }
+
+        public MetroVisualElement()
+        {
+            Utility.Refresh(this);
+        }
+
+        static MetroVisualElement()
+        {
+            ElementBase.DefaultStyle<MetroVisualElement>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 36 - 0
Arthas-WPFUI/Arthas/Controls/MetroVisualElement.xaml

@@ -0,0 +1,36 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroVisualElement}">
+
+        <Setter Property="IsHitTestVisible" Value="False" />
+        <Setter Property="ClipToBounds" Value="False" />
+
+        <Setter Property="Background" Value="#00000000" />
+        <Setter Property="VisualOpacity" Value="1" />
+        <Setter Property="VisualBlurRadius" Value="0" />
+        <Setter Property="Left" Value="0" />
+        <Setter Property="Top" Value="0" />
+
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroVisualElement}">
+                    <Canvas Background="{TemplateBinding Background}">
+                        <Rectangle Opacity="{TemplateBinding VisualOpacity}" Canvas.Left="{TemplateBinding Left}" Canvas.Top="{TemplateBinding Top}" Width="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}" Height="{Binding ActualHeight, RelativeSource={RelativeSource TemplatedParent}}">
+                            <Rectangle.Fill>
+                                <VisualBrush Visual="{Binding Visual, RelativeSource={RelativeSource TemplatedParent}}" AlignmentX="Left" AlignmentY="Top" Stretch="None" />
+                            </Rectangle.Fill>
+                            <Rectangle.Effect>
+                                <BlurEffect Radius="{Binding VisualBlurRadius, RelativeSource={RelativeSource TemplatedParent}}" />
+                            </Rectangle.Effect>
+                        </Rectangle>
+                    </Canvas>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 144 - 0
Arthas-WPFUI/Arthas/Controls/MetroWaterfallFlow.cs

@@ -0,0 +1,144 @@
+using Arthas.Utility.Element;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Arthas.Controls
+{
+    public class MetroWaterfallFlow : Canvas
+    {
+        int column;
+        double listWidth = 180;
+        public double ListWidth { get { return listWidth; } set { listWidth = value; SetColumn(); } }
+
+        static MetroWaterfallFlow()
+        {
+            ElementBase.DefaultStyle<MetroWaterfallFlow>(DefaultStyleKeyProperty);
+        }
+
+        public MetroWaterfallFlow()
+        {
+            Loaded += delegate
+            {
+                SetColumn();
+                Margin = new Thickness(Margin.Left);
+            };
+            SizeChanged += delegate
+            {
+                SetColumn();
+            };
+        }
+
+        void SetColumn()
+        {
+            // MinWidth = listWidth + Margin.Left * 4;
+            column = (int)(ActualWidth / listWidth);
+            if (column <= 0) column = 1;
+            Refresh();
+        }
+
+        public void Add(FrameworkElement element)
+        {
+            element.Width = ListWidth;
+            if (element is Grid)
+            {
+                if ((element as Grid).Children.Count > 0)
+                {
+                    ((element as Grid).Children[0] as FrameworkElement).Margin = new Thickness(Margin.Left);
+                }
+            }
+            Children.Add(element);
+            Refresh();
+        }
+
+        public class Point
+        {
+            public int Index { get; set; }
+            public double Buttom { get; set; }
+            public double Height { get; set; }
+
+            public Point(int index, double height, double buttom)
+            {
+                Index = index; Height = height; Buttom = buttom;
+            }
+        }
+
+        public void Refresh()
+        {
+            // 初始化参数
+            var maxHeight = 0.0;
+            var list = new Dictionary<int, Point>();
+            var nlist = new Dictionary<int, Dictionary<int, Point>>();
+            for (int i = 0; i < Children.Count; i++)
+            {
+                (Children[i] as FrameworkElement).UpdateLayout();
+                list.Add(i, new Point(i, (Children[i] as FrameworkElement).ActualHeight, 0.0));
+            }
+            for (int i = 0; i < column; i++)
+            {
+                nlist.Add(i, new Dictionary<int, Point>());
+            }
+
+            // 智能排序到 nlist
+            for (int i = 0; i < list.Count; i++)
+            {
+                if (i < column)
+                {
+                    list[i].Buttom = list[i].Height;
+                    nlist[i].Add(nlist[i].Count, list[i]);
+                }
+                else
+                {
+                    var b = 0.0;
+                    var l = 0;
+                    for (int j = 0; j < column; j++)
+                    {
+                        var jh = nlist[j][nlist[j].Count - 1].Buttom + list[i].Height;
+                        if (b == 0.0 || jh < b)
+                        {
+                            b = jh;
+                            l = j;
+                        }
+                    }
+                    list[i].Buttom = b;
+                    nlist[l].Add(nlist[l].Count, list[i]);
+                }
+            }
+
+            // 开始布局
+            for (int i = 0; i < nlist.Count; i++)
+            {
+                for (int j = 0; j < nlist[i].Count; j++)
+                {
+                    Children[nlist[i][j].Index].SetValue(LeftProperty, i * ActualWidth / column);
+                    Children[nlist[i][j].Index].SetValue(TopProperty, nlist[i][j].Buttom - nlist[i][j].Height);
+                    Children[nlist[i][j].Index].SetValue(WidthProperty, ActualWidth / column);
+
+                    if (Children[nlist[i][j].Index] is Grid)
+                    {
+                        ((Children[nlist[i][j].Index] as Grid).Children[0] as FrameworkElement).Margin = Margin;
+                    }
+                }
+
+                // 不知道为什么如果不写这么一句会出错
+                if (nlist.ContainsKey(i))
+                {
+                    if (nlist[i].ContainsKey(nlist[i].Count - 1))
+                    {
+                        var mh = nlist[i][nlist[i].Count - 1].Buttom;
+                        maxHeight = mh > maxHeight ? mh : maxHeight;
+                    }
+                }
+            }
+            Height = maxHeight;
+            list.Clear();
+            nlist.Clear();
+        }
+
+        public void Remove(UIElement element)
+        {
+            Children.Remove(element);
+            Refresh();
+        }
+    }
+}

+ 15 - 0
Arthas-WPFUI/Arthas/Controls/MetroWaterfallFlow.xaml

@@ -0,0 +1,15 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Metro="clr-namespace:Arthas.Controls">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style TargetType="{x:Type Metro:MetroWaterfallFlow}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+        <Setter Property="HorizontalAlignment" Value="Stretch" />
+        <Setter Property="VerticalAlignment" Value="Top" />
+        <Setter Property="Margin" Value="5" />
+    </Style>
+</ResourceDictionary>

+ 91 - 0
Arthas-WPFUI/Arthas/Controls/MetroWindow.cs

@@ -0,0 +1,91 @@
+using Arthas.Themes;
+using Arthas.Utility.Element;
+using System;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Arthas.Controls
+{
+    public class MetroWindow : Window
+    {
+        public static readonly DependencyProperty IsSubWindowShowProperty = ElementBase.Property<MetroWindow, bool>(nameof(IsSubWindowShowProperty), false);
+        public static readonly DependencyProperty MenuProperty = ElementBase.Property<MetroWindow, object>(nameof(MenuProperty), null);
+        public static readonly new DependencyProperty BorderBrushProperty = ElementBase.Property<MetroWindow, Brush>(nameof(BorderBrushProperty));
+        public static readonly DependencyProperty TitleForegroundProperty = ElementBase.Property<MetroWindow, Brush>(nameof(TitleForegroundProperty));
+
+        public bool IsSubWindowShow { get { return (bool)GetValue(IsSubWindowShowProperty); } set { SetValue(IsSubWindowShowProperty, value); GoToState(); } }
+        public object Menu { get { return GetValue(MenuProperty); } set { SetValue(MenuProperty, value); } }
+        public new Brush BorderBrush { get { return (Brush)GetValue(BorderBrushProperty); } set { SetValue(BorderBrushProperty, value); BorderBrushChange(value); } }
+        public Brush TitleForeground { get { return (Brush)GetValue(TitleForegroundProperty); } set { SetValue(TitleForegroundProperty, value); } }
+
+        void BorderBrushChange(Brush brush)
+        {
+            if (IsLoaded)
+            {
+                Theme.Switch(this);
+            }
+        }
+
+        void GoToState()
+        {
+            ElementBase.GoToState(this, IsSubWindowShow ? "Enabled" : "Disable");
+        }
+
+        public object ReturnValue { get; set; } = null;
+        public bool EscClose { get; set; } = false;
+
+        protected override void OnInitialized(EventArgs e)
+        {
+            base.OnInitialized(e);
+
+            WindowStartupLocation = WindowStartupLocation.CenterScreen;
+            AllowsTransparency = false;
+            if (WindowStyle == WindowStyle.None)
+            {
+                WindowStyle = WindowStyle.SingleBorderWindow;
+            }
+        }
+
+        public MetroWindow()
+        {
+            // 修复WindowChrome导致的窗口大小错误
+            var sizeToContent = SizeToContent.Manual;
+            Loaded += (ss, ee) =>
+            {
+                sizeToContent = SizeToContent;
+            };
+            ContentRendered += (ss, ee) =>
+            {
+                SizeToContent = SizeToContent.Manual;
+                Width = ActualWidth;
+                Height = ActualHeight;
+                SizeToContent = sizeToContent;
+            };
+
+            KeyUp += delegate (object sender, KeyEventArgs e)
+            {
+                if (e.Key == Key.Escape && EscClose)
+                {
+                    Close();
+                }
+            };
+            StateChanged += delegate
+              {
+                  if (ResizeMode == ResizeMode.CanMinimize || ResizeMode == ResizeMode.NoResize)
+                  {
+                      if (WindowState == WindowState.Maximized)
+                      {
+                          WindowState = WindowState.Normal;
+                      }
+                  }
+              };
+            Utility.Refresh(this);
+        }
+
+        static MetroWindow()
+        {
+            ElementBase.DefaultStyle<MetroWindow>(DefaultStyleKeyProperty);
+        }
+    }
+}

+ 209 - 0
Arthas-WPFUI/Arthas/Controls/MetroWindow.xaml

@@ -0,0 +1,209 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+                    xmlns:Shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
+                    xmlns:Metro="clr-namespace:Arthas.Controls"
+                    x:Class="Arthas.Themes.Metro.MetroWindow">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroBase.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+
+    <Style x:Key="buttonStyle" TargetType="{x:Type Button}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="Width" Value="40" />
+        <Setter Property="Height" Value="32" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Button}">
+                    <Grid>
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup x:Name="CommonStates">
+                                <VisualState x:Name="Normal">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="backRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="MouseOver">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="backRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.15" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Pressed">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="backRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.05" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Disabled" />
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Rectangle x:Name="backRectangle" Fill="{TemplateBinding Foreground}" Opacity="0" />
+                        <ContentPresenter />
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
+    <Style TargetType="{x:Type Metro:MetroWindow}">
+        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+        <Setter Property="SnapsToDevicePixels" Value="True" />
+
+        <Setter Property="Background" Value="#FFF3F3F3" />
+        <Setter Property="BorderBrush" Value="{StaticResource Brush}" />
+        <Setter Property="Foreground" Value="#FF000000" />
+        <Setter Property="TitleForeground" Value="#ffffff" />
+        <Setter Property="BorderThickness" Value="1" />
+
+        <Setter Property="FontSize" Value="12" />
+        <Setter Property="TextOptions.TextFormattingMode" Value="Display" />
+        <Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
+        <Setter Property="UseLayoutRounding" Value="True" />
+
+        <!--
+
+        相对的解决字体显示模糊的问题
+        <Setter Property="TextOptions.TextFormattingMode" Value="Display" />
+        <Setter Property="TextOptions.TextHintingMode" Value="Auto" />
+        <Setter Property="UseLayoutRounding" Value="True" />
+
+        位置会向下偏移一像素
+        <Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
+
+        清晰的字体,但是不好看
+        <Setter Property="FontFamily" Value="Arial,SimSun" />
+
+        -->
+
+        <Setter Property="Shell:WindowChrome.WindowChrome">
+            <Setter.Value>
+                <Shell:WindowChrome CaptionHeight="27" CornerRadius="5" GlassFrameThickness="-1" ResizeBorderThickness="5" UseAeroCaptionButtons="False" NonClientFrameEdges="None" />
+            </Setter.Value>
+        </Setter>
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Metro:MetroWindow}">
+                    <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
+                        <VisualStateManager.VisualStateGroups>
+                            <VisualStateGroup>
+                                <VisualState x:Name="Enabled">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="disableRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.5" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                                <VisualState x:Name="Disable">
+                                    <Storyboard>
+                                        <DoubleAnimation Storyboard.TargetName="disableRectangle" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" Duration="0:0:0.1" />
+                                    </Storyboard>
+                                </VisualState>
+                            </VisualStateGroup>
+                        </VisualStateManager.VisualStateGroups>
+                        <Grid Background="#ffffff">
+                            <Border BorderBrush="#000000" BorderThickness="{Binding BorderThickness,ElementName=border}" Margin="-1" Opacity="0.15" />
+                            <Grid x:Name="windowGrid" Background="{TemplateBinding BorderBrush}">
+                                <Grid.RowDefinitions>
+                                    <RowDefinition Height="32" />
+                                    <RowDefinition />
+                                </Grid.RowDefinitions>
+                                <Grid.ColumnDefinitions>
+                                    <ColumnDefinition x:Name="iconSize" Width="32" />
+                                    <ColumnDefinition Width="Auto" />
+                                    <ColumnDefinition />
+                                    <ColumnDefinition Width="Auto" />
+                                </Grid.ColumnDefinitions>
+                                <Grid Grid.Column="2">
+                                    <ContentPresenter Content="{TemplateBinding Menu}" Margin="0,32,-120,0" />
+                                </Grid>
+                                <Grid Grid.Row="1" Grid.ColumnSpan="4" Background="{TemplateBinding Background}">
+                                    <AdornerDecorator>
+                                        <ContentPresenter />
+                                    </AdornerDecorator>
+                                </Grid>
+                                <Grid Grid.Column="0">
+                                    <Metro:MetroImage Source="{TemplateBinding Icon}" />
+                                    <Rectangle Fill="{TemplateBinding TitleForeground}" Opacity="0.15" />
+                                </Grid>
+                                <Grid Grid.Column="1">
+                                    <Metro:MetroTextBlock Text="{TemplateBinding Title}"  Foreground="{TemplateBinding TitleForeground}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0" />
+                                </Grid>
+                                <Grid Grid.Column="3" Shell:WindowChrome.IsHitTestVisibleInChrome="True">
+                                    <Button x:Name="minimizedButton" Foreground="{TemplateBinding TitleForeground}" HorizontalAlignment="Right" Click="Minimized" Margin="0,0,80,0" Style="{StaticResource buttonStyle}">
+                                        <Button.Content>
+                                            <Grid VerticalAlignment="Center" HorizontalAlignment="Center">
+                                                <Rectangle Width="14" Height="1" Fill="{TemplateBinding TitleForeground}" Margin="0,6,0,0" />
+                                            </Grid>
+                                        </Button.Content>
+                                    </Button>
+                                    <Button x:Name="maximizedButton" Foreground="{TemplateBinding TitleForeground}" HorizontalAlignment="Right" Click="Maximized" Margin="0,0,40,0" Style="{StaticResource buttonStyle}">
+                                        <Button.Content>
+                                            <Grid VerticalAlignment="Center" HorizontalAlignment="Center">
+                                                <Rectangle Width="12" Height="12" Stroke="{TemplateBinding TitleForeground}" />
+                                            </Grid>
+                                        </Button.Content>
+                                    </Button>
+                                    <Button x:Name="normalButton" Foreground="{TemplateBinding TitleForeground}" HorizontalAlignment="Right" Click="Normal" Margin="0,0,40,0" Style="{StaticResource buttonStyle}">
+                                        <Button.Content>
+                                            <Grid VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,2,3,0">
+                                                <Rectangle Width="10" Height="10" Stroke="{TemplateBinding TitleForeground}" />
+                                                <Rectangle Width="10" Height="1" Fill="{TemplateBinding TitleForeground}" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,-4,-4,0" />
+                                                <Rectangle Width="3" Height="1" Fill="{TemplateBinding TitleForeground}" HorizontalAlignment="Right" Margin="0,5,-3,0" VerticalAlignment="Top" />
+                                                <Rectangle Width="1" Height="9" Fill="{TemplateBinding TitleForeground}" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,-3,-4,0" />
+                                                <Rectangle Width="1" Height="3" Fill="{TemplateBinding TitleForeground}" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,-3,5,0" />
+                                            </Grid>
+                                        </Button.Content>
+                                    </Button>
+                                    <Button x:Name="closeButton" Foreground="{TemplateBinding TitleForeground}" HorizontalAlignment="Right" Click="Close" Style="{StaticResource buttonStyle}">
+                                        <Button.Content>
+                                            <Grid VerticalAlignment="Center" HorizontalAlignment="Center">
+                                                <Rectangle Width="16" Height="1.2" Fill="{TemplateBinding TitleForeground}" RenderTransformOrigin="0.5,0.5">
+                                                    <Rectangle.RenderTransform>
+                                                        <TransformGroup>
+                                                            <RotateTransform Angle="45" />
+                                                        </TransformGroup>
+                                                    </Rectangle.RenderTransform>
+                                                </Rectangle>
+                                                <Rectangle Width="16" Height="1.2" Fill="{TemplateBinding TitleForeground}" RenderTransformOrigin="0.5,0.5">
+                                                    <Rectangle.RenderTransform>
+                                                        <TransformGroup>
+                                                            <RotateTransform Angle="-45" />
+                                                        </TransformGroup>
+                                                    </Rectangle.RenderTransform>
+                                                </Rectangle>
+                                            </Grid>
+                                        </Button.Content>
+                                    </Button>
+                                </Grid>
+                                <Rectangle x:Name="disableRectangle" Grid.RowSpan="2" Grid.ColumnSpan="4" Fill="#FF000000" Opacity="0" IsHitTestVisible="False" />
+                            </Grid>
+                        </Grid>
+                    </Border>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="ResizeMode" Value="NoResize">
+                            <Setter Property="Visibility" TargetName="minimizedButton" Value="Hidden" />
+                            <Setter Property="Visibility" TargetName="maximizedButton" Value="Hidden" />
+                            <Setter Property="Visibility" TargetName="normalButton" Value="Hidden" />
+                        </Trigger>
+                        <Trigger Property="ResizeMode" Value="CanMinimize">
+                            <Setter Property="Visibility" TargetName="maximizedButton" Value="Hidden" />
+                            <Setter Property="Visibility" TargetName="normalButton" Value="Hidden" />
+                            <Setter Property="Margin" TargetName="minimizedButton" Value="0,0,40,0" />
+                        </Trigger>
+                        <Trigger Property="WindowState" Value="Maximized">
+                            <Setter Property="Visibility" TargetName="maximizedButton" Value="Hidden" />
+                            <Setter Property="Margin" TargetName="windowGrid" Value="8" />
+                            <Setter TargetName="windowGrid" Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Shell:WindowChrome.WindowChrome).ResizeBorderThickness}" />
+                            <Setter Property="BorderThickness" TargetName="border" Value="0" />
+                        </Trigger>
+                        <Trigger Property="WindowState" Value="Normal">
+                            <Setter Property="Visibility" TargetName="normalButton" Value="Hidden" />
+                        </Trigger>
+                        <Trigger Property="Icon" Value="{x:Null}">
+                            <Setter Property="Width" TargetName="iconSize" Value="0" />
+                            <Setter Property="MinWidth" Value="120" />
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+</ResourceDictionary>

+ 27 - 0
Arthas-WPFUI/Arthas/Controls/MetroWindow.xaml.cs

@@ -0,0 +1,27 @@
+using System.Windows;
+
+namespace Arthas.Themes.Metro
+{
+    public partial class MetroWindow
+    {
+        void Minimized(object sender, RoutedEventArgs e)
+        {
+            Window.GetWindow(sender as FrameworkElement).WindowState = WindowState.Minimized;
+        }
+
+        void Normal(object sender, RoutedEventArgs e)
+        {
+            Window.GetWindow(sender as FrameworkElement).WindowState = WindowState.Normal;
+        }
+
+        void Maximized(object sender, RoutedEventArgs e)
+        {
+            Window.GetWindow(sender as FrameworkElement).WindowState = WindowState.Maximized;
+        }
+
+        void Close(object sender, RoutedEventArgs e)
+        {
+            Window.GetWindow(sender as FrameworkElement).Close();
+        }
+    }
+}

+ 50 - 0
Arthas-WPFUI/Arthas/Controls/Utility.cs

@@ -0,0 +1,50 @@
+using Arthas.Utility.Media;
+using System.ComponentModel;
+using System.Windows;
+
+namespace Arthas.Controls
+{
+    public class Utility
+    {
+        /// <summary>
+        /// 刷新样式
+        /// </summary>
+        /// <param name="control"></param>
+        public static void Refresh(FrameworkElement control)
+        {
+            if (control == null)
+            {
+                return;
+            }
+            if (!DesignerProperties.GetIsInDesignMode(control))
+            {
+                if (control.IsLoaded)
+                {
+                    SetColor(control);
+                }
+                else
+                {
+                    control.Loaded += delegate { SetColor(control); };
+                }
+            }
+        }
+
+        static void SetColor(FrameworkElement control)
+        {
+            var mw = Window.GetWindow(control) is MetroWindow ? Window.GetWindow(control) as MetroWindow : null;
+            if (mw != null)
+            {
+                if (control is MetroTitleMenu) { (control as MetroTitleMenu).Background = mw.BorderBrush; }
+                if (control is MetroTitleMenuItem) { (control as MetroTitleMenuItem).Background = mw.BorderBrush; }
+                if (control is MetroMenuItem) { (control as MetroMenuItem).Background = mw.BorderBrush; }
+                if (control is MetroContextMenu) { (control as MetroContextMenu).Background = mw.BorderBrush; }
+                if (control is MetroTextBox) { (control as MetroTextBox).BorderBrush = mw.BorderBrush; }
+                if (control is MetroButton) { (control as MetroButton).Background = mw.BorderBrush; }
+                if (control is MetroMenuTabControl) { (control as MetroMenuTabControl).BorderBrush = mw.BorderBrush; }
+                if (control is MetroRichTextBox) { (control as MetroRichTextBox).MouseMoveThemeBorderBrush = mw.BorderBrush; }
+                if (control is MetroCanvasGrid) { if ((control as MetroCanvasGrid).IsApplyTheme) (control as MetroCanvasGrid).Background = new RgbaColor(mw.BorderBrush).OpaqueSolidColorBrush; }
+                if (control is MetroColorPicker) { (control as MetroColorPicker).BorderBrush = mw.BorderBrush; }
+            }
+        }
+    }
+}

+ 28 - 0
Arthas-WPFUI/Arthas/Converter/CornerRadiusToDouble.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Arthas.Controls.Converter
+{
+    public class CornerRadiusToDouble : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (parameter != null)
+            {
+                return ((CornerRadius)value).TopLeft * System.Convert.ToDouble(parameter);
+            }
+            return ((CornerRadius)value).TopLeft;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (parameter != null)
+            {
+                return new CornerRadius((double)value / System.Convert.ToDouble(parameter));
+            }
+            return new CornerRadius((double)value);
+        }
+    }
+}

+ 40 - 0
Arthas-WPFUI/Arthas/Converter/DoubleFactor.cs

@@ -0,0 +1,40 @@
+using System.Globalization;
+using System.Windows.Data;
+
+namespace Arthas.Controls.Converter
+{
+    public class DoubleFactor : IValueConverter
+    {
+        public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value == null)
+            {
+                return 0.0;
+            }
+            else if (parameter == null)
+            {
+                return System.Convert.ToDouble(value);
+            }
+            else
+            {
+                return System.Convert.ToDouble(value) * System.Convert.ToDouble(parameter);
+            }
+        }
+
+        public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value == null)
+            {
+                return 0.0;
+            }
+            else if (parameter == null)
+            {
+                return System.Convert.ToDouble(value);
+            }
+            else
+            {
+                return System.Convert.ToDouble(value) / System.Convert.ToDouble(parameter);
+            }
+        }
+    }
+}

+ 27 - 0
Arthas-WPFUI/Arthas/Converter/DoubleToCornerRadius.cs

@@ -0,0 +1,27 @@
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Arthas.Controls.Converter
+{
+    public class DoubleToCornerRadius : IValueConverter
+    {
+        public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
+        {
+            if (parameter != null)
+            {
+                return new CornerRadius((double)value / System.Convert.ToDouble(parameter));
+            }
+            return new CornerRadius((double)value);
+        }
+
+        public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture)
+        {
+            if (parameter != null)
+            {
+                return ((CornerRadius)value).TopLeft * System.Convert.ToDouble(parameter);
+            }
+            return ((CornerRadius)value).TopLeft;
+        }
+    }
+}

+ 85 - 0
Arthas-WPFUI/Arthas/Converter/DoubleToThickness.cs

@@ -0,0 +1,85 @@
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Arthas.Controls.Converter
+{
+    public class DoubleToThickness : IValueConverter
+    {
+        public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value != null)
+            {
+                if (parameter != null)
+                {
+                    switch (parameter.ToString())
+                    {
+                        case "Left":
+                            return new Thickness(System.Convert.ToDouble(value), 0, 0, 0);
+
+                        case "Top":
+                            return new Thickness(0, System.Convert.ToDouble(value), 0, 0);
+
+                        case "Right":
+                            return new Thickness(0, 0, System.Convert.ToDouble(value), 0);
+
+                        case "Buttom":
+                            return new Thickness(0, 0, 0, System.Convert.ToDouble(value));
+
+                        case "LeftTop":
+                            return new Thickness(System.Convert.ToDouble(value), System.Convert.ToDouble(value), 0, 0);
+
+                        case "LeftButtom":
+                            return new Thickness(System.Convert.ToDouble(value), 0, 0, System.Convert.ToDouble(value));
+
+                        case "RightTop":
+                            return new Thickness(0, System.Convert.ToDouble(value), System.Convert.ToDouble(value), 0);
+
+                        case "RigthButtom":
+                            return new Thickness(0, 0, System.Convert.ToDouble(value), System.Convert.ToDouble(value));
+
+                        case "LeftRight":
+                            return new Thickness(System.Convert.ToDouble(value), 0, System.Convert.ToDouble(value), 0);
+
+                        case "TopButtom":
+                            return new Thickness(0, System.Convert.ToDouble(value), 0, System.Convert.ToDouble(value));
+
+                        default:
+                            return new Thickness(System.Convert.ToDouble(value));
+                    }
+                }
+                return new Thickness(System.Convert.ToDouble(value));
+            }
+            return new Thickness(0);
+        }
+
+        public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value != null)
+            {
+                if (parameter != null)
+                {
+                    switch (parameter.ToString())
+                    {
+                        case "Left":
+                            return ((Thickness)value).Left;
+
+                        case "Top":
+                            return ((Thickness)value).Top;
+
+                        case "Right":
+                            return ((Thickness)value).Right;
+
+                        case "Buttom":
+                            return ((Thickness)value).Bottom;
+
+                        default:
+                            return ((Thickness)value).Left;
+                    }
+                }
+                return ((Thickness)value).Left;
+            }
+            return 0.0;
+        }
+    }
+}

+ 19 - 0
Arthas-WPFUI/Arthas/Converter/StringToVisibility.cs

@@ -0,0 +1,19 @@
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Arthas.Controls.Converter
+{
+    public class StringToVisibility : IValueConverter
+    {
+        public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
+        {
+            return value == null || value.ToString() == "" ? Visibility.Hidden : Visibility.Visible;
+        }
+
+        public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture)
+        {
+            return value;
+        }
+    }
+}

+ 5 - 0
Arthas-WPFUI/Arthas/Properties/AssemblyInfo.cs

@@ -0,0 +1,5 @@
+using System.Windows;
+using System.Windows.Markup;
+
+[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
+[assembly: XmlnsDefinition("https://github.com/1217950746/Arthas-WPFUI", "Arthas.Controls")]

+ 32 - 0
Arthas-WPFUI/Arthas/Themes/Generic.xaml

@@ -0,0 +1,32 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroWindow.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroButton.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroTextButton.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroFocusButton.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroTextBox.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroTabControl.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroTextBlock.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroTabItem.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroSwitch.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroGroupBox.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroWaterfallFlow.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroMenuTabItem.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroMenuTabControl.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroTitleMenu.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroTitleMenuItem.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroMenuItem.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroMenuSeparator.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroContextMenu.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroScrollViewer.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroComboBox.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroComboBoxItem.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroVisualElement.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroProgressBar.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroRichTextBox.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroImage.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroExpander.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroCanvasGrid.xaml" />
+        <ResourceDictionary Source="/Arthas;component/Controls/MetroPath.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+</ResourceDictionary>

+ 21 - 0
Arthas-WPFUI/Arthas/Themes/Theme.cs

@@ -0,0 +1,21 @@
+using System.Windows;
+using System.Windows.Media;
+
+namespace Arthas.Themes
+{
+    public class Theme
+    {
+        public static void Switch(Visual myVisual)
+        {
+            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
+            {
+                Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);
+                if (childVisual != null)
+                {
+                    Controls.Utility.Refresh(childVisual as FrameworkElement);
+                    Switch(childVisual);
+                }
+            }
+        }
+    }
+}

+ 82 - 0
Arthas-WPFUI/Arthas/Utility/Element/ElementBase.cs

@@ -0,0 +1,82 @@
+using System.Windows;
+using System.Windows.Input;
+
+namespace Arthas.Utility.Element
+{
+    public class ElementBase
+    {
+        /// <summary>
+        /// 注册属性
+        /// public static readonly DependencyProperty Property = Utility.Property<T,T>(string,T);
+        /// </summary>
+        /// <typeparam name="thisType">this</typeparam>
+        /// <typeparam name="propertyType">如:string,bool</typeparam>
+        /// <param name="name">属性名</param>
+        /// <param name="defaultValue">属性值</param>
+        /// <returns></returns>
+        public static DependencyProperty Property<thisType, propertyType>(string name, propertyType defaultValue)
+        {
+            return DependencyProperty.Register(name.Replace("Property", ""), typeof(propertyType), typeof(thisType), new PropertyMetadata(defaultValue));
+        }
+
+        /// <summary>
+        /// 注册属性
+        /// public static readonly DependencyProperty Property = Utility.Property<T,T>(string,T);
+        /// </summary>
+        /// <typeparam name="thisType"></typeparam>
+        /// <typeparam name="propertyType"></typeparam>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public static DependencyProperty Property<thisType, propertyType>(string name)
+        {
+            return DependencyProperty.Register(name.Replace("Property", ""), typeof(propertyType), typeof(thisType));
+        }
+
+        /// <summary>
+        /// 注册事件
+        /// public static readonly RoutedEvent NameRoutedEvent = Utility.RoutedEvent<T,T>(string,T);
+        /// public event EventHandler Name { add { AddHandler(EventHandler, value); } remove { RemoveHandler(EventHandler, value); } }
+        /// </summary>
+        /// <typeparam name="thisType"></typeparam>
+        /// <typeparam name="propertyType"></typeparam>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public static RoutedEvent RoutedEvent<thisType, propertyType>(string name)
+        {
+            return EventManager.RegisterRoutedEvent(name.Replace("Event", ""), RoutingStrategy.Bubble, typeof(propertyType), typeof(thisType));
+        }
+
+        /// <summary>
+        /// 默认样式
+        /// Utility.DefaultStyle<T>(DefaultStyleKeyProperty);
+        /// </summary>
+        /// <typeparam name="thisType">this</typeparam>
+        /// <param name="dp">DefaultStyleKeyProperty</param>
+        public static void DefaultStyle<thisType>(DependencyProperty dp)
+        {
+            dp.OverrideMetadata(typeof(thisType), new FrameworkPropertyMetadata(typeof(thisType)));
+        }
+
+        /// <summary>
+        /// 初始化一个 Command
+        /// </summary>
+        /// <typeparam name="thisType"></typeparam>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public static RoutedUICommand Command<thisType>(string name)
+        {
+            return new RoutedUICommand(name, name, typeof(thisType));
+        }
+
+        /// <summary>
+        /// 切换状态
+        /// </summary>
+        /// <param name="element"></param>
+        /// <param name="state"></param>
+        public static string GoToState(FrameworkElement element, string state)
+        {
+            VisualStateManager.GoToState(element, state, false);
+            return state;
+        }
+    }
+}

+ 21 - 0
Arthas-WPFUI/Arthas/Utility/Element/VisualObj.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Windows.Media;
+
+namespace Arthas.Utility.Element
+{
+    public class VisualObj
+    {
+        public static void ActionOnAllElement(Visual visual, Action<Visual> action)
+        {
+            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
+            {
+                Visual childVisual = (Visual)VisualTreeHelper.GetChild(visual, i);
+                if (childVisual != null)
+                {
+                    action(childVisual);
+                    ActionOnAllElement(childVisual, action);
+                }
+            }
+        }
+    }
+}

+ 81 - 0
Arthas-WPFUI/Arthas/Utility/Media/HsbaColor.cs

@@ -0,0 +1,81 @@
+using System.Windows.Media;
+
+namespace Arthas.Utility.Media
+{
+    public class HsbaColor
+    {
+        double h = 0, s = 0, b = 0, a = 0;
+
+        /// <summary>
+        /// 0 - 359,360 = 0
+        /// </summary>
+        public double H { get { return h; } set { h = value < 0 ? 0 : value >= 360 ? 0 : value; } }
+
+        /// <summary>
+        /// 0 - 1
+        /// </summary>
+        public double S { get { return s; } set { s = value < 0 ? 0 : value > 1 ? 1 : value; } }
+
+        /// <summary>
+        /// 0 - 1
+        /// </summary>
+        public double B { get { return b; } set { b = value < 0 ? 0 : value > 1 ? 1 : value; } }
+
+        /// <summary>
+        /// 0 - 1
+        /// </summary>
+        public double A { get { return a; } set { a = value < 0 ? 0 : value > 1 ? 1 : value; } }
+
+        /// <summary>
+        /// 亮度 0 - 100
+        /// </summary>
+        public int Y { get { return RgbaColor.Y; } }
+
+        public HsbaColor()
+        {
+            H = 0; S = 0; B = 1; A = 1;
+        }
+
+        public HsbaColor(double h, double s, double b, double a = 1)
+        {
+            H = h; S = s; B = b; A = a;
+        }
+
+        public HsbaColor(int r, int g, int b, int a = 255)
+        {
+            HsbaColor hsba = Utility.RgbaToHsba(new RgbaColor(r, g, b, a));
+            H = hsba.H;
+            S = hsba.S;
+            B = hsba.B;
+            A = hsba.A;
+        }
+
+        public HsbaColor(Brush brush)
+        {
+            HsbaColor hsba = Utility.RgbaToHsba(new RgbaColor(brush));
+            H = hsba.H;
+            S = hsba.S;
+            B = hsba.B;
+            A = hsba.A;
+        }
+
+        public HsbaColor(string hexColor)
+        {
+            HsbaColor hsba = Utility.RgbaToHsba(new RgbaColor(hexColor));
+            H = hsba.H;
+            S = hsba.S;
+            B = hsba.B;
+            A = hsba.A;
+        }
+
+        public Color Color { get { return RgbaColor.Color; } }
+        public Color OpaqueColor { get { return RgbaColor.OpaqueColor; } }
+        public SolidColorBrush SolidColorBrush { get { return RgbaColor.SolidColorBrush; } }
+        public SolidColorBrush OpaqueSolidColorBrush { get { return RgbaColor.OpaqueSolidColorBrush; } }
+
+        public string HexString { get { return Color.ToString(); } }
+        public string RgbaString { get { return RgbaColor.RgbaString; } }
+
+        public RgbaColor RgbaColor { get { return Utility.HsbaToRgba(this); } }
+    }
+}

+ 38 - 0
Arthas-WPFUI/Arthas/Utility/Media/ResObj.cs

@@ -0,0 +1,38 @@
+using System.IO;
+using System.Reflection;
+using System.Windows.Media;
+
+namespace Arthas.Utility.Media
+{
+    public class ResObj
+    {
+        static Stream Get(Assembly assembly, string path)
+        {
+            return assembly.GetManifestResourceStream(assembly.GetName().Name + "." + path);
+        }
+
+        public static string GetString(Assembly assembly, string path)
+        {
+            try
+            {
+                return StreamObj.ToString(Get(assembly, path));
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        public static ImageSource GetImageSource(Assembly assembly, string path)
+        {
+            try
+            {
+                return StreamObj.ToImageSource(Get(assembly, path));
+            }
+            catch
+            {
+                return null;
+            }
+        }
+    }
+}

+ 95 - 0
Arthas-WPFUI/Arthas/Utility/Media/RgbaColor.cs

@@ -0,0 +1,95 @@
+using System.Windows.Media;
+
+namespace Arthas.Utility.Media
+{
+    public class RgbaColor
+    {
+        int r = 0, g = 0, b = 0, a = 0;
+
+        /// <summary>
+        /// 0 - 255
+        /// </summary>
+        public int R { get { return r; } set { r = value < 0 ? 0 : value > 255 ? 255 : value; } }
+
+        /// <summary>
+        /// 0 - 255
+        /// </summary>
+        public int G { get { return g; } set { g = value < 0 ? 0 : value > 255 ? 255 : value; } }
+
+        /// <summary>
+        /// 0 - 255
+        /// </summary>
+        public int B { get { return b; } set { b = value < 0 ? 0 : value > 255 ? 255 : value; } }
+
+        /// <summary>
+        /// 0 - 255
+        /// </summary>
+        public int A { get { return a; } set { a = value < 0 ? 0 : value > 255 ? 255 : value; } }
+
+        /// <summary>
+        /// 亮度 0 - 100
+        /// </summary>
+        public int Y { get { return Utility.GetBrightness(R, G, B); } }
+
+        public RgbaColor()
+        {
+            R = 255; G = 255; B = 255; A = 255;
+        }
+
+        public RgbaColor(int r, int g, int b, int a = 255)
+        {
+            R = r; G = g; B = b; A = a;
+        }
+
+        public RgbaColor(Brush brush)
+        {
+            if (brush != null)
+            {
+                R = ((SolidColorBrush)brush).Color.R;
+                G = ((SolidColorBrush)brush).Color.G;
+                B = ((SolidColorBrush)brush).Color.B;
+                A = ((SolidColorBrush)brush).Color.A;
+            }
+            else
+            {
+                R = G = B = A = 255;
+            }
+        }
+
+        public RgbaColor(double h, double s, double b, double a = 1)
+        {
+            RgbaColor rgba = Utility.HsbaToRgba(new HsbaColor(h, s, b, a));
+            R = rgba.R;
+            G = rgba.G;
+            B = rgba.B;
+            A = rgba.A;
+        }
+
+        public RgbaColor(string hexColor)
+        {
+            try
+            {
+                Color color;
+                if (hexColor.Substring(0, 1) == "#") color = (Color)ColorConverter.ConvertFromString(hexColor);
+                else color = (Color)ColorConverter.ConvertFromString("#" + hexColor);
+                R = color.R;
+                G = color.G;
+                B = color.B;
+                A = color.A;
+            }
+            catch
+            {
+            }
+        }
+
+        public Color Color { get { return Color.FromArgb((byte)A, (byte)R, (byte)G, (byte)B); } }
+        public Color OpaqueColor { get { return Color.FromArgb((byte)255.0, (byte)R, (byte)G, (byte)B); } }
+        public SolidColorBrush SolidColorBrush { get { return new SolidColorBrush(Color); } }
+        public SolidColorBrush OpaqueSolidColorBrush { get { return new SolidColorBrush(OpaqueColor); } }
+
+        public string HexString { get { return Color.ToString(); } }
+        public string RgbaString { get { return R + "," + G + "," + B + "," + A; } }
+
+        public HsbaColor HsbaColor { get { return Utility.RgbaToHsba(this); } }
+    }
+}

+ 30 - 0
Arthas-WPFUI/Arthas/Utility/Media/StreamObj.cs

@@ -0,0 +1,30 @@
+using System.IO;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace Arthas.Utility.Media
+{
+    public class StreamObj
+    {
+        public static string ToString(Stream stream)
+        {
+            try { return new StreamReader(stream).ReadToEnd(); }
+            catch { return ""; }
+        }
+
+        public static ImageSource ToImageSource(Stream stream)
+        {
+            try
+            {
+                BitmapImage bitmapImage = new BitmapImage();
+                bitmapImage.BeginInit();
+                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
+                bitmapImage.StreamSource = stream;
+                bitmapImage.EndInit();
+
+                return bitmapImage;
+            }
+            catch { return null; }
+        }
+    }
+}

+ 196 - 0
Arthas-WPFUI/Arthas/Utility/Media/Utility.cs

@@ -0,0 +1,196 @@
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Windows;
+using System.Windows.Interop;
+using System.Windows.Media.Imaging;
+
+namespace Arthas.Utility.Media
+{
+    /// <summary>
+    /// 实用工具
+    /// </summary>
+    internal class Utility
+    {
+        /// <summary>
+        /// Rgba转Hsba
+        /// </summary>
+        /// <param name="rgba"></param>
+        /// <returns></returns>
+        internal static HsbaColor RgbaToHsba(RgbaColor rgba)
+        {
+            int[] rgb = new int[] { rgba.R, rgba.G, rgba.B };
+            Array.Sort(rgb);
+            int max = rgb[2];
+            int min = rgb[0];
+
+            double hsbB = max / 255.0;
+            double hsbS = max == 0 ? 0 : (max - min) / (double)max;
+            double hsbH = 0;
+
+            if (rgba.R == rgba.G && rgba.R == rgba.B)
+            {
+            }
+            else
+            {
+                if (max == rgba.R && rgba.G >= rgba.B) hsbH = (rgba.G - rgba.B) * 60.0 / (max - min) + 0.0;
+                else if (max == rgba.R && rgba.G < rgba.B) hsbH = (rgba.G - rgba.B) * 60.0 / (max - min) + 360.0;
+                else if (max == rgba.G) hsbH = (rgba.B - rgba.R) * 60.0 / (max - min) + 120.0;
+                else if (max == rgba.B) hsbH = (rgba.R - rgba.G) * 60.0 / (max - min) + 240.0;
+            }
+
+            return new HsbaColor(hsbH, hsbS, hsbB, rgba.A / 255.0);
+        }
+
+        /// <summary>
+        /// Hsba转Rgba
+        /// </summary>
+        /// <param name="hsba"></param>
+        /// <returns></returns>
+        internal static RgbaColor HsbaToRgba(HsbaColor hsba)
+        {
+            double r = 0, g = 0, b = 0;
+            int i = (int)((hsba.H / 60) % 6);
+            double f = (hsba.H / 60) - i;
+            double p = hsba.B * (1 - hsba.S);
+            double q = hsba.B * (1 - f * hsba.S);
+            double t = hsba.B * (1 - (1 - f) * hsba.S);
+            switch (i)
+            {
+                case 0:
+                    r = hsba.B;
+                    g = t;
+                    b = p;
+                    break;
+
+                case 1:
+                    r = q;
+                    g = hsba.B;
+                    b = p;
+                    break;
+
+                case 2:
+                    r = p;
+                    g = hsba.B;
+                    b = t;
+                    break;
+
+                case 3:
+                    r = p;
+                    g = q;
+                    b = hsba.B;
+                    break;
+
+                case 4:
+                    r = t;
+                    g = p;
+                    b = hsba.B;
+                    break;
+
+                case 5:
+                    r = hsba.B;
+                    g = p;
+                    b = q;
+                    break;
+
+                default:
+                    break;
+            }
+            return new RgbaColor((int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b), (int)(255.0 * hsba.A));
+        }
+
+        /*
+        /// <summary>
+        /// Bitmap转byte[]
+        /// </summary>
+        /// <param name="bitmap"></param>
+        /// <returns></returns>
+        internal static byte[] BitmapToByte(Bitmap bitmap)
+        {
+            byte[] bytes = new byte[bitmap.Width * bitmap.Height * 4];
+            BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
+            Marshal.Copy(bitmapData.Scan0, bytes, 0, bytes.Length);
+            bitmap.UnlockBits(bitmapData);
+            return bytes;
+        }
+
+        /// <summary>
+        /// 从BitmapByte中读取颜色
+        /// </summary>
+        /// <param name="buffer"></param>
+        /// <param name="w"></param>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <returns></returns>
+        internal static int[] GetByteColor(byte[] buffer, int w, int x, int y)
+        {
+            int[] color = new int[] { 0, 0, 0, 0 };
+            color[0] = buffer[x * 4 + y * w * 4 + 0];
+            color[1] = buffer[x * 4 + y * w * 4 + 1];
+            color[2] = buffer[x * 4 + y * w * 4 + 2];
+            color[3] = buffer[x * 4 + y * w * 4 + 3];
+            return color;
+        }
+        */
+
+        /// <summary>
+        /// 读取指定图片到内存
+        /// </summary>
+        /// <param name="path"></param>
+        /// <returns></returns>
+        internal static BitmapSource LoadImg(string path)
+        {
+            try
+            {
+                BitmapImage bitmapImage = new BitmapImage();
+                bitmapImage.BeginInit();
+                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
+                bitmapImage.StreamSource = new System.IO.MemoryStream(System.IO.File.ReadAllBytes(path));
+                bitmapImage.EndInit();
+
+                return bitmapImage;
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// BitmapImage转Bitmap
+        /// </summary>
+        /// <param name="bitmapImage"></param>
+        /// <returns></returns>
+        internal static Bitmap BitmapImageToBitmap(BitmapImage bitmapImage)
+        {
+            PixelFormat pp = PixelFormat.Format32bppArgb;
+            Bitmap bmp = new Bitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight, pp);
+            BitmapData data = bmp.LockBits(new Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, pp);
+            bitmapImage.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
+            bmp.UnlockBits(data);
+            return bmp;
+        }
+
+        /// <summary>
+        /// Bitmap转BitmapSource
+        /// </summary>
+        /// <param name="bitmap"></param>
+        /// <returns></returns>
+        internal static BitmapSource BitmapToBitmapSource(Bitmap bitmap)
+        {
+            return Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
+        }
+
+        /// <summary>
+        /// 获取颜色亮度
+        /// </summary>
+        /// <param name="r"></param>
+        /// <param name="g"></param>
+        /// <param name="b"></param>
+        /// <returns></returns>
+        internal static int GetBrightness(int r, int g, int b)
+        {
+            return (int)((0.2126 * r + 0.7152 * g + 0.0722 * b) / 2.55);
+        }
+    }
+}

+ 21 - 0
Arthas-WPFUI/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 ONEO
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 17 - 0
Arthas-WPFUI/README.md

@@ -0,0 +1,17 @@
+# Arthas
+
+> **已经在 develop 分支恢复开发**,希望此项目能让大家感受到 WPF MVVM 惊人的开发效率与漂亮的界面!
+
+![](Screenshots/1.png)
+
+## 支持
+
+同时支持以下两个版本
+
+- .Net 4.6.1
+- .Net Core 3.0
+
+## 食用方法
+
+ - Visual Studio 2019 或 VSCode
+ - .Net Core 3.0 SDK

二進制
Arthas-WPFUI/Screenshots/1.png


+ 242 - 0
DataAccess/AppConfigHelper.cs

@@ -0,0 +1,242 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+//using System.Threading.Tasks;
+using System.Configuration;
+
+namespace WpfModBus.DataAccess
+{
+    public enum DATA_TYPE
+    {
+        DT_REMOTE, 
+    }
+    public class ConnectionStringKeys
+    {
+        public static string  strRemote = "remote"; 
+        ////////
+        public static string strRemoteSetting ="remoteSetting";  
+    }
+    public class ConnectionStrings
+    {
+        public string strRemote { get; set; } 
+        ////
+        ///
+       // public string strRemoteSetting { get; set; }  
+    }
+    public class AppConfigHelper
+    {
+        public const string CONNECTTINGSTRING
+            = @"Data Source=
+                    (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST= {0})(PORT= {1})))(CONNECT_DATA=(SERVICE_NAME= {2})));
+                    User Id= {3};
+                    Password={4};";
+
+        public const string MYSQL_CONNECTTINGSTRING = "server={0};user id={1};password={2};database={3};Port={4};Charset=utf8;";
+        public const string POSTGRESQL_CONNECTTINGSTRING = "HOST={0};USER ID ={1};PASSWORD={2};DATABASE={3};PORT = {4}";
+        public const string SQLITE_CONNECTIONSTRING = "Data Source={0};Initial Catalog=sqlite;Integrated Security=True;Max Pool Size=10";
+        public const string ORACLE_CONNECTIONSTRING = @"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST= {0})(PORT= {1})))(CONNECT_DATA=(SERVICE_NAME= {2})));User Id= {3};Password={4};";
+        public const string MSSQL_CONNECTIONSTRING = "Server={0};uid={1};pwd={2};Database={3};Port={4}";
+
+
+        public static string GetConnectionStringsConfig(string connectionName)
+        { 
+            string connectionString =
+            ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString();
+
+            return connectionString;
+        }
+
+
+        public static ConnectionStrings GetConnectionStrings()
+        {
+            ConnectionStrings connectionStrings = new ConnectionStrings();
+            connectionStrings.strRemote= AppConfigHelper.GetConnectionStringsConfig("remote"); 
+            ////////
+            //connectionStrings.strRemoteSetting = AppConfigHelper.GetConnectionStringsConfig("remoteSetting"); 
+            return connectionStrings;
+        }
+        public static string ProviderName(string name)
+        {
+            if (name == "mongodb" || name == "redis")
+                return "";
+            if(name == "mysql")
+            { 
+                //< add name = "mysql" connectionString = "Server=localhost;Uid=root;Pwd=zpsoft2019;Database=system;Port=3306" providerName = "MySql.Data.MySqlClient" />
+                //< add name = "mysqlconnector" connectionString = "Server=localhost;Uid=petapoco;Pwd=petapoco;Database=petapoco;Port=5006" providerName = "MySqlConnector" />
+                //        < add name = "mariadb" connectionString = "Server=localhost;Uid=petapoco;Pwd=petapoco;Database=petapoco;Port=5003;SslMode=none" providerName = "MySql.Data.MySqlClient" />
+                return "Sql.Data.MySqlClient";
+            }
+
+            //< add name = "postgres" connectionString = "Host=localhost;Username=petapoco;Password=petapoco;Database=petapoco;Port=5001" providerName = "Npgsql" /> -->
+            if(name == "postgresql")
+            {
+                return "Npgsql";
+            }
+
+            if(name == "sqlite")
+            {
+                //< add name = "sqlite" connectionString = "Data Source=PetaPoco.sqlite;Version=3;" providerName = "System.Data.SQLite" />
+                return "System.Data.SQLite";
+            }
+            if(name == "mssql")
+            {
+                //        < add name = "mssql" connectionString = "Data Source=localhost,5005;Initial Catalog=PetaPoco;User ID=sa;Password=pAtAp0c8" providerName = "System.Data.SqlClient" />
+            //       < add name = "mssqlce" connectionString = "Data Source=petapoco.sdf" providerName = "System.Data.SqlServerCe.4.0" />
+              //      < add name = "mssql_builder" connectionString = "Data Source=localhost,5005;User ID=sa;Password=pAtAp0c8" providerName = "System.Data.SqlClient" />
+                //    < add name = "mssqlmsdata_builder" connectionString = "Data Source=localhost,5005;User ID=sa;Password=pAtAp0c8" providerName = "Microsoft.Data.SqlClient" />
+                  //  < add name = "mssqlmsdata" connectionString = "Data Source=localhost,5005;Initial Catalog=PetaPocoMsData;User ID=sa;Password=pAtAp0c8" providerName = "Microsoft.Data.SqlClient" />
+                return "System.Data.SqlClient";
+            }
+            if(name == "oracle")
+            {
+                return "Oracle.ManagedDataAccess";
+            }
+            if(name == "access")
+            {
+                //        < add name = "msaccess" connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|Databases\MSAccess\petapoco.accdb" providerName = "OleDb" />
+                 return "OleDb";
+            }
+
+ 
+            // < add name = "firebird" connectionString = "User=SYSDBA;Password=petapoco;Database=/firebird/data/petapoco.fdb;DataSource=localhost;Port=5004;ServerType=0;Charset=NONE;Pooling=false" providerName = "FirebirdSql.Data.FirebirdClient" />
+
+            return "";
+        }
+        public static  string ConnectionStrings(DatabaseParam param)
+        {
+            string connectionStr = "";
+            if(param.database_type == "mysql")
+            {
+                connectionStr = string.Format(MYSQL_CONNECTTINGSTRING, param.host, param.user_name, param.password, param.database, param.port);
+                return connectionStr;
+            }
+            if (param.database_type == "sqlite")
+            {
+                connectionStr = string.Format(SQLITE_CONNECTIONSTRING, param.directory +@"\"+  param.database+"_"+param.well_name+".db");
+                return connectionStr;
+            }
+            if (param.database_type == "postgresql")
+            {
+                connectionStr = string.Format(POSTGRESQL_CONNECTTINGSTRING, param.host, param.user_name, param.password, param.database, param.port);
+                return connectionStr;
+            }
+            if (param.database_type == "mssql")
+            {
+                connectionStr = string.Format(MSSQL_CONNECTIONSTRING ,param.host, param.user_name, param.password, param.database, param.port);
+                return connectionStr;
+            }
+            if (param.database_type == "oracle")
+            {
+                connectionStr = string.Format(ORACLE_CONNECTIONSTRING, param.host, param.port, param.database, param.user_name, param.password);
+                return connectionStr;
+            }
+
+            connectionStr = string.Format(CONNECTTINGSTRING, param.host, param.port, param.database, param.user_name, param.password);
+            return connectionStr;
+        }   
+                  
+        public static bool update_connection_string(ref Dictionary<string,DatabaseParam> dict)
+        {
+            ConnectionStrings connectionStrings1 =  GetConnectionStrings();
+            foreach(string strKey in dict.Keys)
+            {
+                string providerName = ProviderName(dict[strKey].database_type);
+                if (providerName.Length <= 0)
+                    continue;
+                //dict[strKey] 
+                UpdateConnectionStringsConfig(strKey, ConnectionStrings(dict[strKey]), providerName);
+            }
+            ConnectionStrings connectionStrings2 = GetConnectionStrings();
+
+
+            return true;
+        }
+
+        ///<summary>     
+        ///更新连接字符串      
+        ///</summary>     
+        ///<param name="newName">连接字符串名称</param>     
+        ///<param name="newConString">连接字符串内容</param>
+        ///查看本栏目更多精彩内容:http://www.bianceng.cn/Programming/csharp/
+        ///<param name="newProviderName">数据提供程序名称</param>     
+        public static void UpdateConnectionStringsConfig(string newName,
+            string newConString,
+            string newProviderName)
+        {
+            bool isModified = false;    //记录该连接串是否已经存在      
+                                        //如果要更改的连接串已经存在      
+            if (ConfigurationManager.ConnectionStrings[newName] != null)
+            {
+                isModified = true;
+            }
+            //新建一个连接字符串实例      
+            ConnectionStringSettings mySettings =
+                new ConnectionStringSettings(newName, newConString, newProviderName);
+            // 打开可执行的配置文件*.exe.config      
+            Configuration config =
+                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
+            // 如果连接串已存在,首先删除它      
+            if (isModified)
+            {
+                config.ConnectionStrings.ConnectionStrings.Remove(newName);
+            }
+            // 将新的连接串添加到配置文件中.      
+            config.ConnectionStrings.ConnectionStrings.Add(mySettings);
+            // 保存对配置文件所作的更改      
+            config.Save(ConfigurationSaveMode.Modified);
+            // 强制重新载入配置文件的ConnectionStrings配置节      
+            ConfigurationManager.RefreshSection("ConnectionStrings");
+        }
+
+
+        ///<summary>     
+        ///返回***.exe.config文件中appSettings配置节的value项      
+        ///</summary>     
+        ///<param name="strKey"></param>     
+        ///<returns></returns>     
+        public static string GetAppConfig(string strKey)
+        {
+            foreach (string key in ConfigurationManager.AppSettings)
+            {
+                if (key == strKey)
+                {
+                    return ConfigurationManager.AppSettings[strKey];
+                }
+            }
+            return null;
+        }
+
+        ///<summary>      
+        ///在***.exe.config文件中appSettings配置节增加一对键、值对      
+        ///</summary>      
+        ///<param name="newKey"></param>      
+        ///<param name="newValue"></param>      
+        public static void UpdateAppConfig(string newKey, string newValue)
+        {
+            bool isModified = false;
+            foreach (string key in ConfigurationManager.AppSettings)
+            {
+                if (key == newKey)
+                {
+                    isModified = true;
+                }
+            }
+
+            // Open App.Config of executable      
+            Configuration config =
+                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
+            // You need to remove the old settings object before you can replace it      
+            if (isModified)
+            {
+                config.AppSettings.Settings.Remove(newKey);
+            }
+            // Add an Application Setting.      
+            config.AppSettings.Settings.Add(newKey, newValue);
+            // Save the changes in App.config file.      
+            config.Save(ConfigurationSaveMode.Modified);
+            // Force a reload of a changed section.      
+            ConfigurationManager.RefreshSection("appSettings");
+        }
+    }
+}

部分文件因文件數量過多而無法顯示