diff --git a/src/Resources.props b/src/Resources.props
index ac35ddcb..7ae435f6 100644
--- a/src/Resources.props
+++ b/src/Resources.props
@@ -75,6 +75,9 @@
 		<Resource Include="..\WPFDevelopers.Samples.Shared\Resources\Images\ZooSemy\1.png">
 			<Link>Resources\Images\ZooSemy\1.png</Link>
 		</Resource>
+		<Resource Include="..\WPFDevelopers.Samples.Shared\Resources\Images\IconicThumbnail\*.jpg">
+			<Link>Resources\Images\IconicThumbnail\%(Filename)%(Extension)</Link>
+		</Resource>
 		<Resource Include="..\WPFDevelopers.Samples.Shared\Resources\Audio\HelloWPFDevelopes_en.mp3">
 			<Link>Resources\Audio\HelloWPFDevelopes_en.mp3</Link>
 		</Resource>
diff --git a/src/TargetFrameworks.props b/src/TargetFrameworks.props
index ea6ba3f9..68da39e9 100644
--- a/src/TargetFrameworks.props
+++ b/src/TargetFrameworks.props
@@ -17,7 +17,7 @@
 			<Version>7.0.0</Version>
 		</PackageReference>
 		<PackageReference Include="Microsoft.Win32.SystemEvents">
-			<Version>7.0.0</Version>
+			<Version>5.0.0</Version>
 		</PackageReference>
 	</ItemGroup>
 	<ItemGroup Condition="'$(TargetFramework)' == 'net6.0-windows'">
@@ -43,7 +43,7 @@
 			<Version>7.0.0</Version>
 		</PackageReference>
 		<PackageReference Include="Microsoft.Win32.SystemEvents">
-			<Version>7.0.0</Version>
+			<Version>4.7.0</Version>
 		</PackageReference>
 	</ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/WPFDevelopers.Net40/Themes/Generic.xaml b/src/WPFDevelopers.Net40/Themes/Generic.xaml
index 8fba6634..42892e77 100644
--- a/src/WPFDevelopers.Net40/Themes/Generic.xaml
+++ b/src/WPFDevelopers.Net40/Themes/Generic.xaml
@@ -17,7 +17,6 @@
         <Setter Property="SnapsToDevicePixels" Value="True" />
         <Setter Property="UseLayoutRounding" Value="True" />
         <Setter Property="TextOptions.TextFormattingMode" Value="Ideal" />
-        <Setter Property="WindowStyle" Value="None" />
         <Setter Property="FontFamily" Value="{DynamicResource WD.FontFamily}" />
         <Setter Property="shell:WindowChrome.WindowChrome">
             <Setter.Value>
@@ -27,11 +26,6 @@
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="{x:Type wd:Window}">
-                    <ControlTemplate.Resources>
-                        <Style TargetType="Grid">
-                            <Setter Property="Background" Value="Transparent" />
-                        </Style>
-                    </ControlTemplate.Resources>
                     <Border
                         Name="PART_Border"
                         Background="{TemplateBinding Background}"
@@ -43,10 +37,12 @@
                                 <RowDefinition Height="Auto" />
                                 <RowDefinition Height="*" />
                             </Grid.RowDefinitions>
-                            <control:SmallPanel
-                                x:Name="PART_Normal"
+                            <Border
                                 Grid.Row="0"
-                                Background="{TemplateBinding TitleBackground}">
+                                Margin="0,0,-1,0"
+                                HorizontalAlignment="Stretch"
+                                Background="{TemplateBinding TitleBackground}" />
+                            <control:SmallPanel x:Name="PART_Normal" Grid.Row="0">
                                 <Grid Height="{TemplateBinding TitleHeight}">
                                     <Grid.ColumnDefinitions>
                                         <ColumnDefinition Width="*" />
@@ -85,7 +81,7 @@
                                         Orientation="Horizontal">
                                         <StackPanel x:Name="PART_TitleBarMinAndMax" Orientation="Horizontal">
                                             <Button
-                                                Name="PART_TitleBarMinimizeButton"
+                                                x:Name="PART_TitleBarMinimizeButton"
                                                 Padding="0"
                                                 Command="{Binding Source={x:Static shell:SystemCommands.MinimizeWindowCommand}}"
                                                 IsTabStop="False"
@@ -101,7 +97,7 @@
                                                 </Grid>
                                             </Button>
                                             <Button
-                                                Name="PART_TitleBarMaximizeButton"
+                                                x:Name="PART_TitleBarMaximizeButton"
                                                 Padding="0"
                                                 Command="{Binding Source={x:Static shell:SystemCommands.MaximizeWindowCommand}}"
                                                 IsTabStop="False"
@@ -120,7 +116,7 @@
                                                 </Grid>
                                             </Button>
                                             <Button
-                                                Name="PART_TitleBarRestoreButton"
+                                                x:Name="PART_TitleBarRestoreButton"
                                                 Padding="0"
                                                 Command="{Binding Source={x:Static shell:SystemCommands.RestoreWindowCommand}}"
                                                 IsTabStop="False"
@@ -162,7 +158,6 @@
                             <control:SmallPanel
                                 x:Name="PART_HighTitleBar"
                                 Grid.Row="0"
-                                Background="{TemplateBinding TitleBackground}"
                                 Visibility="Collapsed">
                                 <Grid
                                     x:Name="PART_GridChrome"
@@ -213,7 +208,7 @@
                                                 </Grid>
                                             </Button>
                                             <Button
-                                                Name="PART_MaximizeButton"
+                                                x:Name="PART_MaximizeButton"
                                                 Padding="0"
                                                 Command="{Binding Source={x:Static shell:SystemCommands.MaximizeWindowCommand}}"
                                                 IsTabStop="False"
@@ -232,7 +227,7 @@
                                                 </Grid>
                                             </Button>
                                             <Button
-                                                Name="PART_RestoreButton"
+                                                x:Name="PART_RestoreButton"
                                                 Padding="0"
                                                 Command="{Binding Source={x:Static shell:SystemCommands.RestoreWindowCommand}}"
                                                 IsTabStop="False"
diff --git a/src/WPFDevelopers.Net40/Window.cs b/src/WPFDevelopers.Net40/Window.cs
index 23e65028..5eecc53f 100644
--- a/src/WPFDevelopers.Net40/Window.cs
+++ b/src/WPFDevelopers.Net40/Window.cs
@@ -1,6 +1,8 @@
 ﻿using Microsoft.Windows.Shell;
 using System;
 using System.Windows;
+using System.Windows.Automation.Peers;
+using System.Windows.Automation.Provider;
 using System.Windows.Controls;
 using System.Windows.Input;
 using System.Windows.Interop;
@@ -8,16 +10,28 @@
 using WPFDevelopers.Controls;
 using WPFDevelopers.Core.Helpers;
 using WPFDevelopers.Helpers;
-using static WPFDevelopers.Core.Helpers.MonitorHelper;
 
 namespace WPFDevelopers.Net40
 {
     [TemplatePart(Name = TitleBarIcon, Type = typeof(Button))]
+    [TemplatePart(Name = HighTitleMaximizeButton, Type = typeof(Button))]
+    [TemplatePart(Name = HighTitleRestoreButton, Type = typeof(Button))]
+    [TemplatePart(Name = TitleBarMaximizeButton, Type = typeof(Button))]
+    [TemplatePart(Name = TitleBarRestoreButton, Type = typeof(Button))]
     public class Window : System.Windows.Window
     {
         private const string TitleBarIcon = "PART_TitleBarIcon";
+        private const string HighTitleMaximizeButton = "PART_MaximizeButton";
+        private const string HighTitleRestoreButton = "PART_RestoreButton";
+        private const string TitleBarMaximizeButton = "PART_TitleBarMaximizeButton";
+        private const string TitleBarRestoreButton = "PART_TitleBarRestoreButton";
         private WindowStyle _windowStyle;
         private Button _titleBarIcon;
+        private Button _highTitleMaximizeButton;
+        private Button _highTitleRestoreButton;
+        private Button _titleBarMaximizeButton;
+        private Button _titleBarRestoreButton;
+        private IntPtr hWnd;
 
         public static readonly DependencyProperty TitleHeightProperty =
             DependencyProperty.Register("TitleHeight", typeof(double), typeof(Window), new PropertyMetadata(50d));
@@ -41,7 +55,6 @@ static Window()
 
         public Window()
         {
-            Loaded += Window_Loaded;
             WPFDevelopers.Resources.ThemeChanged += Resources_ThemeChanged;
             CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, CloseWindow));
             CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, MaximizeWindow,
@@ -69,9 +82,12 @@ public override void OnApplyTemplate()
                 _titleBarIcon.MouseDoubleClick -= Icon_MouseDoubleClick;
                 _titleBarIcon.MouseDoubleClick += Icon_MouseDoubleClick;
             }
+            _highTitleMaximizeButton = GetTemplateChild(HighTitleMaximizeButton) as Button;
+            _highTitleRestoreButton = GetTemplateChild(HighTitleRestoreButton) as Button;
+            _titleBarMaximizeButton = GetTemplateChild(TitleBarMaximizeButton) as Button;
+            _titleBarRestoreButton = GetTemplateChild(TitleBarRestoreButton) as Button;
         }
 
-
         private void Icon_MouseDoubleClick(object sender, MouseButtonEventArgs e)
         {
             if (e.ChangedButton == MouseButton.Left)
@@ -108,8 +124,9 @@ public TitleBarMode TitleBarMode
             set => SetValue(TitleBarModeProperty, value);
         }
 
-        private void Window_Loaded(object sender, RoutedEventArgs e)
+        protected override void OnSourceInitialized(EventArgs e)
         {
+            base.OnSourceInitialized(e);
             hWnd = new WindowInteropHelper(this).Handle;
             HwndSource.FromHwnd(hWnd).AddHook(WindowProc);
             if (TitleBarMode == TitleBarMode.Normal)
@@ -152,7 +169,7 @@ private void MaximizeWindow(object sender, ExecutedRoutedEventArgs e)
 
         private void MinimizeWindow(object sender, ExecutedRoutedEventArgs e)
         {
-            SendMessage(hWnd, MonitorHelper.WindowsMessageCodes.WM_SYSCOMMAND, new IntPtr(MonitorHelper.WindowsMessageCodes.SC_MINIMIZE), IntPtr.Zero);
+            Win32.SendMessage(hWnd, WindowsMessageCodes.WM_SYSCOMMAND, new IntPtr(WindowsMessageCodes.SC_MINIMIZE), IntPtr.Zero);
         }
 
         private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
@@ -160,8 +177,7 @@ private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
             SystemCommands.RestoreWindow(this);
         }
 
-        private IntPtr hWnd;
-      
+
         private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
         {
             switch (msg)
@@ -184,6 +200,75 @@ private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, re
                         handled = true;
                     }
                     break;
+                #region SnapLayouts
+                case WindowsMessageCodes.WM_NCHITTEST:
+                    try
+                    {
+                        if (OSVersionHelper.IsSnapLayoutSupported() && ResizeMode != ResizeMode.NoResize && ResizeMode != ResizeMode.CanMinimize)
+                        {
+                            int x = lParam.ToInt32() & 0xffff;
+                            int y = lParam.ToInt32() >> 16;
+                            var dpiX = OSVersionHelper.DeviceUnitsScalingFactorX;
+                            var button = TitleBarMode == TitleBarMode.Normal
+                                ? (WindowState != WindowState.Maximized ? _titleBarMaximizeButton : _titleBarRestoreButton)
+                                : (WindowState != WindowState.Maximized ? _highTitleMaximizeButton : _highTitleRestoreButton);
+                            if (button != null)
+                            {
+                                var contentPresenter = button.Template.FindName("PART_ContentPresenter", button) as ContentPresenter;
+                                if (contentPresenter != null)
+                                {
+                                    var rect = new Rect(button.PointToScreen(new Point()), new Size(button.ActualWidth * dpiX, button.ActualHeight * dpiX));
+                                    if (rect.Contains(new Point(x, y)))
+                                    {
+                                        handled = true;
+                                        contentPresenter.Opacity = 1;
+                                    }
+                                    else
+                                    {
+                                        contentPresenter.Opacity = 0.7;
+                                    }
+                                    return new IntPtr(OSVersionHelper.HTMAXBUTTON);
+                                }
+
+                            }
+                        }
+                    }
+                    catch (OverflowException)
+                    {
+                        handled = true;
+                    }
+                    break;
+                case WindowsMessageCodes.WM_NCLBUTTONDOWN:
+                    if (OSVersionHelper.IsSnapLayoutSupported()
+                        &&
+                        (ResizeMode != ResizeMode.NoResize
+                        ||
+                        ResizeMode != ResizeMode.CanMinimize))
+                    {
+                        int x = lParam.ToInt32() & 0xffff;
+                        int y = lParam.ToInt32() >> 16;
+                        var dpiX = OSVersionHelper.DeviceUnitsScalingFactorX;
+                        Button button = TitleBarMode == TitleBarMode.Normal
+                            ? (WindowState != WindowState.Maximized ? _titleBarMaximizeButton : _titleBarRestoreButton)
+                            : (WindowState != WindowState.Maximized ? _highTitleMaximizeButton : _highTitleRestoreButton);
+                        if (button != null)
+                        {
+                            var rect = new Rect(button.PointToScreen(
+                            new Point()),
+                            new Size(button.ActualWidth * dpiX, button.ActualHeight * dpiX));
+                            if (rect.Contains(new Point(x, y)))
+                            {
+                                handled = true;
+                                IInvokeProvider invokeProv = new ButtonAutomationPeer(button).GetPattern(PatternInterface.Invoke) as IInvokeProvider;
+                                invokeProv?.Invoke();
+                            }
+                        }
+                    }
+                    break;
+                #endregion
+                default:
+                    handled = false;
+                    break;
             }
             return IntPtr.Zero;
         }
diff --git a/src/WPFDevelopers.Net45x/Styles/Styles.TreeView.xaml b/src/WPFDevelopers.Net45x/Styles/Styles.TreeView.xaml
index bd2ac6d8..1073206e 100644
--- a/src/WPFDevelopers.Net45x/Styles/Styles.TreeView.xaml
+++ b/src/WPFDevelopers.Net45x/Styles/Styles.TreeView.xaml
@@ -157,13 +157,6 @@
         <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
         <Setter Property="Padding" Value="{Binding Padding, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}}" />
         <Setter Property="FocusVisualStyle" Value="{StaticResource WD.TreeViewItemFocusVisual}" />
-        <Setter Property="ItemsPanel">
-            <Setter.Value>
-                <ItemsPanelTemplate>
-                    <VirtualizingStackPanel />
-                </ItemsPanelTemplate>
-            </Setter.Value>
-        </Setter>
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="{x:Type TreeViewItem}">
@@ -247,6 +240,17 @@
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
+        <Style.Triggers>
+            <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="True">
+                <Setter Property="ItemsPanel">
+                    <Setter.Value>
+                        <ItemsPanelTemplate>
+                            <VirtualizingStackPanel />
+                        </ItemsPanelTemplate>
+                    </Setter.Value>
+                </Setter>
+            </Trigger>
+        </Style.Triggers>
     </Style>
 
     <Style BasedOn="{StaticResource WD.DefaultTreeView}" TargetType="{x:Type TreeView}" />
diff --git a/src/WPFDevelopers.Net45x/Themes/Generic.xaml b/src/WPFDevelopers.Net45x/Themes/Generic.xaml
index 1a031dd1..f1b35397 100644
--- a/src/WPFDevelopers.Net45x/Themes/Generic.xaml
+++ b/src/WPFDevelopers.Net45x/Themes/Generic.xaml
@@ -19,7 +19,6 @@
         <Setter Property="SnapsToDevicePixels" Value="True" />
         <Setter Property="UseLayoutRounding" Value="True" />
         <Setter Property="TextOptions.TextFormattingMode" Value="Ideal" />
-        <Setter Property="WindowStyle" Value="None" />
         <Setter Property="FontFamily" Value="{DynamicResource WD.FontFamily}" />
         <Setter Property="WindowChrome.WindowChrome">
             <Setter.Value>
@@ -32,11 +31,6 @@
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="{x:Type wd:Window}">
-                    <ControlTemplate.Resources>
-                        <Style TargetType="Grid">
-                            <Setter Property="Background" Value="Transparent" />
-                        </Style>
-                    </ControlTemplate.Resources>
                     <Border
                         Name="PART_Border"
                         Background="{TemplateBinding Background}"
@@ -48,10 +42,12 @@
                                 <RowDefinition Height="Auto" />
                                 <RowDefinition Height="*" />
                             </Grid.RowDefinitions>
-                            <control:SmallPanel
-                                x:Name="PART_Normal"
+                            <Border
                                 Grid.Row="0"
-                                Background="{TemplateBinding TitleBackground}">
+                                Margin="0,0,-1,0"
+                                HorizontalAlignment="Stretch"
+                                Background="{TemplateBinding TitleBackground}" />
+                            <control:SmallPanel x:Name="PART_Normal" Grid.Row="0">
                                 <Grid Height="{TemplateBinding TitleHeight}">
                                     <Grid.ColumnDefinitions>
                                         <ColumnDefinition Width="*" />
@@ -106,7 +102,7 @@
                                                 </Grid>
                                             </Button>
                                             <Button
-                                                Name="PART_TitleBarMaximizeButton"
+                                                x:Name="PART_TitleBarMaximizeButton"
                                                 Padding="0"
                                                 Command="SystemCommands.MaximizeWindowCommand"
                                                 IsTabStop="False"
@@ -125,7 +121,7 @@
                                                 </Grid>
                                             </Button>
                                             <Button
-                                                Name="PART_TitleBarRestoreButton"
+                                                x:Name="PART_TitleBarRestoreButton"
                                                 Padding="0"
                                                 Command="SystemCommands.RestoreWindowCommand"
                                                 IsTabStop="False"
@@ -167,7 +163,6 @@
                             <control:SmallPanel
                                 x:Name="PART_HighTitleBar"
                                 Grid.Row="0"
-                                Background="{TemplateBinding TitleBackground}"
                                 Visibility="Collapsed">
                                 <Grid
                                     x:Name="PART_GridChrome"
@@ -218,7 +213,7 @@
                                                 </Grid>
                                             </Button>
                                             <Button
-                                                Name="PART_MaximizeButton"
+                                                x:Name="PART_MaximizeButton"
                                                 Padding="0"
                                                 Command="SystemCommands.MaximizeWindowCommand"
                                                 IsTabStop="False"
@@ -237,7 +232,7 @@
                                                 </Grid>
                                             </Button>
                                             <Button
-                                                Name="PART_RestoreButton"
+                                                x:Name="PART_RestoreButton"
                                                 Padding="0"
                                                 Command="SystemCommands.RestoreWindowCommand"
                                                 IsTabStop="False"
diff --git a/src/WPFDevelopers.Net45x/Window.cs b/src/WPFDevelopers.Net45x/Window.cs
index 706d3ae2..c007ca95 100644
--- a/src/WPFDevelopers.Net45x/Window.cs
+++ b/src/WPFDevelopers.Net45x/Window.cs
@@ -1,5 +1,7 @@
 ﻿using System;
 using System.Windows;
+using System.Windows.Automation.Peers;
+using System.Windows.Automation.Provider;
 using System.Windows.Controls;
 using System.Windows.Input;
 using System.Windows.Interop;
@@ -7,16 +9,29 @@
 using WPFDevelopers.Controls;
 using WPFDevelopers.Core.Helpers;
 using WPFDevelopers.Helpers;
-using static WPFDevelopers.Core.Helpers.MonitorHelper;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
 
 namespace WPFDevelopers.Net45x
 {
     [TemplatePart(Name = TitleBarIcon, Type = typeof(Button))]
+    [TemplatePart(Name = HighTitleMaximizeButton, Type = typeof(Button))]
+    [TemplatePart(Name = HighTitleRestoreButton, Type = typeof(Button))]
+    [TemplatePart(Name = TitleBarMaximizeButton, Type = typeof(Button))]
+    [TemplatePart(Name = TitleBarRestoreButton, Type = typeof(Button))]
     public class Window : System.Windows.Window
     {
         private const string TitleBarIcon = "PART_TitleBarIcon";
+        private const string HighTitleMaximizeButton = "PART_MaximizeButton";
+        private const string HighTitleRestoreButton = "PART_RestoreButton";
+        private const string TitleBarMaximizeButton = "PART_TitleBarMaximizeButton";
+        private const string TitleBarRestoreButton = "PART_TitleBarRestoreButton";
         private WindowStyle _windowStyle;
         private Button _titleBarIcon;
+        private Button _highTitleMaximizeButton;
+        private Button _highTitleRestoreButton;
+        private Button _titleBarMaximizeButton;
+        private Button _titleBarRestoreButton;
+        private IntPtr hWnd;
 
         public static readonly DependencyProperty TitleHeightProperty =
             DependencyProperty.Register("TitleHeight", typeof(double), typeof(Window), new PropertyMetadata(50d));
@@ -41,7 +56,6 @@ static Window()
 
         public Window()
         {
-            Loaded += Window_Loaded;
             WPFDevelopers.Resources.ThemeChanged += Resources_ThemeChanged;
             CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, CloseWindow));
             CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, MaximizeWindow,
@@ -69,6 +83,10 @@ public override void OnApplyTemplate()
                 _titleBarIcon.MouseDoubleClick -= Icon_MouseDoubleClick;
                 _titleBarIcon.MouseDoubleClick += Icon_MouseDoubleClick;
             }
+            _highTitleMaximizeButton = GetTemplateChild(HighTitleMaximizeButton) as Button;
+            _highTitleRestoreButton = GetTemplateChild(HighTitleRestoreButton) as Button;
+            _titleBarMaximizeButton = GetTemplateChild(TitleBarMaximizeButton) as Button;
+            _titleBarRestoreButton = GetTemplateChild(TitleBarRestoreButton) as Button;
         }
 
         private void Icon_MouseDoubleClick(object sender, MouseButtonEventArgs e)
@@ -114,13 +132,13 @@ private static T GetResourceKey<T>(string key)
                 return resource;
             return default;
         }
-
-        private void Window_Loaded(object sender, RoutedEventArgs e)
+        protected override void OnSourceInitialized(EventArgs e)
         {
+            base.OnSourceInitialized(e);
             hWnd = new WindowInteropHelper(this).Handle;
             HwndSource.FromHwnd(hWnd).AddHook(WindowProc);
             if (TitleBarMode == TitleBarMode.Normal)
-                TitleHeight = SystemParameters.WindowNonClientFrameThickness.Top + SystemParameters.WindowResizeBorderThickness.Top; //32;//SystemParameters.WindowNonClientFrameThickness.Top;
+                TitleHeight = SystemParameters.WindowNonClientFrameThickness.Top + SystemParameters.WindowResizeBorderThickness.Top;
         }
 
         protected override void OnContentRendered(EventArgs e)
@@ -159,7 +177,7 @@ private void MaximizeWindow(object sender, ExecutedRoutedEventArgs e)
 
         private void MinimizeWindow(object sender, ExecutedRoutedEventArgs e)
         {
-            MonitorHelper.SendMessage(hWnd, MonitorHelper.WindowsMessageCodes.WM_SYSCOMMAND, new IntPtr(MonitorHelper.WindowsMessageCodes.SC_MINIMIZE), IntPtr.Zero);
+            Win32.SendMessage(hWnd, WindowsMessageCodes.WM_SYSCOMMAND, new IntPtr(WindowsMessageCodes.SC_MINIMIZE), IntPtr.Zero);
         }
 
         private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
@@ -167,9 +185,6 @@ private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
             SystemCommands.RestoreWindow(this);
         }
 
-
-        private IntPtr hWnd;
-
         private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
         {
             switch (msg)
@@ -192,9 +207,81 @@ private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, re
                         handled = true;
                     }
                     break;
+                #region SnapLayouts
+                case WindowsMessageCodes.WM_NCHITTEST:
+                    try
+                    {
+                        if (OSVersionHelper.IsSnapLayoutSupported() && ResizeMode != ResizeMode.NoResize && ResizeMode != ResizeMode.CanMinimize)
+                        {
+                            int x = lParam.ToInt32() & 0xffff;
+                            int y = lParam.ToInt32() >> 16;
+                            var dpiX = OSVersionHelper.DeviceUnitsScalingFactorX;
+                            var button = TitleBarMode == TitleBarMode.Normal
+                                ? (WindowState != WindowState.Maximized ? _titleBarMaximizeButton : _titleBarRestoreButton)
+                                : (WindowState != WindowState.Maximized ? _highTitleMaximizeButton : _highTitleRestoreButton);
+                            if (button != null)
+                            {
+                                var contentPresenter = button.Template.FindName("PART_ContentPresenter", button) as ContentPresenter;
+                                if (contentPresenter != null)
+                                {
+                                    var rect = new Rect(button.PointToScreen(new Point()),new Size(button.ActualWidth * dpiX, button.ActualHeight * dpiX));
+                                    if (rect.Contains(new Point(x, y)))
+                                    {
+                                        handled = true;
+                                        contentPresenter.Opacity = 1;
+                                    }
+                                    else
+                                    {
+                                        contentPresenter.Opacity = 0.7;
+                                    }
+                                    return new IntPtr(OSVersionHelper.HTMAXBUTTON);
+                                }
+
+                            }
+                        }
+                    }
+                    catch (OverflowException)
+                    {
+                        handled = true;
+                    }
+                    break;
+                case WindowsMessageCodes.WM_NCLBUTTONDOWN:
+                    if (OSVersionHelper.IsSnapLayoutSupported()
+                        &&
+                        (ResizeMode != ResizeMode.NoResize
+                        ||
+                        ResizeMode != ResizeMode.CanMinimize))
+                    {
+                        int x = lParam.ToInt32() & 0xffff;
+                        int y = lParam.ToInt32() >> 16;
+                        var dpiX = OSVersionHelper.DeviceUnitsScalingFactorX;
+                        Button button = TitleBarMode == TitleBarMode.Normal
+                            ? (WindowState != WindowState.Maximized ? _titleBarMaximizeButton : _titleBarRestoreButton)
+                            : (WindowState != WindowState.Maximized ? _highTitleMaximizeButton : _highTitleRestoreButton);
+                        if (button != null)
+                        {
+                            var rect = new Rect(button.PointToScreen(
+                            new Point()),
+                            new Size(button.ActualWidth * dpiX, button.ActualHeight * dpiX));
+                            if (rect.Contains(new Point(x, y)))
+                            {
+                                handled = true;
+                                IInvokeProvider invokeProv = new ButtonAutomationPeer(button).GetPattern(PatternInterface.Invoke) as IInvokeProvider;
+                                invokeProv?.Invoke();
+                            }
+                        }
+                    }
+                    break;
+                #endregion
+                default:
+                    handled = false;
+                    break;
             }
             return IntPtr.Zero;
         }
+
+
+
         private void ShowSystemMenu(object sender, ExecutedRoutedEventArgs e)
         {
             var element = e.OriginalSource as FrameworkElement;
@@ -210,5 +297,5 @@ private void ShowSystemMenu(object sender, ExecutedRoutedEventArgs e)
 
         #endregion
     }
-    
+
 }
\ No newline at end of file
diff --git a/src/WPFDevelopers.Samples.Shared/Controls/BubblleControl/BubbleControl.cs b/src/WPFDevelopers.Samples.Shared/Controls/BubblleControl/BubblleControl.cs
similarity index 100%
rename from src/WPFDevelopers.Samples.Shared/Controls/BubblleControl/BubbleControl.cs
rename to src/WPFDevelopers.Samples.Shared/Controls/BubblleControl/BubblleControl.cs
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/BasicControlsExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/BasicControlsExample.xaml
index 2aa7ff12..fb608303 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/BasicControlsExample.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/BasicControlsExample.xaml
@@ -561,6 +561,18 @@
                                         Binding="{Binding Address}"
                                         Header="Address"
                                         IsReadOnly="True" />
+                                    <DataGridTemplateColumn Width="*" Header="ContactMethod">
+                                        <DataGridTemplateColumn.CellEditingTemplate>
+                                            <DataTemplate>
+                                                <ComboBox ItemsSource="{x:Static local:BasicControlsExample.ContactMethods}" SelectedItem="{Binding ContactMethod, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
+                                            </DataTemplate>
+                                        </DataGridTemplateColumn.CellEditingTemplate>
+                                        <DataGridTemplateColumn.CellTemplate>
+                                            <DataTemplate>
+                                                <TextBlock Text="{Binding ContactMethod}" />
+                                            </DataTemplate>
+                                        </DataGridTemplateColumn.CellTemplate>
+                                    </DataGridTemplateColumn>
                                 </DataGrid.Columns>
                             </DataGrid>
                         </TabItem>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/BasicControlsExample.xaml.cs b/src/WPFDevelopers.Samples.Shared/ExampleViews/BasicControlsExample.xaml.cs
index d8e2b57c..6814fe90 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/BasicControlsExample.xaml.cs
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/BasicControlsExample.xaml.cs
@@ -31,6 +31,7 @@ public partial class BasicControlsExample : UserControl
             DependencyProperty.Register("AllSelected", typeof(bool), typeof(BasicControlsExample),
                 new PropertyMetadata(AllSelectedChangedCallback));
 
+        public static List<string> ContactMethods { get; } = new List<string> { "Tel", "Fax", "MB" };
         public BasicControlsExample()
         {
             InitializeComponent();
@@ -54,6 +55,7 @@ private void MainView_Loaded(object sender, RoutedEventArgs e)
                     Date = time,
                     Name = "WPFDevelopers",
                     Address = "One Microsoft Way, Redmond",
+                    ContactMethod = "MB",
                     Children = new List<UserModel>
                     {
                         new UserModel { Name = "WPFDevelopers1.1",Children=new List<UserModel>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/BubblleControlExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/BubblleControlExample.xaml
index 62c0bd91..c5e229da 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/BubblleControlExample.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/BubblleControlExample.xaml
@@ -100,15 +100,15 @@
             <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/BubblleControlExample.xaml" CodeType="Xaml" />
             <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/BubblleControlExample.xaml.cs" CodeType="CSharp" />
             <controls:SourceCodeModel
-                CodeSource="/WPFDevelopers.SamplesCode;component/BubblleControl/BubblleControl.cs"
+                CodeSource="/WPFDevelopers.SamplesCode;component/Controls/BubblleControl/BubblleControl.cs"
                 CodeType="CSharp"
                 Haader="BubblleControl.cs" />
             <controls:SourceCodeModel
-                CodeSource="/WPFDevelopers.SamplesCode;component/BubblleControl/BubblleCanvas.cs"
+                CodeSource="/WPFDevelopers.SamplesCode;component/Controls/BubblleControl/BubblleCanvas.cs"
                 CodeType="CSharp"
                 Haader="BubblleCanvas.cs" />
             <controls:SourceCodeModel
-                CodeSource="/WPFDevelopers.SamplesCode;component/BubblleControl/BubblleControl.xaml"
+                CodeSource="/WPFDevelopers.SamplesCode;component/Controls/BubblleControl/BubblleControl.xaml"
                 CodeType="Xaml"
                 Haader="BubblleControl.xaml" />
         </controls:CodeViewer.SourceCodes>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/DateRangePickerExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/DateRangePickerExample.xaml
index 1b84089a..3d83c0a5 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/DateRangePickerExample.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/DateRangePickerExample.xaml
@@ -33,6 +33,8 @@
                     wd:ElementHelper.IsClear="True"
                     EndDate="{Binding EndDate, RelativeSource={RelativeSource AncestorType=local:DateRangePickerExample}}"
                     EndWatermark="结束日期"
+                    MaxDate="2025-08-30"
+                    MinDate="2025-08-06"
                     StartDate="{Binding StartDate, RelativeSource={RelativeSource AncestorType=local:DateRangePickerExample}}"
                     StartWatermark="开始日期" />
                 <Button
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/GestureUnlockExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/GestureUnlockExample.xaml
new file mode 100644
index 00000000..0ffb74d8
--- /dev/null
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/GestureUnlockExample.xaml
@@ -0,0 +1,48 @@
+﻿<UserControl
+    x:Class="WPFDevelopers.Sample.ExampleViews.GestureUnlockExample"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
+    d:DesignHeight="450"
+    d:DesignWidth="800"
+    mc:Ignorable="d">
+    <controls:CodeViewer Header="{Binding NavigateMenuItem.Name}">
+        <TabControl TabStripPlacement="Bottom">
+            <TabItem Header="Event">
+                <wd:GestureUnlock
+                    x:Name="myGestureUnlock"
+                    wd:ElementHelper.CornerRadius="5"
+                    GestureCompleted="GestureCompleted">
+                    <wd:GestureUnlock.Background>
+                        <ImageBrush ImageSource="pack://application:,,,/WPFDevelopers.Samples;component/Resources/Images/Chat/Right.jpg" />
+                    </wd:GestureUnlock.Background>
+                </wd:GestureUnlock>
+            </TabItem>
+            <TabItem Header="Command">
+                <TabItem.Resources>
+                    <Style BasedOn="{StaticResource WD.GestureItem}" TargetType="wd:GestureItem">
+                        <Setter Property="BorderBrush" Value="Yellow" />
+                    </Style>
+                </TabItem.Resources>
+                <wd:GestureUnlock
+                    x:Name="myGestureUnlock2"
+                    Width="400"
+                    Height="500"
+                    wd:ElementHelper.CornerRadius="10"
+                    GestureCompletedCommand="{Binding GestureCompletedCommand, RelativeSource={RelativeSource AncestorType=UserControl}}">
+                    <wd:GestureUnlock.Background>
+                        <ImageBrush ImageSource="pack://application:,,,/WPFDevelopers.Samples;component/Resources/Images/IconicThumbnail/LcupqA.jpg" />
+                    </wd:GestureUnlock.Background>
+                </wd:GestureUnlock>
+            </TabItem>
+        </TabControl>
+        <controls:CodeViewer.SourceCodes>
+            <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/GestureUnlockExample.xaml" CodeType="Xaml" />
+            <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/GestureUnlockExample.xaml.cs" CodeType="CSharp" />
+        </controls:CodeViewer.SourceCodes>
+    </controls:CodeViewer>
+</UserControl>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/GestureUnlockExample.xaml.cs b/src/WPFDevelopers.Samples.Shared/ExampleViews/GestureUnlockExample.xaml.cs
new file mode 100644
index 00000000..b88ce27c
--- /dev/null
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/GestureUnlockExample.xaml.cs
@@ -0,0 +1,69 @@
+﻿using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using WPFDevelopers.Controls;
+using WPFDevelopers.Samples.Helpers;
+
+namespace WPFDevelopers.Sample.ExampleViews
+{
+    /// <summary>
+    /// GestureUnlockExample.xaml 的交互逻辑
+    /// </summary>
+    public partial class GestureUnlockExample : UserControl
+    {
+        private string _password = "0426";
+        private enum GestureUnlockType
+        {
+            Unlock1,
+            Unlock2
+        }
+        public GestureUnlockExample()
+        {
+            InitializeComponent();
+        }
+
+        private void HandleGestureUnlock(string pwd, GestureUnlockType unlockType)
+        {
+            if (pwd.Length < 4)
+            {
+                SetGestureState(unlockType, GestureState.Error);
+                Message.PushDesktop("手势错误，最少 4 个节点!", MessageBoxImage.Error, true);
+                return;
+            }
+
+            if (pwd != _password)
+            {
+                SetGestureState(unlockType, GestureState.Error);
+                Message.PushDesktop("手势错误，请重新解锁!", MessageBoxImage.Error, true);
+                return;
+            }
+
+            SetGestureState(unlockType, GestureState.Success);
+            Message.Push("手势正确!", MessageBoxImage.Information, true);
+        }
+
+        private void SetGestureState(GestureUnlockType unlockType, GestureState state)
+        {
+            if (unlockType == GestureUnlockType.Unlock1)
+            {
+                myGestureUnlock.State = state;
+            }
+            else if (unlockType == GestureUnlockType.Unlock2)
+            {
+                myGestureUnlock2.State = state;
+            }
+        }
+
+        private void GestureCompleted(object sender, RoutedEventArgs e)
+        {
+            var pwd = e.OriginalSource.ToString();
+            HandleGestureUnlock(pwd, GestureUnlockType.Unlock1);
+        }
+
+        public ICommand GestureCompletedCommand => new RelayCommand(param =>
+        {
+            var pwd = param.ToString();
+            HandleGestureUnlock(pwd, GestureUnlockType.Unlock2);
+        });
+    }
+}
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailExample.xaml
new file mode 100644
index 00000000..ded17743
--- /dev/null
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailExample.xaml
@@ -0,0 +1,18 @@
+﻿<UserControl
+    x:Class="WPFDevelopers.Sample.ExampleViews.IconicThumbnailExample"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    d:DesignHeight="450"
+    d:DesignWidth="800"
+    mc:Ignorable="d">
+    <controls:CodeViewer Header="{Binding NavigateMenuItem.Name}">
+        <controls:CodeViewer.SourceCodes>
+            <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/IconicThumbnailWindowExample.xaml" CodeType="Xaml" />
+            <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/IconicThumbnailWindowExample.xaml.cs" CodeType="CSharp" />
+        </controls:CodeViewer.SourceCodes>
+    </controls:CodeViewer>
+</UserControl>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailExample.xaml.cs b/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailExample.xaml.cs
new file mode 100644
index 00000000..856324a6
--- /dev/null
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailExample.xaml.cs
@@ -0,0 +1,15 @@
+﻿using System.Windows.Controls;
+
+namespace WPFDevelopers.Sample.ExampleViews
+{
+    /// <summary>
+    /// IconicThumbnailExample.xaml 的交互逻辑
+    /// </summary>
+    public partial class IconicThumbnailExample: UserControl
+    {
+        public IconicThumbnailExample()
+        {
+            InitializeComponent();
+        }
+    }
+}
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailWindowExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailWindowExample.xaml
new file mode 100644
index 00000000..266a9f25
--- /dev/null
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailWindowExample.xaml
@@ -0,0 +1,49 @@
+﻿<wd:Window
+    x:Class="WPFDevelopers.Sample.ExampleViews.IconicThumbnailWindowExample"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:converts="clr-namespace:WPFDevelopers.Sample.Converts"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:local="clr-namespace:WPFDevelopers.Sample.ExampleViews"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:model="clr-namespace:WPFDevelopers.Sample.Models"
+    xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
+    Title="IconicThumbnailWindowExample"
+    Width="600"
+    Height="450"
+    Icon="pack://application:,,,/WPFDevelopers.Samples;component/WPFDevelopers.ico"
+    WindowStartupLocation="CenterScreen"
+    mc:Ignorable="d">
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="7*" />
+            <RowDefinition Height="3*" />
+        </Grid.RowDefinitions>
+        <Image
+            x:Name="ImagePreview"
+            Width="200"
+            Height="200"
+            VerticalAlignment="Bottom" />
+        <StackPanel
+            Grid.Row="1"
+            HorizontalAlignment="Center"
+            VerticalAlignment="Center"
+            wd:PanelHelper.Spacing="3"
+            Orientation="Horizontal">
+            <Button
+                x:Name="BtnPrevious"
+                Width="50"
+                Height="50"
+                Click="BtnPrevious_Click">
+                <wd:PathIcon Width="10" Kind="Previous" />
+            </Button>
+            <Button
+                x:Name="BtnNext"
+                Width="50"
+                Height="50"
+                Click="BtnNext_Click">
+                <wd:PathIcon Width="10" Kind="Next" />
+            </Button>
+        </StackPanel>
+    </Grid>
+</wd:Window>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailWindowExample.xaml.cs b/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailWindowExample.xaml.cs
new file mode 100644
index 00000000..396d851f
--- /dev/null
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/IconicThumbnailWindowExample.xaml.cs
@@ -0,0 +1,50 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Windows;
+using System.Windows.Media.Imaging;
+using WPFDevelopers.Helpers;
+
+namespace WPFDevelopers.Sample.ExampleViews
+{
+    /// <summary>
+    /// IconicThumbnailWindowExample.xaml 的交互逻辑
+    /// </summary>
+    public partial class IconicThumbnailWindowExample
+    {
+        private List<string> fileList = new List<string>(); 
+        private int currentFileIndex = -1;
+        public IconicThumbnailWindowExample()
+        {
+            InitializeComponent();
+            Loaded += IconicThumbnailWindowExample_Loaded;
+        }
+
+        private void IconicThumbnailWindowExample_Loaded(object sender, RoutedEventArgs e)
+        {
+            fileList.Clear();
+            currentFileIndex = -1;
+            var directorys = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "IconicThumbnail");
+            if (!Directory.Exists(directorys)) return;
+            string[] files = Directory.GetFiles(directorys);
+            fileList.AddRange(files);
+        }
+
+        private void BtnPrevious_Click(object sender, RoutedEventArgs e)
+        {
+            if (fileList.Count == 0) return;
+            currentFileIndex = (currentFileIndex + 1) % fileList.Count;
+            var img = fileList[currentFileIndex];
+            ImagePreview.Source = new BitmapImage(new Uri(img));
+            this.SetIconicThumbnail(img);
+        }
+        private void BtnNext_Click(object sender, RoutedEventArgs e)
+        {
+            if (fileList.Count == 0) return;
+            currentFileIndex = (currentFileIndex - 1 + fileList.Count) % fileList.Count;
+            var img = fileList[currentFileIndex];
+            ImagePreview.Source = new BitmapImage(new Uri(img));
+            this.SetIconicThumbnail(img);
+        }
+    }
+}
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/CustomControl/InputBoxBase.cs b/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/CustomControl/InputBoxBase.cs
index 126f6446..00c9e120 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/CustomControl/InputBoxBase.cs
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/CustomControl/InputBoxBase.cs
@@ -73,7 +73,7 @@ private static void OnIconChanged(DependencyObject sender, DependencyPropertyCha
             {
                 try
                 {
-                    control.ApplyIcon(new BitmapImage(new Uri("pack://application:,,,/ExampleViews/LoginWindow/" + control.Icon)));
+                    control.ApplyIcon(new BitmapImage(new Uri("pack://application:,,,/WPFDevelopers.Samples;component/Resources/Assets/" + control.Icon)));
                 }
                 catch (Exception ex)
                 {
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/Generic.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/Generic.xaml
index dd97f639..e93d6a19 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/Generic.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/Generic.xaml
@@ -61,12 +61,6 @@
             </Style>
         <!-- 文本框样式 -->
             <Style x:Key="TextBoxStyle" TargetType="TextBox">
-                <!-- 选中底色 -->
-                <Setter Property="SelectionBrush" Value="#4370F5"/>
-                <!-- 选中底色透明度 -->
-                <Setter Property="SelectionOpacity" Value="1"/>
-                <!-- 选中文本色 -->
-                <Setter Property="SelectionBrush" Value="White"/>
                 <!-- 文本色 -->
                 <Setter Property="Foreground" Value="Black"/>
                 <!-- 文本垂直居中 -->
@@ -100,17 +94,11 @@
             </Style>
             <!-- 密码框样式 -->
             <Style x:Key="PasswordBoxStyle" TargetType="PasswordBox">
-                <!-- 选中底色 -->
-                <Setter Property="SelectionBrush" Value="#4370F5"/>
-                <!-- 选中底色透明度 -->
-                <Setter Property="SelectionOpacity" Value="1"/>
-                <!-- 选中文本色 -->
-                <Setter Property="SelectionBrush" Value="White"/>
                 <!-- 文本色 -->
                 <Setter Property="Foreground" Value="Black"/>
                 <!-- 文本垂直居中 -->
                 <Setter Property="VerticalContentAlignment" Value="Center"/>
-                <Setter Property="PasswordChar" Value="*"/>
+                <Setter Property="PasswordChar" Value="●"/>
                 <!-- 模板 -->
                 <Setter Property="Template">
                     <Setter.Value>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/LoginWindow.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/LoginWindow.xaml
index 3c55f863..a9f60a4f 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/LoginWindow.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/LoginWindow.xaml
@@ -1,29 +1,57 @@
-﻿<local:WindowBase x:Class="WPFDevelopers.Samples.ExampleViews.LoginWindowExample"
-        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-        xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
-        xmlns:cc="clr-namespace:WPFDevelopers.Samples.ExampleViews.LoginWindow.CustomControl"
-        mc:Ignorable="d"
-        Title="登录" Height="372" Width="360" ResizeMode="NoResize" WindowStyle="None"
-        FontFamily="NSimSun" FontSize="13px" WindowStartupLocation="CenterScreen"
-        Style="{StaticResource NormalWindow}" Loaded="Window_Loaded">
+﻿<local:WindowBase
+    x:Class="WPFDevelopers.Samples.ExampleViews.LoginWindowExample"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:cc="clr-namespace:WPFDevelopers.Samples.ExampleViews.LoginWindow.CustomControl"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    Title="登录"
+    Width="360"
+    Height="372"
+    FontFamily="NSimSun"
+    FontSize="13px"
+    Loaded="Window_Loaded"
+    ResizeMode="NoResize"
+    Style="{StaticResource NormalWindow}"
+    WindowStartupLocation="CenterScreen"
+    WindowStyle="None"
+    mc:Ignorable="d">
     <Grid>
-        <StackPanel VerticalAlignment="Top" Margin="40,40,40,0">
-            <!-- 邮箱输入框 -->
-            <cc:TextInputBox Height="40" PlaceHolder="邮箱" Icon="pack://application:,,,/WPFDevelopers.Samples;component/Resources/Assets/Mail.png"/>
-            <!-- 密码输入框 -->
-            <cc:PasswordInputBox Height="40" PlaceHolder="密码" Icon="pack://application:,,,/WPFDevelopers.Samples;component/Resources/Assets/Lock.png" Margin="0,20,0,0"/>
-            <!-- 登录按钮 -->
-            <Button x:Name="LoginButton" Content="登录" Height="40" Margin="0,20,0,0" Style="{StaticResource LoginButtonStyle}"/>
-            <!-- 可点击文本 -->
-            <Grid Margin="0 20 0 0">
+        <StackPanel Margin="40,40,40,0" VerticalAlignment="Top">
+            <!--  邮箱输入框  -->
+            <cc:TextInputBox
+                Height="40"
+                Icon="Mail.png"
+                PlaceHolder="邮箱" />
+            <!--  密码输入框  -->
+            <cc:PasswordInputBox
+                Height="40"
+                Margin="0,20,0,0"
+                Icon="Lock.png"
+                PlaceHolder="密码" />
+            <!--  登录按钮  -->
+            <Button
+                x:Name="LoginButton"
+                Height="40"
+                Margin="0,20,0,0"
+                Content="登录"
+                Style="{StaticResource LoginButtonStyle}" />
+            <!--  可点击文本  -->
+            <Grid Margin="0,20,0,0">
                 <TextBlock FontSize="12">
                     <Hyperlink Foreground="#A1A1A1" TextDecorations="None">忘记密码</Hyperlink>
                 </TextBlock>
-                <TextBlock FontSize="12" HorizontalAlignment="Right" Margin="0 0 -1 0">
-                    <Hyperlink Foreground="#4370F5" TextDecorations="None" Click="SignUp_Click" >注册账号</Hyperlink>
+                <TextBlock
+                    Margin="0,0,-1,0"
+                    HorizontalAlignment="Right"
+                    FontSize="12">
+                    <Hyperlink
+                        Click="SignUp_Click"
+                        Foreground="#4370F5"
+                        TextDecorations="None">
+                        注册账号
+                    </Hyperlink>
                 </TextBlock>
             </Grid>
         </StackPanel>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/SignUpDialog.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/SignUpDialog.xaml
index cb57cf69..e96446be 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/SignUpDialog.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/LoginWindow/SignUpDialog.xaml
@@ -22,19 +22,19 @@
             <!--  用户名输入框  -->
             <cc:TextInputBox
                 Height="40"
-                Icon="pack://application:,,,/WPFDevelopers.Samples;component/Resources/Assets/User.png"
+                Icon="User.png"
                 PlaceHolder="用户名" />
             <!--  邮箱输入框  -->
             <cc:TextInputBox
                 Height="40"
                 Margin="0,20,0,0"
-                Icon="pack://application:,,,/WPFDevelopers.Samples;component/Resources/Assets/Mail.png"
+                Icon="Mail.png"
                 PlaceHolder="邮箱" />
             <!--  密码输入框  -->
             <cc:PasswordInputBox
                 Height="40"
                 Margin="0,20,0,0"
-                Icon="pack://application:,,,/WPFDevelopers.Samples;component/Resources/Assets/Lock.png"
+                Icon="Lock.png"
                 PlaceHolder="密码" />
             <!--  注册按钮  -->
             <Button
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/MessageExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/MessageExample.xaml
index d97e07ef..3da9c6dc 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/MessageExample.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/MessageExample.xaml
@@ -55,6 +55,11 @@
                         Content="Long Message"
                         Style="{StaticResource WD.SuccessPrimaryButton}"
                         Tag="Long" />
+                    <Button
+                        Click="AddButton_Click"
+                        Content="IntPtr Window"
+                        Style="{StaticResource WD.SuccessPrimaryButton}"
+                        Tag="IntPtr" />
                     <Button Click="BtnClear_Click" Content="Clear" />
                 </UniformGrid>
             </GroupBox>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/MessageExample.xaml.cs b/src/WPFDevelopers.Samples.Shared/ExampleViews/MessageExample.xaml.cs
index 3d604e0f..ea32739b 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/MessageExample.xaml.cs
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/MessageExample.xaml.cs
@@ -1,6 +1,7 @@
 ﻿using System;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Interop;
 using WPFDevelopers.Controls;
 
 namespace WPFDevelopers.Samples.ExampleViews
@@ -42,6 +43,11 @@ private void AddButton_Click(object sender, RoutedEventArgs e)
                 case "Question":
                     Message.Push("This is a question message", MessageBoxImage.Question);
                     break;
+                case "IntPtr":
+                    Window parentWindow = Window.GetWindow(this);
+                    IntPtr windowHandle = new WindowInteropHelper(parentWindow).Handle;
+                    Message.Push(windowHandle, "This is a Handle message", MessageBoxImage.Question);
+                    break;
                 default:
                     Message.Push("这是一条很长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长消息", MessageBoxImage.Information);
                     break;
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/NavScrollPanelExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/NavScrollPanelExample.xaml
index 659a6b7b..c9b2224a 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/NavScrollPanelExample.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/NavScrollPanelExample.xaml
@@ -11,11 +11,33 @@
     d:DesignWidth="800"
     mc:Ignorable="d">
     <controls:CodeViewer Header="{Binding NavigateMenuItem.Name}">
-        <wd:NavScrollPanel
-            Padding="10"
-            wd:ElementHelper.CornerRadius="10"
-            BorderThickness="0"
-            ItemsSource="{Binding Items}" />
+        <TabControl TabStripPlacement="Bottom">
+            <TabItem Header="Xaml">
+                <wd:NavScrollPanel wd:ElementHelper.CornerRadius="10">
+                    <wd:NavScrollPanelItem Header="播放相关">
+                        <local:PlaybackSettings />
+                    </wd:NavScrollPanelItem>
+                    <wd:NavScrollPanelItem Header="桌面歌词">
+                        <local:DesktopLyrics />
+                    </wd:NavScrollPanelItem>
+                    <wd:NavScrollPanelItem Header="快捷键">
+                        <local:ShortcutKeys />
+                    </wd:NavScrollPanelItem>
+                    <wd:NavScrollPanelItem Header="隐私设置">
+                        <local:PrivacySettings />
+                    </wd:NavScrollPanelItem>
+                    <wd:NavScrollPanelItem Header="关于我们">
+                        <local:About />
+                    </wd:NavScrollPanelItem>
+                </wd:NavScrollPanel>
+            </TabItem>
+            <TabItem Header="Binding">
+                <wd:NavScrollPanel
+                    Padding="10"
+                    wd:ElementHelper.CornerRadius="10"
+                    ItemsSource="{Binding Items, RelativeSource={RelativeSource AncestorType=UserControl}}" />
+            </TabItem>
+        </TabControl>
         <controls:CodeViewer.SourceCodes>
             <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/NavScrollPanelExample.xaml" CodeType="Xaml" />
             <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/NavScrollPanelExample.xaml.cs" CodeType="CSharp" />
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/NavScrollPanelExample.xaml.cs b/src/WPFDevelopers.Samples.Shared/ExampleViews/NavScrollPanelExample.xaml.cs
index 3b4fe22a..444f35d7 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/NavScrollPanelExample.xaml.cs
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/NavScrollPanelExample.xaml.cs
@@ -15,13 +15,12 @@ public NavScrollPanelExample()
             InitializeComponent();
             Items = new ObservableCollection<NavScrollPanelItem>
             {
-                new NavScrollPanelItem{ Title = "播放相关", Content = new PlaybackSettings()},
-                new NavScrollPanelItem{ Title = "桌面歌词", Content = new DesktopLyrics()},
-                new NavScrollPanelItem{ Title = "快捷键", Content = new ShortcutKeys()},
-                new NavScrollPanelItem{ Title = "隐私设置", Content = new PrivacySettings()},
-                new NavScrollPanelItem{ Title = "关于我们", Content = new About()},
+                new NavScrollPanelItem{ Header = "播放相关", Content = new PlaybackSettings()},
+                new NavScrollPanelItem{ Header = "桌面歌词", Content = new DesktopLyrics()},
+                new NavScrollPanelItem{ Header = "快捷键", Content = new ShortcutKeys()},
+                new NavScrollPanelItem{ Header = "隐私设置", Content = new PrivacySettings()},
+                new NavScrollPanelItem{ Header = "关于我们", Content = new About()},
             };
-            DataContext = this;
         }
     }
 }
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/ScrollViewerAnimationExample.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/ScrollViewerAnimationExample.xaml
index d2867125..391c2f19 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/ScrollViewerAnimationExample.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/ScrollViewerAnimationExample.xaml
@@ -11,9 +11,6 @@
     d:DesignHeight="450"
     d:DesignWidth="800"
     mc:Ignorable="d">
-    <UserControl.DataContext>
-        <vm:MainVM />
-    </UserControl.DataContext>
     <controls:CodeViewer Header="{Binding NavigateMenuItem.Name}">
         <WrapPanel HorizontalAlignment="Center" VerticalAlignment="Center">
             <StackPanel>
diff --git a/src/WPFDevelopers.Samples.Shared/ExampleViews/UsageGuide.xaml b/src/WPFDevelopers.Samples.Shared/ExampleViews/UsageGuide.xaml
index 5f3be544..959d321c 100644
--- a/src/WPFDevelopers.Samples.Shared/ExampleViews/UsageGuide.xaml
+++ b/src/WPFDevelopers.Samples.Shared/ExampleViews/UsageGuide.xaml
@@ -12,32 +12,33 @@
     mc:Ignorable="d">
     <controls:CodeViewer Header="{Binding NavigateMenuItem.Name}">
         <Grid Margin="20" HorizontalAlignment="Center">
-            <StackPanel>
-                <TextBlock>
-                    <Run FontStretch="UltraExpanded" FontWeight="Bold">Step 1:</Run>
-                    <Run>Add nuget;</Run>
-                    <LineBreak />
-                </TextBlock>
-                <TextBox IsReadOnly="True">
-                    Install-Package WPFDevelopers -Version 1.1.0.3-preview3
-                </TextBox>
-                <TextBlock Margin="0,10,0,0">
-                    <Run FontStretch="UltraExpanded" FontWeight="Bold">Step 2:</Run>
-                    <Run>Add the Namespace in App.xaml</Run>
-                    <LineBreak />
-                </TextBlock>
-                <TextBox IsReadOnly="True">
-                    xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
-                </TextBox>
-                <TextBlock Margin="0,10,0,0">
-                    <Run FontStretch="UltraExpanded" FontWeight="Bold">Step 3:</Run>
-                    <Run>Add the Resources to App.xaml</Run>
-                    <LineBreak />
-                </TextBlock>
-                <TextBox
-                    xml:space="preserve"
-                    IsReadOnly="True"
-                    TextWrapping="Wrap">
+            <wd:WDScrollViewer IsScrollAnimation="True">
+                <StackPanel Margin="0,0,0,20">
+                    <TextBlock>
+                        <Run FontStretch="UltraExpanded" FontWeight="Bold">Step 1:</Run>
+                        <Run>Add nuget;</Run>
+                        <LineBreak />
+                    </TextBlock>
+                    <TextBox IsReadOnly="True">
+                        Install-Package WPFDevelopers -Version 1.1.0.3-preview3
+                    </TextBox>
+                    <TextBlock Margin="0,10,0,0">
+                        <Run FontStretch="UltraExpanded" FontWeight="Bold">Step 2:</Run>
+                        <Run>Add the Namespace in App.xaml</Run>
+                        <LineBreak />
+                    </TextBlock>
+                    <TextBox IsReadOnly="True">
+                        xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
+                    </TextBox>
+                    <TextBlock Margin="0,10,0,0">
+                        <Run FontStretch="UltraExpanded" FontWeight="Bold">Step 3:</Run>
+                        <Run>Add the Resources to App.xaml</Run>
+                        <LineBreak />
+                    </TextBlock>
+                    <TextBox
+                        xml:space="preserve"
+                        IsReadOnly="True"
+                        TextWrapping="Wrap">
                 &lt;Application.Resources&gt;
                     &lt;ResourceDictionary&gt;
                         &lt;ResourceDictionary.MergedDictionaries&gt;
@@ -51,7 +52,8 @@
                     &lt;/ResourceDictionary&gt;
                 &lt;/Application.Resources&gt;
             </TextBox>
-            </StackPanel>
+                </StackPanel>
+            </wd:WDScrollViewer>
         </Grid>
     </controls:CodeViewer>
 </UserControl>
diff --git a/src/WPFDevelopers.Samples.Shared/Helpers/MenuEnum.cs b/src/WPFDevelopers.Samples.Shared/Helpers/MenuEnum.cs
index 71f4a8d2..f5ab4b95 100644
--- a/src/WPFDevelopers.Samples.Shared/Helpers/MenuEnum.cs
+++ b/src/WPFDevelopers.Samples.Shared/Helpers/MenuEnum.cs
@@ -93,6 +93,8 @@ public enum MenuEnum
         Gauge,
         Tag,
         NavScrollPanel,
+        IconicThumbnail,
+        GestureUnlock,
         VirtualizingWrapPanel,
         AcrylicBlur,
         TaskbarInfo
diff --git a/src/WPFDevelopers.Samples.Shared/Helpers/RelayCommand.cs b/src/WPFDevelopers.Samples.Shared/Helpers/RelayCommand.cs
index 2f1deb74..abb62b98 100644
--- a/src/WPFDevelopers.Samples.Shared/Helpers/RelayCommand.cs
+++ b/src/WPFDevelopers.Samples.Shared/Helpers/RelayCommand.cs
@@ -8,6 +8,10 @@ public class RelayCommand : ICommand
         private readonly Func<object, bool> canExecuteFunc;
         private readonly Action<object> executeAction;
 
+        public RelayCommand()
+        {
+        }
+
         public RelayCommand(Action<object> execute)
             : this(execute, null)
         {
diff --git a/src/WPFDevelopers.Samples.Shared/Models/UserModel.cs b/src/WPFDevelopers.Samples.Shared/Models/UserModel.cs
index 07b173e7..6a282d31 100644
--- a/src/WPFDevelopers.Samples.Shared/Models/UserModel.cs
+++ b/src/WPFDevelopers.Samples.Shared/Models/UserModel.cs
@@ -21,6 +21,7 @@ public bool IsChecked
         public DateTime Date { get; set; }
         public string Name { get; set; }
         public string Address { get; set; }
+        public string ContactMethod { get; set; }
         public List<UserModel> Children { get; set; }
     }
 }
\ No newline at end of file
diff --git a/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/AUO2Bw.jpg b/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/AUO2Bw.jpg
new file mode 100644
index 00000000..b3efcecf
Binary files /dev/null and b/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/AUO2Bw.jpg differ
diff --git a/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/Ikcsk.jpg b/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/Ikcsk.jpg
new file mode 100644
index 00000000..d5cbc789
Binary files /dev/null and b/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/Ikcsk.jpg differ
diff --git a/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/LcupqA.jpg b/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/LcupqA.jpg
new file mode 100644
index 00000000..6941876b
Binary files /dev/null and b/src/WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail/LcupqA.jpg differ
diff --git a/src/WPFDevelopers.Samples.Shared/ViewModels/MainVM.cs b/src/WPFDevelopers.Samples.Shared/ViewModels/MainVM.cs
index 9b830873..073ae01a 100644
--- a/src/WPFDevelopers.Samples.Shared/ViewModels/MainVM.cs
+++ b/src/WPFDevelopers.Samples.Shared/ViewModels/MainVM.cs
@@ -384,6 +384,13 @@ void MenuItemSelection(string _menuName)
                 case MenuEnum.NavScrollPanel:
                     ControlPanel = new NavScrollPanelExample();
                     break;
+                case MenuEnum.IconicThumbnail:
+                    ControlPanel = new IconicThumbnailExample();
+                    new IconicThumbnailWindowExample().MaskShowDialog();
+                    break;
+                case MenuEnum.GestureUnlock:
+                    ControlPanel = new GestureUnlockExample();
+                    break;
                 case MenuEnum.VirtualizingWrapPanel:
                     ControlPanel = new VirtualizingWrapPanel();
                     new VirtualizingWrapPanelExample().MaskShowDialog();
diff --git a/src/WPFDevelopers.Samples.Shared/WPFDevelopers.Samples.Shared.projitems b/src/WPFDevelopers.Samples.Shared/WPFDevelopers.Samples.Shared.projitems
index 032cebf7..43b4d392 100644
--- a/src/WPFDevelopers.Samples.Shared/WPFDevelopers.Samples.Shared.projitems
+++ b/src/WPFDevelopers.Samples.Shared/WPFDevelopers.Samples.Shared.projitems
@@ -13,7 +13,7 @@
       <SubType>Code</SubType>
       <DependentUpon>App.xaml</DependentUpon>
     </Compile>
-    <Compile Include="$(MSBuildThisFileDirectory)Controls\BubblleControl\BubbleControl.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Controls\BubblleControl\BubblleControl.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\BubblleControl\BubblleCanvas.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\ChatEmoji\ChatEmoji.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\ChatEmoji\EmojiHelper.cs" />
@@ -67,6 +67,12 @@
       <SubType>Code</SubType>
       <DependentUpon>AnimationAudioExample.xaml</DependentUpon>
     </Compile>
+    <Compile Include="$(MSBuildThisFileDirectory)ExampleViews\IconicThumbnailExample.xaml.cs">
+      <DependentUpon>IconicThumbnailExample.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="$(MSBuildThisFileDirectory)ExampleViews\IconicThumbnailWindowExample.xaml.cs">
+      <DependentUpon>IconicThumbnailWindowExample.xaml</DependentUpon>
+    </Compile>
     <Compile Include="$(MSBuildThisFileDirectory)ExampleViews\NavMenu3DExample.xaml.cs">
       <SubType>Code</SubType>
       <DependentUpon>NavMenu3DExample.xaml</DependentUpon>
@@ -322,6 +328,9 @@
     <Compile Include="$(MSBuildThisFileDirectory)ExampleViews\NavScrollPanel\ShortcutKeys.xaml.cs">
       <DependentUpon>ShortcutKeys.xaml</DependentUpon>
     </Compile>
+    <Compile Include="$(MSBuildThisFileDirectory)ExampleViews\GestureUnlockExample.xaml.cs">
+      <DependentUpon>GestureUnlockExample.xaml</DependentUpon>
+    </Compile>
     <Compile Include="$(MSBuildThisFileDirectory)ExampleViews\TagExample.xaml.cs">
       <DependentUpon>TagExample.xaml</DependentUpon>
     </Compile>
@@ -611,6 +620,14 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="$(MSBuildThisFileDirectory)ExampleViews\IconicThumbnailExample.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
+    <Page Include="$(MSBuildThisFileDirectory)ExampleViews\IconicThumbnailWindowExample.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
     <Page Include="$(MSBuildThisFileDirectory)ExampleViews\NavMenu3DExample.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
@@ -892,6 +909,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="$(MSBuildThisFileDirectory)ExampleViews\GestureUnlockExample.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
     <Page Include="$(MSBuildThisFileDirectory)ExampleViews\TagExample.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
diff --git a/src/WPFDevelopers.Samples40/WPFDevelopers.Samples40.csproj b/src/WPFDevelopers.Samples40/WPFDevelopers.Samples40.csproj
index c891665f..876989b5 100644
--- a/src/WPFDevelopers.Samples40/WPFDevelopers.Samples40.csproj
+++ b/src/WPFDevelopers.Samples40/WPFDevelopers.Samples40.csproj
@@ -28,6 +28,6 @@
 	</PropertyGroup>
 	<Import Project="..\WPFDevelopers.Samples.Shared\WPFDevelopers.Samples.Shared.projitems" Label="Shared" />
 	<Target Name="PostBuild" AfterTargets="PostBuildEvent">
-		<Exec Command=" if not exist &quot;$(OutDir)emoji&quot; mkdir &quot;$(OutDir)emoji&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/emoji&quot; &quot;$(OutDir)emoji\&quot;&#xD;&#xA;&#xD;&#xA; if not exist &quot;$(OutDir)Audio&quot; mkdir &quot;$(OutDir)Audio&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/Audio&quot; &quot;$(OutDir)Audio\&quot;" />
+		<Exec Command=" if not exist &quot;$(OutDir)emoji&quot; mkdir &quot;$(OutDir)emoji&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/emoji&quot; &quot;$(OutDir)emoji\&quot;&#xD;&#xA;&#xD;&#xA; if not exist &quot;$(OutDir)Audio&quot; mkdir &quot;$(OutDir)Audio&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/Audio&quot; &quot;$(OutDir)Audio\&quot; &#xD;&#xA;&#xD;&#xA; if not exist &quot;$(OutDir)IconicThumbnail&quot; mkdir &quot;$(OutDir)IconicThumbnail&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail&quot; &quot;$(OutDir)IconicThumbnail\&quot;" />
 	</Target>
 </Project>
\ No newline at end of file
diff --git a/src/WPFDevelopers.Samples45x/WPFDevelopers.Samples45x.csproj b/src/WPFDevelopers.Samples45x/WPFDevelopers.Samples45x.csproj
index 161ae3e3..201371f4 100644
--- a/src/WPFDevelopers.Samples45x/WPFDevelopers.Samples45x.csproj
+++ b/src/WPFDevelopers.Samples45x/WPFDevelopers.Samples45x.csproj
@@ -7,6 +7,6 @@
 	</ItemGroup>
 	<Import Project="..\WPFDevelopers.Samples.Shared\WPFDevelopers.Samples.Shared.projitems" Label="Shared" />
 	<Target Name="PostBuild" AfterTargets="PostBuildEvent">
-	  <Exec Command=" if not exist &quot;$(OutDir)emoji&quot; mkdir &quot;$(OutDir)emoji&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/emoji&quot; &quot;$(OutDir)emoji\&quot;&#xD;&#xA;&#xD;&#xA; if not exist &quot;$(OutDir)Audio&quot; mkdir &quot;$(OutDir)Audio&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/Audio&quot; &quot;$(OutDir)Audio\&quot;" />
+	  <Exec Command=" if not exist &quot;$(OutDir)emoji&quot; mkdir &quot;$(OutDir)emoji&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/emoji&quot; &quot;$(OutDir)emoji\&quot;&#xD;&#xA;&#xD;&#xA; if not exist &quot;$(OutDir)Audio&quot; mkdir &quot;$(OutDir)Audio&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/Audio&quot; &quot;$(OutDir)Audio\&quot;&#xD;&#xA;&#xD;&#xA; if not exist &quot;$(OutDir)IconicThumbnail&quot; mkdir &quot;$(OutDir)IconicThumbnail&quot;&#xD;&#xA;&#xD;&#xA; copy &quot;$(SolutionDir)WPFDevelopers.Samples.Shared/Resources/Images/IconicThumbnail&quot; &quot;$(OutDir)IconicThumbnail\&quot;" />
 	</Target>
 </Project>
diff --git a/src/WPFDevelopers.Samples45x/WPFDevelopers.Samples45x.csproj.user b/src/WPFDevelopers.Samples45x/WPFDevelopers.Samples45x.csproj.user
index b5309f2d..ee8897e5 100644
--- a/src/WPFDevelopers.Samples45x/WPFDevelopers.Samples45x.csproj.user
+++ b/src/WPFDevelopers.Samples45x/WPFDevelopers.Samples45x.csproj.user
@@ -1,5 +1,7 @@
 ﻿<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup />
+  <PropertyGroup>
+    <ActiveDebugFramework>netcoreapp3.0</ActiveDebugFramework>
+  </PropertyGroup>
   <ItemGroup />
 </Project>
\ No newline at end of file
diff --git a/src/WPFDevelopers.SamplesCode/WPFDevelopers.SamplesCode.csproj b/src/WPFDevelopers.SamplesCode/WPFDevelopers.SamplesCode.csproj
index d66d4017..badc9c48 100644
--- a/src/WPFDevelopers.SamplesCode/WPFDevelopers.SamplesCode.csproj
+++ b/src/WPFDevelopers.SamplesCode/WPFDevelopers.SamplesCode.csproj
@@ -146,7 +146,7 @@
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\ChartLineExample.xaml.cs" Link="ExampleViews\ChartLineExample.xaml.cs" DependentUpon="ChartLineExample.xaml" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\ChartPieExample.xaml.cs" Link="ExampleViews\ChartPieExample.xaml.cs" DependentUpon="ChartPieExample.xaml" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\DrawerExample.xaml.cs" Link="ExampleViews\DrawerExample.xaml.cs" DependentUpon="DrawerExample.xaml" />
-		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\Loadings\StreamerLoading.cs" Link="Controls\Loadings\StreamerLoading.cs"/>
+		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\Loadings\StreamerLoading.cs" Link="Controls\Loadings\StreamerLoading.cs" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\DateRangePickerExample.xaml.cs" Link="ExampleViews\DateRangePickerExample.xaml.cs" DependentUpon="DateRangePickerExample.xaml" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\SpacingExample.xaml.cs" Link="ExampleViews\SpacingExample.xaml.cs" DependentUpon="SpacingExample.xaml" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\NotifyIconExample.xaml.cs" Link="ExampleViews\NotifyIconExample.xaml.cs" DependentUpon="NotifyIconExample.xaml" />
@@ -154,11 +154,13 @@
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\Window\NormalWindow.xaml.cs" Link="ExampleViews\Window\NormalWindow.xaml.cs" DependentUpon="NormalWindow.xaml" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\Window\HighTitleBarWindow.xaml.cs" Link="ExampleViews\Window\HighTitleBarWindow.xaml.cs" DependentUpon="HighTitleBarWindow.xaml" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\TagExample.xaml.cs" Link="ExampleViews\TagExample.xaml.cs" DependentUpon="TagExample.xaml" />
-		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\Theme\Theme.cs" Link="Controls\Theme\Theme.cs"/>
-		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\Theme\ThemeItem.cs" Link="Controls\Theme\ThemeItem.cs"/>
-		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\BubblleControl\BubbleControl.cs" Link="Controls\BubblleControl\BubbleControl.cs" />
+		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\Theme\Theme.cs" Link="Controls\Theme\Theme.cs" />
+		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\Theme\ThemeItem.cs" Link="Controls\Theme\ThemeItem.cs" />
+		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\BubblleControl\BubblleControl.cs" Link="Controls\BubblleControl\BubblleControl.cs" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\Controls\BubblleControl\BubblleCanvas.cs" Link="Controls\BubblleControl\BubblleCanvas.cs" />
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\NavScrollPanelExample.xaml.cs" Link="ExampleViews\NavScrollPanelExample.xaml.cs" DependentUpon="NavScrollPanelExample.xaml" />
+		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\IconicThumbnailWindowExample.xaml.cs" Link="ExampleViews\IconicThumbnailWindowExample.xaml.cs" DependentUpon="IconicThumbnailWindowExample.xaml" />
+		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\GestureUnlockExample.xaml.cs" Link="ExampleViews\GestureUnlockExample.xaml.cs" DependentUpon="GestureUnlockExample.xaml" />
 	</ItemGroup>
 	<ItemGroup>
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\AboutWindow.xaml">
@@ -542,5 +544,11 @@
 		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\NavScrollPanelExample.xaml">
 			<Link>ExampleViews\NavScrollPanelExample.xaml</Link>
 		</Resource>
+		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\IconicThumbnailWindowExample.xaml">
+			<Link>ExampleViews\IconicThumbnailWindowExample.xaml</Link>
+		</Resource>
+		<Resource Include="..\WPFDevelopers.Samples.Shared\ExampleViews\GestureUnlockExample.xaml">
+			<Link>ExampleViews\GestureUnlockExample.xaml</Link>
+		</Resource>
 	</ItemGroup>
 </Project>
diff --git a/src/WPFDevelopers.Shared/Controls/Badge/Badge.cs b/src/WPFDevelopers.Shared/Controls/Badge/Badge.cs
index 8b0f05b7..ee9788cd 100644
--- a/src/WPFDevelopers.Shared/Controls/Badge/Badge.cs
+++ b/src/WPFDevelopers.Shared/Controls/Badge/Badge.cs
@@ -172,18 +172,20 @@ private static void Parent_Loaded(object sender, RoutedEventArgs e)
 
         private static void CreateBadge(UIElement uIElement, bool isRemove = false)
         {
+            if (uIElement == null) return;
             var layer = AdornerLayer.GetAdornerLayer(uIElement);
             if (layer == null) return;
-            if (isRemove && uIElement != null)
+            var adorners = layer.GetAdorners(uIElement);
+            if (adorners != null)
             {
-                var adorners = layer.GetAdorners(uIElement);
-                if (adorners != null)
-                    foreach (var item in adorners)
-                        if (item is Badge container)
-                            layer.Remove(container);
-                return;
+                foreach (var item in adorners)
+                {
+                    if (item is Badge container)
+                        layer.Remove(container);
+                }
             }
-
+            if (isRemove)
+                return;
             var value = GetText(uIElement);
             var size = GetFontSize(uIElement);
             var horizontalOffset = GetHorizontalOffset(uIElement);
diff --git a/src/WPFDevelopers.Shared/Controls/BaseControls/WDUserControl.cs b/src/WPFDevelopers.Shared/Controls/BaseControls/WDUserControl.cs
new file mode 100644
index 00000000..25277dd5
--- /dev/null
+++ b/src/WPFDevelopers.Shared/Controls/BaseControls/WDUserControl.cs
@@ -0,0 +1,14 @@
+﻿using System.Windows;
+using System.Windows.Controls;
+
+namespace WPFDevelopers.Controls
+{
+    public class WDUserControl : ContentControl
+    {
+        static WDUserControl()
+        {
+            DefaultStyleKeyProperty.OverrideMetadata(typeof(WDUserControl),
+                new FrameworkPropertyMetadata(typeof(WDUserControl)));
+        }
+    }
+}
diff --git a/src/WPFDevelopers.Shared/Controls/DateRangePicker/DateRangePicker.cs b/src/WPFDevelopers.Shared/Controls/DateRangePicker/DateRangePicker.cs
index 81f39019..286afd7d 100644
--- a/src/WPFDevelopers.Shared/Controls/DateRangePicker/DateRangePicker.cs
+++ b/src/WPFDevelopers.Shared/Controls/DateRangePicker/DateRangePicker.cs
@@ -1,6 +1,5 @@
 ﻿using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.Linq;
 using System.Windows;
 using System.Windows.Controls;
@@ -61,16 +60,24 @@ public class DateRangePicker : Control
             DependencyProperty.Register(nameof(IsSyncingDisplayDate), typeof(bool), typeof(DateRangePicker),
                 new PropertyMetadata(false, OnIsSyncingDisplayDateChanged));
 
+        public static readonly DependencyProperty MinDateProperty =
+    DependencyProperty.Register("MinDate", typeof(DateTime?), typeof(DateRangePicker),
+        new PropertyMetadata(null, OnMinDateChanged));
+
+        public static readonly DependencyProperty MaxDateProperty =
+            DependencyProperty.Register("MaxDate", typeof(DateTime?), typeof(DateRangePicker),
+                    new PropertyMetadata(null, OnMaxDateChanged));
+
         private int _clickCount;
 
         private HwndSource _hwndSource;
-        private Window _window;
         private bool _isHandlingSelectionChange;
         private Popup _popup;
         private Calendar _startCalendar, _endCalendar;
         private IEnumerable<CalendarDayButton> _startCalendarDayButtons, _endCalendarDayButtons;
         private DateTime? _startDate, _endDate;
         private DatePickerTextBox _textBoxStart, _textBoxEnd;
+        private Window _window;
 
         static DateRangePicker()
         {
@@ -115,6 +122,18 @@ public bool IsSyncingDisplayDate
             set => SetValue(IsSyncingDisplayDateProperty, value);
         }
 
+        public DateTime? MinDate
+        {
+            get => (DateTime?)GetValue(MinDateProperty);
+            set => SetValue(MinDateProperty, value);
+        }
+
+        public DateTime? MaxDate
+        {
+            get => (DateTime?)GetValue(MaxDateProperty);
+            set => SetValue(MaxDateProperty, value);
+        }
+
         private static void OnStartDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
         {
             var ctrl = d as DateRangePicker;
@@ -157,6 +176,28 @@ protected virtual void OnIsSyncingDisplayDateChanged(bool oldValue, bool newValu
         {
         }
 
+        private static void OnMinDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            var control = (DateRangePicker)d;
+            if (control._startCalendar != null)
+                OnMinAndMaxChanged(control);
+        }
+
+        private static void OnMaxDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            var control = (DateRangePicker)d;
+            if (control._endCalendar != null)
+                OnMinAndMaxChanged(control);
+        }
+
+        static void OnMinAndMaxChanged(DateRangePicker control)
+        {
+            control._startCalendar.BlackoutDates.Add(new CalendarDateRange(DateTime.MinValue, control.MinDate.Value.AddDays(-1)));
+            control._endCalendar.BlackoutDates.Add(new CalendarDateRange(DateTime.MinValue, control.MinDate.Value.AddDays(-1)));
+            control._startCalendar.BlackoutDates.Add(new CalendarDateRange(control.MaxDate.Value.AddDays(1), DateTime.MaxValue));
+            control._endCalendar.BlackoutDates.Add(new CalendarDateRange(control.MaxDate.Value.AddDays(1), DateTime.MaxValue));
+        }
+
         public override void OnApplyTemplate()
         {
             base.OnApplyTemplate();
@@ -164,13 +205,16 @@ public override void OnApplyTemplate()
             if (_window != null)
             {
                 if (_window.IsInitialized)
+                {
                     WindowSourceInitialized(_window, EventArgs.Empty);
+                }
                 else
                 {
                     _window.SourceInitialized -= WindowSourceInitialized;
                     _window.SourceInitialized += WindowSourceInitialized;
                 }
             }
+
             _popup = (Popup)GetTemplateChild(PopupTemplateName);
             if (_popup != null)
             {
@@ -206,8 +250,23 @@ public override void OnApplyTemplate()
                 _endCalendar.PreviewMouseUp += OnEndCalendar_PreviewMouseUp;
             }
 
-            var now = DateTime.Now;
+            if (_startCalendar != null)
+            {
+                if (MinDate != null)
+                    _startCalendar.BlackoutDates.Add(new CalendarDateRange(DateTime.MinValue, MinDate.Value.AddDays(-1)));
+                if (MaxDate != null)
+                    _startCalendar.BlackoutDates.Add(new CalendarDateRange(MaxDate.Value.AddDays(1), DateTime.MaxValue));
+            }
+            if (_endCalendar != null)
+            {
+                if (MinDate != null)
+                    _endCalendar.BlackoutDates.Add(new CalendarDateRange(DateTime.MinValue, MinDate.Value.AddDays(-1)));
+                if (MaxDate != null)
+                    _endCalendar.BlackoutDates.Add(new CalendarDateRange(MaxDate.Value.AddDays(1), DateTime.MaxValue));
+            }
+            var now = MinDate == null ? DateTime.Now : MinDate.Value;
             var firstDayOfNextMonth = new DateTime(now.Year, now.Month, 1).AddMonths(1);
+            _startCalendar.DisplayDate = now;
             _startCalendar.DisplayDateEnd = firstDayOfNextMonth.AddDays(-1);
             _endCalendar.DisplayDate = firstDayOfNextMonth;
             _endCalendar.DisplayDateStart = firstDayOfNextMonth;
@@ -236,17 +295,16 @@ private void OnEndCalendar_PreviewMouseUp(object sender, MouseButtonEventArgs e)
                 var calendar = sender as Calendar;
                 if (e.OriginalSource is FrameworkElement fe)
                 {
-                    var dayButton = FindParent<CalendarDayButton>(fe);
+                    var dayButton = ControlsHelper.FindParent<CalendarDayButton>(fe);
                     if (dayButton != null && dayButton.DataContext is DateTime clickedDate)
-                    {
                         if (!calendar.SelectedDates.Contains(clickedDate))
                         {
                             var dateTime = clickedDate;
                             _startCalendar.SelectedDates.Clear();
                             ResetDate(dateTime);
                         }
-                    }
                 }
+
                 SetSelectedDates();
             }
             finally
@@ -265,17 +323,16 @@ private void OnStartCalendar_PreviewMouseUp(object sender, MouseButtonEventArgs
                 var calendar = sender as Calendar;
                 if (e.OriginalSource is FrameworkElement fe)
                 {
-                    var dayButton = FindParent<CalendarDayButton>(fe);
+                    var dayButton = ControlsHelper.FindParent<CalendarDayButton>(fe);
                     if (dayButton != null && dayButton.DataContext is DateTime clickedDate)
-                    {
                         if (!calendar.SelectedDates.Contains(clickedDate))
                         {
                             var dateTime = clickedDate;
                             _endCalendar.SelectedDates.Clear();
                             ResetDate(dateTime);
                         }
-                    }
                 }
+
                 SetSelectedDates();
             }
             finally
@@ -284,17 +341,6 @@ private void OnStartCalendar_PreviewMouseUp(object sender, MouseButtonEventArgs
             }
         }
 
-        private T FindParent<T>(DependencyObject child) where T : DependencyObject
-        {
-            var parent = VisualTreeHelper.GetParent(child);
-            if (parent == null) return null;
-
-            if (parent is T tParent)
-                return tParent;
-
-            return FindParent<T>(parent);
-        }
-
         private void OnBorder_PreviewMouseUp(object sender, MouseButtonEventArgs e)
         {
             if (e.OriginalSource is Button button)
@@ -308,7 +354,7 @@ private void TextBoxEnd_TextChanged(object sender, TextChangedEventArgs e)
             UpdateEndDateFromTextBox();
         }
 
-        void UpdateEndDateFromTextBox()
+        private void UpdateEndDateFromTextBox()
         {
             if (_textBoxEnd != null)
             {
@@ -318,6 +364,7 @@ void UpdateEndDateFromTextBox()
                     SetIsHighlightFalse(_startCalendarDayButtons);
                     return;
                 }
+
                 if (DateTime.TryParse(_textBoxEnd.Text, out var dateTime))
                 {
                     if (EndDate.HasValue && dateTime.ToString(DateFormat) == EndDate.Value.ToString(DateFormat))
@@ -346,7 +393,7 @@ private void TextBoxStart_TextChanged(object sender, TextChangedEventArgs e)
             UpdateStartDateFromTextBox();
         }
 
-        void UpdateStartDateFromTextBox()
+        private void UpdateStartDateFromTextBox()
         {
             if (_textBoxStart != null)
             {
@@ -356,6 +403,7 @@ void UpdateStartDateFromTextBox()
                     SetIsHighlightFalse(_startCalendarDayButtons);
                     return;
                 }
+
                 if (DateTime.TryParse(_textBoxStart.Text, out var dateTime))
                 {
                     if (StartDate.HasValue && dateTime.ToString(DateFormat) == StartDate.Value.ToString(DateFormat))
@@ -398,10 +446,7 @@ private void WindowSourceInitialized(object sender, EventArgs e)
             if (window != null)
             {
                 _hwndSource = PresentationSource.FromVisual(window) as HwndSource;
-                if (_hwndSource != null)
-                {
-                    _hwndSource.AddHook(WndProc);
-                }
+                if (_hwndSource != null) _hwndSource.AddHook(WndProc);
             }
         }
 
@@ -416,6 +461,7 @@ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref b
                 _startCalendar.SelectedDate = null;
                 _endCalendar.SelectedDate = null;
             }
+
             return IntPtr.Zero;
         }
 
@@ -448,6 +494,7 @@ private void PopupOpened()
                 if (prevBtn != null)
                     prevBtn.Visibility = Visibility.Collapsed;
             }
+
             if (StartDate.HasValue)
                 _startDate = StartDate.Value;
             if (EndDate.HasValue)
@@ -476,6 +523,7 @@ private void OnEndCalendar_DisplayDateChanged(object sender, CalendarDateChanged
                         _startCalendar.DisplayDateEnd = target.AddMonths(1).AddDays(-1);
                 }
             }
+
             if (!_startDate.HasValue || !_endDate.HasValue)
                 return;
             SetIsHighlightFalse(_endCalendarDayButtons);
@@ -488,7 +536,6 @@ private void OnStartCalendar_DisplayDateChanged(object sender, CalendarDateChang
         {
             if (_endCalendar != null)
             {
-                
                 var selectedDate = _endCalendar.DisplayDate;
                 var target = _startCalendar.DisplayDate.AddMonths(1);
                 if (_endCalendar.DisplayDate.Year != target.Year
@@ -504,15 +551,14 @@ private void OnStartCalendar_DisplayDateChanged(object sender, CalendarDateChang
                     if (!IsSyncingDisplayDate)
                         _endCalendar.DisplayDateStart = target;
                 }
-
             }
+
             if (!_startDate.HasValue || !_endDate.HasValue)
                 return;
             SetIsHighlightFalse(_startCalendarDayButtons);
             var isYearMonthBetween = IsYearMonthBetween(e.AddedDate.Value, _startDate.Value, _endDate.Value);
-            if(isYearMonthBetween)
+            if (isYearMonthBetween)
                 SetIsHighlight(_endDate.Value);
-
         }
 
         private void OnCalendar_PreviewMouseUp(object sender, MouseButtonEventArgs e)
@@ -592,6 +638,7 @@ private void SetSelectedDates(DateTime? endDate = null)
                     _startDate = _endDate.Value;
                     _endDate = temp;
                 }
+
                 _startCalendar.SelectedDates.Clear();
                 _endCalendar.SelectedDates.Clear();
                 var eDate = _endDate;
@@ -600,10 +647,7 @@ private void SetSelectedDates(DateTime? endDate = null)
                 _startCalendar.SelectedDates.AddRange(_startDate.Value, eDate.Value);
                 _endCalendar.SelectedDates.AddRange(_startDate.Value, eDate.Value);
                 SetIsHighlight(eDate.Value);
-                if (_clickCount == 2)
-                {
-                    SetDate();
-                }
+                if (_clickCount == 2) SetDate();
             }
         }
 
@@ -616,14 +660,15 @@ private void SetIsHighlight(DateTime endDate)
                 if (_startCalendarDayButtons != null)
                 {
                     var day = _startCalendarDayButtons.FirstOrDefault(x =>
-                    x.DataContext is DateTime buttonDate && buttonDate.Date == date.Date);
+                        x.DataContext is DateTime buttonDate && buttonDate.Date == date.Date);
                     if (day != null)
-                    {
                         if (day.DataContext is DateTime dt)
-                            DatePickerHelper.SetIsHighlight(day, (dt.Month == _startCalendar.DisplayDate.Month && dt.Year == _startCalendar.DisplayDate.Year));
-                    }
+                            DatePickerHelper.SetIsHighlight(day,
+                                dt.Month == _startCalendar.DisplayDate.Month &&
+                                dt.Year == _startCalendar.DisplayDate.Year);
                 }
             }
+
             foreach (var date in _endCalendar.SelectedDates)
             {
                 if (date.Date == endDate.Date || date.Date <= _startDate.Value.Date)
@@ -633,10 +678,9 @@ private void SetIsHighlight(DateTime endDate)
                     var day = _endCalendarDayButtons.FirstOrDefault(x =>
                         x.DataContext is DateTime buttonDate && buttonDate.Date == date.Date);
                     if (day != null)
-                    {
                         if (day.DataContext is DateTime dt)
-                            DatePickerHelper.SetIsHighlight(day, (dt.Month == _endCalendar.DisplayDate.Month && dt.Year == _endCalendar.DisplayDate.Year));
-                    }
+                            DatePickerHelper.SetIsHighlight(day,
+                                dt.Month == _endCalendar.DisplayDate.Month && dt.Year == _endCalendar.DisplayDate.Year);
                 }
             }
         }
@@ -681,6 +725,7 @@ private Button GetButtonFromCalendar(Calendar calendar, bool isNext)
                 if (button != null)
                     return button;
             }
+
             return null;
         }
     }
diff --git a/src/WPFDevelopers.Shared/Controls/Gauge/Gauge.cs b/src/WPFDevelopers.Shared/Controls/Gauge/Gauge.cs
index 4839eb9c..bd6b0d81 100644
--- a/src/WPFDevelopers.Shared/Controls/Gauge/Gauge.cs
+++ b/src/WPFDevelopers.Shared/Controls/Gauge/Gauge.cs
@@ -7,38 +7,16 @@ namespace WPFDevelopers.Controls
 {
     public class Gauge : RangeBase
     {
-        public string Title
-        {
-            get { return (string)GetValue(TitleProperty); }
-            set { SetValue(TitleProperty, value); }
-        }
-
         public static readonly DependencyProperty TitleProperty =
             DependencyProperty.Register("TitleProperty", typeof(string), typeof(Gauge), new PropertyMetadata("WD"));
 
         public static readonly DependencyProperty ValueFormatProperty =
-       DependencyProperty.Register("ValueFormat", typeof(string), typeof(Gauge),
-           new PropertyMetadata("{0:0}%", OnValueFormatChanged));
-
-        private static void OnValueFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
-        {
-            var gauge = d as Gauge;
-            gauge?.InvalidateVisual();
-        }
-
-        public string ValueFormat
-        {
-            get { return (string)GetValue(ValueFormatProperty); }
-            set { SetValue(ValueFormatProperty, value); }
-        }
-        public double Thickness
-        {
-            get { return (double)GetValue(ThicknessProperty); }
-            set { SetValue(ThicknessProperty, value); }
-        }
+            DependencyProperty.Register("ValueFormat", typeof(string), typeof(Gauge),
+                new PropertyMetadata("{0:0}%", OnValueFormatChanged));
 
         public static readonly DependencyProperty ThicknessProperty =
-            DependencyProperty.Register("Thickness", typeof(double), typeof(Gauge), new PropertyMetadata(10.0, OnValueFormatChanged));
+            DependencyProperty.Register("Thickness", typeof(double), typeof(Gauge),
+                new PropertyMetadata(10.0, OnValueFormatChanged));
 
 
         static Gauge()
@@ -53,6 +31,30 @@ public Gauge()
             SetValue(MaximumProperty, 100.0);
         }
 
+        public string Title
+        {
+            get => (string) GetValue(TitleProperty);
+            set => SetValue(TitleProperty, value);
+        }
+
+        public string ValueFormat
+        {
+            get => (string) GetValue(ValueFormatProperty);
+            set => SetValue(ValueFormatProperty, value);
+        }
+
+        public double Thickness
+        {
+            get => (double) GetValue(ThicknessProperty);
+            set => SetValue(ThicknessProperty, value);
+        }
+
+        private static void OnValueFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            var gauge = d as Gauge;
+            gauge?.InvalidateVisual();
+        }
+
         protected override void OnValueChanged(double oldValue, double newValue)
         {
             InvalidateVisual();
@@ -67,32 +69,36 @@ protected override void OnMaximumChanged(double oldValue, double newValue)
         {
             InvalidateVisual();
         }
+
         protected override void OnRender(DrawingContext drawingContext)
         {
             base.OnRender(drawingContext);
             if (Background == null)
-                Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#293950"));
+                Background = new SolidColorBrush((Color) ColorConverter.ConvertFromString("#293950"));
             var width = ActualWidth;
             var height = ActualHeight;
             var radius = Math.Min(width, height) / 2;
-            drawingContext.DrawEllipse(Background, new Pen(Background, Thickness), new Point(width / 2, height / 2), radius, radius);
+            drawingContext.DrawEllipse(Background, new Pen(Background, Thickness), new Point(width / 2, height / 2),
+                radius, radius);
             var normalizedValue = (Value - Minimum) / (Maximum - Minimum);
             var mappedAngle = -220 + normalizedValue * 260;
             var angleInRadians = mappedAngle * Math.PI / 180;
             var pointerLength = radius * 0.7;
             var pointerX = width / 2 + pointerLength * Math.Cos(angleInRadians);
             var pointerY = height / 2 + pointerLength * Math.Sin(angleInRadians);
-            drawingContext.DrawLine(new Pen(Brushes.Red, 2), new Point(width / 2, height / 2), new Point(pointerX, pointerY));
-            drawingContext.DrawEllipse(Brushes.White, new Pen(Brushes.Red, 2), new Point(width / 2, height / 2), width / 20, width / 20);
+            drawingContext.DrawLine(new Pen(Brushes.Red, 2), new Point(width / 2, height / 2),
+                new Point(pointerX, pointerY));
+            drawingContext.DrawEllipse(Brushes.White, new Pen(Brushes.Red, 2), new Point(width / 2, height / 2),
+                width / 20, width / 20);
             var pathGeometry = new PathGeometry();
             var startAngle = -220;
             angleInRadians = startAngle * Math.PI / 180;
             var startX = width / 2 + radius * Math.Cos(angleInRadians);
             var startY = height / 2 + radius * Math.Sin(angleInRadians);
 
-            var pathFigure = new PathFigure()
+            var pathFigure = new PathFigure
             {
-                StartPoint = new Point(startX, startY),
+                StartPoint = new Point(startX, startY)
             };
 
             var endAngle = 40;
@@ -100,14 +106,14 @@ protected override void OnRender(DrawingContext drawingContext)
             var endX = width / 2 + radius * Math.Cos(angleInRadians);
             var endY = height / 2 + radius * Math.Sin(angleInRadians);
 
-            var isLargeArc = (endAngle - startAngle > 180);
-            var arcSegment = new ArcSegment()
+            var isLargeArc = endAngle - startAngle > 180;
+            var arcSegment = new ArcSegment
             {
                 Point = new Point(endX, endY),
                 Size = new Size(radius, radius),
                 RotationAngle = 0,
                 SweepDirection = SweepDirection.Clockwise,
-                IsLargeArc = isLargeArc,
+                IsLargeArc = isLargeArc
             };
 
             pathFigure.Segments.Add(arcSegment);
@@ -119,33 +125,40 @@ protected override void OnRender(DrawingContext drawingContext)
                     StartPoint = new Point(0, 0),
                     EndPoint = new Point(1, 0)
                 };
-                gradientBrush.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#37D2C2"), 0.0));
-                gradientBrush.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#5AD2B2"), 0.01));
-                gradientBrush.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#B77D29"), 0.49));
+                gradientBrush.GradientStops.Add(new GradientStop((Color) ColorConverter.ConvertFromString("#37D2C2"),
+                    0.0));
+                gradientBrush.GradientStops.Add(new GradientStop((Color) ColorConverter.ConvertFromString("#5AD2B2"),
+                    0.01));
+                gradientBrush.GradientStops.Add(new GradientStop((Color) ColorConverter.ConvertFromString("#B77D29"),
+                    0.49));
                 gradientBrush.GradientStops.Add(new GradientStop(Colors.Red, 1.0));
                 gradientBrush.Freeze();
                 BorderBrush = gradientBrush;
             }
+
             drawingContext.DrawGeometry(null, new Pen(BorderBrush, Thickness), pathGeometry);
-            var tickLength = radius * 0.1; 
+            var tickLength = radius * 0.1;
             var step = (Maximum - Minimum) / 10;
-            for (int i = 0; i <= 10; i++)
+            for (var i = 0; i <= 10; i++)
             {
-                var angle = startAngle + (i * (endAngle - startAngle) / 10);
+                var angle = startAngle + i * (endAngle - startAngle) / 10;
                 var tickStartX = width / 2 + (radius - tickLength) * Math.Cos(angle * Math.PI / 180);
                 var tickStartY = height / 2 + (radius - tickLength) * Math.Sin(angle * Math.PI / 180);
                 var tickEndX = width / 2 + (radius + Thickness / 2) * Math.Cos(angle * Math.PI / 180);
                 var tickEndY = height / 2 + (radius + Thickness / 2) * Math.Sin(angle * Math.PI / 180);
-                drawingContext.DrawLine(new Pen(Brushes.White, 2), new Point(tickStartX, tickStartY), new Point(tickEndX, tickEndY));
+                drawingContext.DrawLine(new Pen(Brushes.White, 2), new Point(tickStartX, tickStartY),
+                    new Point(tickEndX, tickEndY));
 
                 var labelValue = Minimum + step * i;
-                var formattedText = DrawingContextHelper.GetFormattedText(labelValue.ToString(),Brushes.White, FlowDirection.LeftToRight,FontSize);
+                var formattedText = DrawingContextHelper.GetFormattedText(labelValue.ToString(), Brushes.White,
+                    FlowDirection.LeftToRight, FontSize);
 
                 var labelRadius = radius - tickLength * 2;
                 var labelX = width / 2 + labelRadius * Math.Cos(angle * Math.PI / 180) - formattedText.Width / 2;
                 var labelY = height / 2 + labelRadius * Math.Sin(angle * Math.PI / 180) - formattedText.Height / 2;
                 drawingContext.DrawText(formattedText, new Point(labelX, labelY));
             }
+
             var formattedValue = "{0:0}%";
             try
             {
@@ -155,15 +168,17 @@ protected override void OnRender(DrawingContext drawingContext)
             {
                 throw new InvalidOperationException("Formatting failed ", ex);
             }
-            var currentValueText = DrawingContextHelper.GetFormattedText(formattedValue, Brushes.White, FlowDirection.LeftToRight, FontSize * 2);
+
+            var currentValueText = DrawingContextHelper.GetFormattedText(formattedValue, Brushes.White,
+                FlowDirection.LeftToRight, FontSize * 2);
             var valueX = width / 2 - currentValueText.Width / 2;
-            var valueY = height / 2 + radius * 0.4; 
+            var valueY = height / 2 + radius * 0.4;
             drawingContext.DrawText(currentValueText, new Point(valueX, valueY));
-            var titleValue = DrawingContextHelper.GetFormattedText(Title, Brushes.White, FlowDirection.LeftToRight, FontSize);
+            var titleValue =
+                DrawingContextHelper.GetFormattedText(Title, Brushes.White, FlowDirection.LeftToRight, FontSize);
             valueX = width / 2 - titleValue.Width / 2;
             valueY = height / 2 + radius * 0.8;
             drawingContext.DrawText(titleValue, new Point(valueX, valueY));
         }
-
     }
-}
+}
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Controls/GestureUnlock/GestureItem.cs b/src/WPFDevelopers.Shared/Controls/GestureUnlock/GestureItem.cs
new file mode 100644
index 00000000..95ea6e27
--- /dev/null
+++ b/src/WPFDevelopers.Shared/Controls/GestureUnlock/GestureItem.cs
@@ -0,0 +1,32 @@
+﻿using System.Windows;
+using System.Windows.Controls;
+
+namespace WPFDevelopers.Controls
+{
+    public class GestureItem : Control
+    {
+        public static readonly DependencyProperty NumberProperty =
+            DependencyProperty.Register("Number", typeof(int), typeof(GestureItem), new PropertyMetadata(0));
+
+        public static readonly DependencyProperty IsSelectedProperty =
+            DependencyProperty.Register("IsSelected", typeof(bool), typeof(GestureItem), new PropertyMetadata(false));
+
+        static GestureItem()
+        {
+            DefaultStyleKeyProperty.OverrideMetadata(typeof(GestureItem),
+                new FrameworkPropertyMetadata(typeof(GestureItem)));
+        }
+
+        public int Number
+        {
+            get => (int) GetValue(NumberProperty);
+            set => SetValue(NumberProperty, value);
+        }
+
+        public bool IsSelected
+        {
+            get => (bool) GetValue(IsSelectedProperty);
+            set => SetValue(IsSelectedProperty, value);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Controls/GestureUnlock/GestureUnlock.cs b/src/WPFDevelopers.Shared/Controls/GestureUnlock/GestureUnlock.cs
new file mode 100644
index 00000000..49eaf60d
--- /dev/null
+++ b/src/WPFDevelopers.Shared/Controls/GestureUnlock/GestureUnlock.cs
@@ -0,0 +1,327 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Shapes;
+using System.Windows.Threading;
+using WPFDevelopers.Helpers;
+
+namespace WPFDevelopers.Controls
+{
+    [TemplatePart(Name = CanvasTemplateName, Type = typeof(Canvas))]
+    public class GestureUnlock : Control
+    {
+        private const string CanvasTemplateName = "PART_GestureUnlockCanvas";
+
+        public static readonly DependencyProperty PasswordProperty =
+            DependencyProperty.Register("Password", typeof(string), typeof(GestureUnlock),
+                new PropertyMetadata(string.Empty));
+
+        public static readonly DependencyProperty StateProperty =
+            DependencyProperty.Register("State", typeof(GestureState), typeof(GestureUnlock),
+                new PropertyMetadata(GestureState.None, OnIsErrorChanged));
+
+        public static readonly DependencyProperty GestureCompletedCommandProperty =
+            DependencyProperty.Register("GestureCompletedCommand", typeof(ICommand), typeof(GestureUnlock),
+                new PropertyMetadata(null));
+
+
+        public static readonly RoutedEvent GestureCompletedEvent =
+            EventManager.RegisterRoutedEvent("GestureCompleted", RoutingStrategy.Bubble, typeof(RoutedEventHandler),
+                typeof(GestureUnlock));
+
+        private Canvas _canvas;
+
+        private readonly List<GestureItem> _gestureItems = new List<GestureItem>();
+        private readonly List<int> _gestures = new List<int>();
+        private Polyline _line;
+        private Line _moveLine;
+        private double _thickness = 1;
+        private DispatcherTimer _timer;
+        private bool _tracking;
+        private bool _isEventHandled = false;
+
+        static GestureUnlock()
+        {
+            DefaultStyleKeyProperty.OverrideMetadata(typeof(GestureUnlock),
+                new FrameworkPropertyMetadata(typeof(GestureUnlock)));
+        }
+
+        public GestureUnlock()
+        {
+            SizeChanged -= GestureUnlock_SizeChanged;
+            SizeChanged += GestureUnlock_SizeChanged;
+        }
+
+        public string Password
+        {
+            get => (string) GetValue(PasswordProperty);
+            set => SetValue(PasswordProperty, value);
+        }
+
+        public GestureState State
+        {
+            get => (GestureState) GetValue(StateProperty);
+            set => SetValue(StateProperty, value);
+        }
+
+        public ICommand GestureCompletedCommand
+        {
+            get => (ICommand) GetValue(GestureCompletedCommandProperty);
+            set => SetValue(GestureCompletedCommandProperty, value);
+        }
+
+        private static void OnIsErrorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            var ctrl = d as GestureUnlock;
+            if (ctrl != null)
+            {
+                ctrl.UpdateLineStroke();
+                switch (ctrl.State)
+                {
+                    case GestureState.Success:
+                    case GestureState.Error:
+                        if (ctrl._timer == null)
+                        {
+                            ctrl._timer = new DispatcherTimer
+                            {
+                                Interval = TimeSpan.FromSeconds(1.5)
+                            };
+                            ctrl._timer.Tick += (sender, args) =>
+                            {
+                                ctrl._timer.Stop();
+                                ctrl.CleraGestureAndLine();
+                            };
+                        }
+
+                        ctrl._timer.Start();
+                        break;
+                }
+            }
+        }
+
+
+        public event RoutedEventHandler GestureCompleted
+        {
+            add => AddHandler(GestureCompletedEvent, value);
+            remove => RemoveHandler(GestureCompletedEvent, value);
+        }
+
+
+        public override void OnApplyTemplate()
+        {
+            base.OnApplyTemplate();
+            _canvas = GetTemplateChild(CanvasTemplateName) as Canvas;
+            if (_canvas != null)
+            {
+                _canvas.MouseDown -= OnCanvas_MouseDown;
+                _canvas.MouseDown += OnCanvas_MouseDown;
+                _canvas.MouseMove -= OnCanvas_MouseMove;
+                _canvas.MouseMove += OnCanvas_MouseMove;
+                _canvas.MouseUp -= OnCanvas_MouseUp;
+                _canvas.MouseUp += OnCanvas_MouseUp;
+                Loaded += (s, e) => CreateGestureItems();
+            }
+        }
+
+        protected override void OnMouseLeave(MouseEventArgs e)
+        {
+            base.OnMouseLeave(e);
+            if (_tracking && !_isEventHandled)
+            {
+                _isEventHandled = true; 
+                CompleteGesture();
+            }
+            _tracking = false;
+            _isEventHandled = false;
+        }
+
+        private void CleraGestureAndLine()
+        {
+            State = GestureState.None;
+            _gestureItems.ForEach(x => { x.IsSelected = false; });
+            _gestures.Clear();
+            _line.Points.Clear();
+            _isEventHandled = false;
+        }
+
+        private void ResetMoveLine()
+        {
+            if (_moveLine != null)
+            {
+                _canvas.Children.Remove(_moveLine);
+                _moveLine = null;
+            }
+            _moveLine = new Line
+            {
+                Stroke = _gestureItems.Count > 0 ? _gestureItems[0].BorderBrush : ThemeManager.Instance.PrimaryBrush,
+                StrokeThickness = _thickness > 1 ? _thickness - 1 : _thickness
+            };
+        }
+
+        private void GestureUnlock_SizeChanged(object sender, SizeChangedEventArgs e)
+        {
+            CreateGestureItems();
+        }
+
+        private void CreateGestureItems()
+        {
+            _gestureItems.Clear();
+            _canvas.Children.Clear();
+            double radius = 20d;
+            int cols = 3; 
+            int rows = 3; 
+            double gap = (300 - (3 * radius * 2)) / 4; 
+            gap = Math.Max(gap, radius);
+            double totalWidth = (3 * radius * 2) + (2 * gap);
+            double totalHeight = (3 * radius * 2) + (2 * gap);
+            double startX = (ActualWidth - totalWidth) / 2 + radius;
+            double startY = (ActualHeight - totalHeight) / 2 + radius;
+            for (int i = 0; i < 9; i++)
+            {
+                int col = i % cols;
+                int row = i / rows;
+                double x = startX + col * (gap + radius * 2);
+                double y = startY + row * (gap + radius * 2);
+                var gestureItem = new GestureItem();
+                gestureItem.Number = i;
+                gestureItem.Loaded += (s, e) =>
+                {
+                    double actualRadius = Math.Max(gestureItem.ActualWidth, gestureItem.ActualHeight) / 2;
+                    Canvas.SetLeft(gestureItem, x - actualRadius);
+                    Canvas.SetTop(gestureItem, y - actualRadius);
+                    ElementHelper.SetCornerRadius(gestureItem, new CornerRadius(actualRadius));
+                };
+                _canvas.Children.Add(gestureItem);
+                _gestureItems.Add(gestureItem);
+            }
+            _line = new Polyline
+            {
+                Stroke = _gestureItems.Count > 0 ? _gestureItems[0].BorderBrush : ThemeManager.Instance.PrimaryBrush,
+                StrokeThickness = _thickness
+            };
+            _canvas.Children.Add(_line);
+            Panel.SetZIndex(_line, -98);
+            ResetMoveLine();
+        }
+
+        private void OnCanvas_MouseUp(object sender, MouseButtonEventArgs e)
+        {
+            if (!_isEventHandled)
+            {
+                _tracking = false;
+                _isEventHandled = true; 
+                CompleteGesture();
+            }
+        }
+
+        void CompleteGesture()
+        {
+            if (_gestures.Count == 0) return;
+            Password = string.Join("", _gestures);
+            GestureCompletedCommand?.Execute(Password);
+            RaiseEvent(new RoutedEventArgs(GestureCompletedEvent, Password));
+            ResetMoveLine();
+        }
+
+        private void OnCanvas_MouseMove(object sender, MouseEventArgs e)
+        {
+            if (_tracking && e.LeftButton == MouseButtonState.Pressed)
+            {
+                var point = e.GetPosition(_canvas);
+                if (_moveLine.X2 == 0 && _moveLine.Y1 == 0)
+                {
+                    _moveLine.X1 = point.X;
+                    _moveLine.Y1 = point.Y;
+                }
+                if (_moveLine.X2 != point.X)
+                    _moveLine.X2 = point.X;
+                if (_moveLine.Y2 != point.Y)
+                    _moveLine.Y2 = point.Y;
+                TryAddPoint(point);
+            }
+        }
+
+        private void OnCanvas_MouseDown(object sender, MouseButtonEventArgs e)
+        {
+            CleraGestureAndLine();
+            if (_timer != null)
+                _timer.Stop();
+            ResetMoveLine();
+            _tracking = true;
+            _isEventHandled = false;
+            var point = e.GetPosition(_canvas);
+            TryAddPoint(point);
+        }
+
+        private void TryAddPoint(Point position)
+        {
+            for (var i = 0; i < _gestureItems.Count; i++)
+            {
+                var gestureItem = _gestureItems[i];
+                var left = Canvas.GetLeft(gestureItem);
+                var top = Canvas.GetTop(gestureItem);
+                var centerX = left + gestureItem.Width / 2;
+                var centerY = top + gestureItem.Height / 2;
+                var dist = (position - new Point(centerX, centerY)).Length;
+                if (dist <= gestureItem.Width / 2 && !_gestures.Contains(i))
+                {
+                    if(_gestures.Count == 1)
+                    {
+                        var brush = _gestureItems.Count > 0 ? _gestureItems[0].BorderBrush : ThemeManager.Instance.PrimaryBrush;
+                        _line.Stroke = brush;
+                        _moveLine.Stroke = brush;
+                    }
+                    _gestures.Add(i);
+                    _line.Points.Add(new Point(centerX, centerY));
+                    gestureItem.IsSelected = true;
+                    if (_moveLine.X1 == 0 
+                        && 
+                        _moveLine.Y1 == 0
+                        &&
+                        _moveLine.X2 == 0 
+                        && 
+                        _moveLine.Y2 == 0)
+                    {
+                        _moveLine.X1 = centerX;
+                        _moveLine.Y1 = centerY;
+                        _canvas.Children.Add(_moveLine);
+                    }
+                    else
+                    {
+                        var endPoint = _line.Points.LastOrDefault();
+                        _moveLine.X1 = endPoint.X;
+                        _moveLine.Y1 = endPoint.Y;
+                    }
+
+                    Panel.SetZIndex(_moveLine, -99);
+                    _moveLine.X2 = centerX;
+                    _moveLine.Y2 = centerY;
+                    break;
+                }
+            }
+        }
+
+        private void UpdateLineStroke()
+        {
+            if (_line == null)
+                return;
+
+            switch (State)
+            {
+                case GestureState.Success:
+                    _line.Stroke = ThemeManager.Instance.Resources.TryFindResource<Brush>("WD.SuccessBrush");
+                    break;
+                case GestureState.Error:
+                    _line.Stroke = ThemeManager.Instance.Resources.TryFindResource<Brush>("WD.DangerBrush");
+                    break;
+                default:
+                    _line.Stroke = _gestureItems.Count > 0 ? _gestureItems[0].BorderBrush : ThemeManager.Instance.PrimaryBrush;
+                    break;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Controls/Loading/Loading.cs b/src/WPFDevelopers.Shared/Controls/Loading/Loading.cs
index f14b28f7..3c4ed41c 100644
--- a/src/WPFDevelopers.Shared/Controls/Loading/Loading.cs
+++ b/src/WPFDevelopers.Shared/Controls/Loading/Loading.cs
@@ -70,11 +70,12 @@ private static void Parent_Loaded(object sender, RoutedEventArgs e)
 
         private static void CreateLoading(UIElement uIElement, bool isRemove = false)
         {
+            if (uIElement == null) return;
             UIElement value = null;
             var layer = AdornerLayer.GetAdornerLayer(uIElement);
             if (layer == null) return;
             var adorners = layer.GetAdorners(uIElement);
-            if (isRemove || adorners != null)
+            if (adorners != null)
             {
                 foreach (var item in adorners)
                 {
@@ -87,6 +88,8 @@ private static void CreateLoading(UIElement uIElement, bool isRemove = false)
                     }
                 }
             }
+            if (isRemove)
+                return;
             var adornerContainer = new AdornerContainer(uIElement);
             var type = GetLoadingType(uIElement);
             var isLoading = GetIsShow(uIElement);
diff --git a/src/WPFDevelopers.Shared/Controls/Mask/Mask.cs b/src/WPFDevelopers.Shared/Controls/Mask/Mask.cs
index ee820295..6b741828 100644
--- a/src/WPFDevelopers.Shared/Controls/Mask/Mask.cs
+++ b/src/WPFDevelopers.Shared/Controls/Mask/Mask.cs
@@ -50,18 +50,20 @@ private static void Parent_Loaded(object sender, RoutedEventArgs e)
 
         private static void CreateMask(UIElement uIElement, bool isRemove = false)
         {
+            if (uIElement == null) return;
             var layer = AdornerLayer.GetAdornerLayer(uIElement);
             if (layer == null) return;
-            if (isRemove && uIElement != null)
+            var adorners = layer.GetAdorners(uIElement);
+            if (adorners != null)
             {
-                var adorners = layer.GetAdorners(uIElement);
-                if (adorners != null)
-                    foreach (var item in adorners)
-                        if (item is AdornerContainer container)
-                            layer.Remove(container);
-                return;
+                foreach (var item in adorners)
+                {
+                    if (item is AdornerContainer container)
+                        layer.Remove(container);
+                }
             }
-
+            if (isRemove)
+                return;
             var adornerContainer = new AdornerContainer(uIElement);
             var value = GetChild(uIElement);
             if (value != null)
diff --git a/src/WPFDevelopers.Shared/Controls/Message/Message.cs b/src/WPFDevelopers.Shared/Controls/Message/Message.cs
index ac3963ba..3e834265 100644
--- a/src/WPFDevelopers.Shared/Controls/Message/Message.cs
+++ b/src/WPFDevelopers.Shared/Controls/Message/Message.cs
@@ -40,16 +40,22 @@ static void CreateMessageAdorner(Window owner = null, string message = null, Mes
                 throw;
             }
         }
+
         public static void Push(this Window owner, string message, MessageBoxImage type = MessageBoxImage.Information, bool center = false)
         {
             CreateMessageAdorner(owner, message, type, center);
         }
+
         public static void Push(string message, MessageBoxImage type = MessageBoxImage.Information, bool center = false)
         {
             CreateMessageAdorner(message: message, type: type, center: center);
         }
+        public static void Push(IntPtr intPtr, string message, MessageBoxImage type = MessageBoxImage.Information, bool center = false)
+        {
+            PushDesktop(message, type, center, intPtr);
+        }
 
-        public static void PushDesktop(string message, MessageBoxImage type = MessageBoxImage.Information, bool center = false)
+        public static void PushDesktop(string message, MessageBoxImage type = MessageBoxImage.Information, bool center = false, IntPtr intPtr = default)
         {
             if (_messageExt == null)
             {
@@ -63,13 +69,15 @@ public static void PushDesktop(string message, MessageBoxImage type = MessageBox
                 _messageExt.IsPosition = false;
                 _messageExt.Position = _position;
             }
-            _messageExt.Push(message, type, center); 
+            _messageExt.Push(message, type, center, intPtr);
         }
+
         public static void SetPosition(Position position = Position.Top)
         {
             if (_position != position)
                 _position = position;
         }
+
         public static void Clear()
         {
             if(_messageAdorner != null)
diff --git a/src/WPFDevelopers.Shared/Controls/Message/MessageExt.cs b/src/WPFDevelopers.Shared/Controls/Message/MessageExt.cs
index a6a14774..30efe064 100644
--- a/src/WPFDevelopers.Shared/Controls/Message/MessageExt.cs
+++ b/src/WPFDevelopers.Shared/Controls/Message/MessageExt.cs
@@ -1,6 +1,7 @@
 ﻿using System;
 using System.Windows;
 using System.Windows.Media;
+using WPFDevelopers.Helpers;
 
 namespace WPFDevelopers.Controls
 {
@@ -30,43 +31,76 @@ public MessageExt()
             }
            
         }
-        
-        internal void Push(string message, MessageBoxImage type = MessageBoxImage.Information, bool center = false)
+
+        internal void Push(string message, MessageBoxImage type = MessageBoxImage.Information,
+                  bool center = false, IntPtr intPtr = default)
         {
-            var desktopWorkingArea = SystemParameters.WorkArea;
-            var item = new MessageListBoxItem { Content = message, MessageType = type, IsCenter = center };
-            _listBox.Items.Insert(0, item);
+            Rect targetArea = GetTargetArea(intPtr);
+            var messageItem = new MessageListBoxItem
+            {
+                Content = message,
+                MessageType = type,
+                IsCenter = center
+            };
+            _listBox.Items.Insert(0, messageItem);
             if (!IsPosition || Position == Position.Bottom)
             {
-                double x = 0;
-                double y = 0;
-                switch (Position)
-                {
-                    case Position.Top:
-                        x = (desktopWorkingArea.Right - item.Width) / 2;
-                        break;
-                    case Position.Right:
-                        x = desktopWorkingArea.Right - (item.Width + item.Margin.Right + item.Padding.Right);
-                        break;
-                    case Position.Bottom:
-                        x = (desktopWorkingArea.Right - item.Width) / 2;
-                        _listBox.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
-                        var controlHeight = _listBox.DesiredSize.Height;
-                        y = desktopWorkingArea.Height - controlHeight;
-                        break;
-                }
-                Height = desktopWorkingArea.Height;
-                Left = x;
-                Top = y;
+                CalculateAndSetPosition(targetArea, messageItem);
                 IsPosition = true;
             }
         }
+
+        private Rect GetTargetArea(IntPtr windowHandle)
+        {
+            if (windowHandle != IntPtr.Zero)
+            {
+                IsPosition = false;
+                return WindowHelpers.GetWindowBounds(windowHandle);
+            }
+            return SystemParameters.WorkArea;
+        }
+
+        private void CalculateAndSetPosition(Rect targetArea, MessageListBoxItem item)
+        {
+            double x = 0;
+            double y = 0;
+
+            switch (Position)
+            {
+                case Position.Left:
+                    x = targetArea.Left + item.Margin.Left;
+                    y = targetArea.Top;
+                    break;
+
+                case Position.Top:
+                    x = targetArea.Left + (targetArea.Width - item.Width) / 2;
+                    y = targetArea.Top;
+                    break;
+
+                case Position.Right:
+                    x = targetArea.Right - (item.Width + item.Margin.Right + item.Padding.Right);
+                    y = targetArea.Top;
+                    break;
+
+                case Position.Bottom:
+                    x = targetArea.Left + (targetArea.Width - item.Width) / 2;
+                    _listBox.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+                    y = targetArea.Bottom - _listBox.DesiredSize.Height;
+                    break;
+            }
+
+            Height = targetArea.Height;
+            Left = x;
+            Top = y;
+        }
+
         internal void Clear() 
         {
             if(_listBox!=null)
                 _listBox.Items.Clear();
             Close();
         }
+
         private void ListBox_SizeChanged(object sender, SizeChangedEventArgs e)
         {
             if(_listBox.ActualHeight <= 10)
diff --git a/src/WPFDevelopers.Shared/Controls/MultiSelectComboBox/MultiSelectComboBox.cs b/src/WPFDevelopers.Shared/Controls/MultiSelectComboBox/MultiSelectComboBox.cs
index ce4f384d..ed7ca6c1 100644
--- a/src/WPFDevelopers.Shared/Controls/MultiSelectComboBox/MultiSelectComboBox.cs
+++ b/src/WPFDevelopers.Shared/Controls/MultiSelectComboBox/MultiSelectComboBox.cs
@@ -1,6 +1,7 @@
 ﻿using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Collections.Specialized;
 using System.ComponentModel;
 using System.Linq;
 using System.Runtime.InteropServices;
@@ -95,6 +96,7 @@ public static readonly DependencyProperty MaxDropDownHeightProperty
         private CheckBox _checkBox;
         private string _theLastText;
         private ItemsPresenter _itemsPresenter;
+        private bool _isUpdating;
 
         private List<object> selectedItems;
         private List<object> selectedList;
@@ -188,7 +190,7 @@ private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedE
         }
 
         public virtual void OnTextChanged(string oldValue, string newValue)
-        { 
+        {
         }
 
         protected override bool IsItemItsOwnContainerOverride(object item)
@@ -217,11 +219,23 @@ protected override void OnSelectionChanged(SelectionChangedEventArgs e)
                 {
                     SelectedItems.Remove(item);
                 }
-                if (SelectedItemsExt is IList list)
+                if (!_isUpdating && SelectedItemsExt != null)
                 {
-                    list.Clear();
-                    foreach (var itm in SelectedItems.Cast<object>())
-                        list.Add(itm);
+                    _isUpdating = true;
+                    try
+                    {
+                        if (SelectedItemsExt is IList list)
+                        {
+                            if(list.Count > 0)
+                                list.Clear();
+                            foreach (var itm in SelectedItems.Cast<object>())
+                                list.Add(itm);
+                        }
+                    }
+                    finally
+                    {
+                        _isUpdating = false;
+                    }
                 }
                 SelectionChecked(this);
             }
@@ -235,7 +249,6 @@ protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable n
                 ApplySearchLogic();
         }
 
-
         public override void OnApplyTemplate()
         {
             base.OnApplyTemplate();
@@ -295,6 +308,20 @@ public override void OnApplyTemplate()
                 _panel = GetTemplateChild(PART_SimpleWrapPanel) as Panel;
             }
         }
+        public MultiSelectComboBox()
+        {
+            IsVisibleChanged += OnMultiSelectComboBox_IsVisibleChanged;
+        }
+
+        private void OnMultiSelectComboBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
+        {
+            if (Visibility == Visibility.Visible)
+            {
+                InvalidateMeasure();
+                InvalidateArrange();
+                UpdateLayout();
+            }
+        }
 
         private void ApplySearchLogic()
         {
@@ -512,6 +539,7 @@ private void SearchText(string text)
 
         private void SelectionChecked(ListBox listbox)
         {
+            if (_checkBox == null) return;
             if (listbox.SelectedItems.Count > 0
                 &&
                 listbox.Items.Count == listbox.SelectedItems.Count)
@@ -661,29 +689,64 @@ protected object GetItemDisplayValue(object item)
 
         private static void OnSelectedItemsExtChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
         {
-            var multiSelectComboBox = d as MultiSelectComboBox;
-            if (multiSelectComboBox == null) return;
+            var ctrl = d as MultiSelectComboBox;
+            if (ctrl == null) return;
+            if (e.OldValue is INotifyCollectionChanged oldCollection)
+                oldCollection.CollectionChanged -= ctrl.OnSelectedItemsExtCollectionChanged;
             if (e.NewValue != null)
             {
+                if (e.NewValue is INotifyCollectionChanged newCollection)
+                {
+                    ctrl.SelectedItemsExt = (IList)newCollection;
+                    newCollection.CollectionChanged += ctrl.OnSelectedItemsExtCollectionChanged;
+                }
                 var collection = e.NewValue as IList;
                 if (collection.Count <= 0) return;
-                multiSelectComboBox.SelectedItems.Clear();
+                ctrl.SelectedItems.Clear();
+                ctrl._isUpdating = true;
                 foreach (var item in collection)
                 {
-                    var name = multiSelectComboBox.GetPropertyValue(item);
+                    var name = ctrl.GetPropertyValue(item);
                     object model = null;
                     if (!string.IsNullOrWhiteSpace(name))
-                        model = multiSelectComboBox.ItemsSource.OfType<object>().FirstOrDefault(h =>
-                            multiSelectComboBox.GetPropertyValue(h) == name);
+                        model = ctrl.ItemsSource.OfType<object>().FirstOrDefault(h =>
+                            ctrl.GetPropertyValue(h) == name);
                     else
-                        model = multiSelectComboBox.ItemsSource.OfType<object>()
+                        model = ctrl.ItemsSource.OfType<object>()
                             .FirstOrDefault(h => h == item);
-                    if (model != null && !multiSelectComboBox.SelectedItems.Contains(item))
-                        multiSelectComboBox.SelectedItems.Add(model);
+                    if (model != null && !ctrl.SelectedItems.Contains(item))
+                        ctrl.SelectedItems.Add(model);
 
                 }
-                multiSelectComboBox.UpdateText();
+                ctrl._isUpdating = false;
+                ctrl.UpdateText();
+            }
+        }
+
+        private void OnSelectedItemsExtCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+        {
+            if (_isUpdating) return;
+            if (e.Action == NotifyCollectionChangedAction.Reset)
+                SelectedItems.Clear();
+            _isUpdating = true;
+            if (e.OldItems != null)
+            {
+                foreach (var item in e.OldItems)
+                {
+                    if (SelectedItems.Contains(item))
+                        SelectedItems.Remove(item);
+                }
+            }
+
+            if (e.NewItems != null)
+            {
+                foreach (var item in e.NewItems)
+                {
+                    if (!SelectedItems.Contains(item))
+                        SelectedItems.Add(item);
+                }
             }
+            _isUpdating = false;
         }
     }
     public enum ShowType
diff --git a/src/WPFDevelopers.Shared/Controls/NavScrollPanel/NavScrollPanel.cs b/src/WPFDevelopers.Shared/Controls/NavScrollPanel/NavScrollPanel.cs
index 89b1dbe9..2fe84dfb 100644
--- a/src/WPFDevelopers.Shared/Controls/NavScrollPanel/NavScrollPanel.cs
+++ b/src/WPFDevelopers.Shared/Controls/NavScrollPanel/NavScrollPanel.cs
@@ -1,69 +1,70 @@
 ﻿using System.Collections;
+using System.Linq;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Media;
 
 namespace WPFDevelopers.Controls
 {
-    public class NavScrollPanel: Control
+    [TemplatePart(Name = ListBoxTemplateName, Type = typeof(ListBox))]
+    [TemplatePart(Name = ScrollViewerTemplateName, Type = typeof(WDScrollViewer))]
+    [TemplatePart(Name = StackPanelTemplateName, Type = typeof(StackPanel))]
+    public class NavScrollPanel : ItemsControl
     {
+        private const string ListBoxTemplateName = "PART_ListBox";
+        private const string ScrollViewerTemplateName = "PART_ScrollViewer";
+        private const string StackPanelTemplateName = "PART_ContentPanel";
+
+        public static readonly DependencyProperty SelectedIndexProperty =
+            DependencyProperty.Register(nameof(SelectedIndex), typeof(int), typeof(NavScrollPanel),
+                new PropertyMetadata(-1, OnSelectedIndexChanged));
+
+        private StackPanel _contentPanel;
+
+        private ListBox _navListBox;
+        private WDScrollViewer _scrollViewer;
         private bool _suppressAutoSelectDuringAnimation;
+
         static NavScrollPanel()
         {
             DefaultStyleKeyProperty.OverrideMetadata(typeof(NavScrollPanel),
                 new FrameworkPropertyMetadata(typeof(NavScrollPanel)));
         }
 
-        public IEnumerable ItemsSource
-        {
-            get => (IEnumerable)GetValue(ItemsSourceProperty);
-            set => SetValue(ItemsSourceProperty, value);
-        }
-
-        public static readonly DependencyProperty ItemsSourceProperty =
-            DependencyProperty.Register(nameof(ItemsSource), typeof(IEnumerable), typeof(NavScrollPanel), new PropertyMetadata(null, OnItemsSourceChanged));
-
-        public DataTemplate ItemTemplate
-        {
-            get => (DataTemplate)GetValue(ItemTemplateProperty);
-            set => SetValue(ItemTemplateProperty, value);
-        }
-
-        public static readonly DependencyProperty ItemTemplateProperty =
-            DependencyProperty.Register(nameof(ItemTemplate), typeof(DataTemplate), typeof(NavScrollPanel), new PropertyMetadata(null));
-
         public int SelectedIndex
         {
-            get => (int)GetValue(SelectedIndexProperty);
+            get => (int) GetValue(SelectedIndexProperty);
             set => SetValue(SelectedIndexProperty, value);
         }
 
-        public static readonly DependencyProperty SelectedIndexProperty =
-            DependencyProperty.Register(nameof(SelectedIndex), typeof(int), typeof(NavScrollPanel), new PropertyMetadata(-1, OnSelectedIndexChanged));
-
-        private ListBox _navListBox;
-        private WDScrollViewer _scrollViewer;
-        private StackPanel _contentPanel;
-
         public override void OnApplyTemplate()
         {
             base.OnApplyTemplate();
 
-            _navListBox = GetTemplateChild("PART_ListBox") as ListBox;
-            _scrollViewer = GetTemplateChild("PART_ScrollViewer") as WDScrollViewer;
-            _contentPanel = GetTemplateChild("PART_ContentPanel") as StackPanel;
+            _navListBox = GetTemplateChild(ListBoxTemplateName) as ListBox;
+            _scrollViewer = GetTemplateChild(ScrollViewerTemplateName) as WDScrollViewer;
+            _contentPanel = GetTemplateChild(StackPanelTemplateName) as StackPanel;
 
             if (_navListBox != null)
             {
-                _navListBox.DisplayMemberPath = "Title";
                 _navListBox.SelectionChanged -= NavListBox_SelectionChanged;
                 _navListBox.SelectionChanged += NavListBox_SelectionChanged;
             }
+
             if (_scrollViewer != null)
             {
                 _scrollViewer.ScrollChanged -= ScrollViewer_ScrollChanged;
                 _scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
             }
-            RenderContent();
+
+            RefreshContent();
+        }
+
+        protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+        {
+            base.OnItemsChanged(e);
+            RefreshContent();
         }
 
         private void NavListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -90,25 +91,17 @@ private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
                         _navListBox.SelectedIndex = i;
                         _navListBox.SelectionChanged += NavListBox_SelectionChanged;
                     }
+
                     break;
                 }
             }
         }
 
-
-        private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
-        {
-            if (d is NavScrollPanel ctrl)
-            {
-                ctrl.RenderContent();
-            }
-        }
-
         private static void OnSelectedIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
         {
             if (d is NavScrollPanel ctrl)
             {
-                int index = (int)e.NewValue;
+                var index = (int) e.NewValue;
 
                 if (ctrl._contentPanel != null &&
                     index >= 0 && index < ctrl._contentPanel.Children.Count)
@@ -117,28 +110,34 @@ private static void OnSelectedIndexChanged(DependencyObject d, DependencyPropert
                     if (target != null)
                     {
                         var virtualPoint = target.TranslatePoint(new Point(0, 0), ctrl._contentPanel);
-                        ctrl._scrollViewer.AnimateScroll(virtualPoint.Y, () => { ctrl._suppressAutoSelectDuringAnimation = false; });
+                        ctrl._scrollViewer.AnimateScroll(virtualPoint.Y,
+                            () => { ctrl._suppressAutoSelectDuringAnimation = false; });
                     }
                 }
             }
         }
 
-        private void RenderContent()
+        private void RefreshContent()
         {
-            if (_contentPanel == null || ItemsSource == null || ItemTemplate == null)
-                return;
+            if (_navListBox == null || _contentPanel == null) return;
+            _navListBox.Items.Clear();
             _contentPanel.Children.Clear();
-            foreach (var item in ItemsSource)
+            foreach (var item in Items)
             {
-                var content = new ContentControl
+                if (item is NavScrollPanelItem panelItem)
                 {
-                    Content = item,
-                    ContentTemplate = ItemTemplate,
-                };
-                _contentPanel.Children.Add(content);
+                    _navListBox.Items.Add(panelItem.Header);
+                    
+                    var content = new NavScrollPanelItem
+                    {
+                        Header = panelItem.Header,
+                        Content = panelItem.Content,
+                    };
+                    _contentPanel.Children.Add(content);
+                }
             }
-            var panel = new SmallPanel { Height = 100 };
-            _contentPanel.Children.Add(panel);
+            if (_contentPanel.Children.Count > 1)
+                _contentPanel.Children.Add(new Border { Background = Brushes.Transparent, Height = 200 });
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Controls/NavScrollPanel/NavScrollPanelItem.cs b/src/WPFDevelopers.Shared/Controls/NavScrollPanel/NavScrollPanelItem.cs
index 20bd70f0..f6a4d5aa 100644
--- a/src/WPFDevelopers.Shared/Controls/NavScrollPanel/NavScrollPanelItem.cs
+++ b/src/WPFDevelopers.Shared/Controls/NavScrollPanel/NavScrollPanelItem.cs
@@ -1,8 +1,17 @@
-﻿namespace WPFDevelopers.Controls
+﻿using System.Windows;
+using System.Windows.Controls;
+
+namespace WPFDevelopers.Controls
 {
-    public class NavScrollPanelItem
+    public class NavScrollPanelItem : ContentControl
     {
-        public string Title { get; set; }
-        public object Content { get; set; }
+        public static readonly DependencyProperty HeaderProperty =
+            DependencyProperty.Register(nameof(Header), typeof(string), typeof(NavScrollPanelItem), new PropertyMetadata(string.Empty));
+
+        public string Header
+        {
+            get => (string)GetValue(HeaderProperty);
+            set => SetValue(HeaderProperty, value);
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Controls/Panel/SmallPanel.cs b/src/WPFDevelopers.Shared/Controls/Panel/SmallPanel.cs
index b4209c55..e6cc5be0 100644
--- a/src/WPFDevelopers.Shared/Controls/Panel/SmallPanel.cs
+++ b/src/WPFDevelopers.Shared/Controls/Panel/SmallPanel.cs
@@ -4,16 +4,9 @@
 
 namespace WPFDevelopers.Controls
 {
-    /// <summary>
-    /// 当不需要使用Grid的分行分列，则可使用 SmallPanel
-    /// </summary>
     public class SmallPanel : Panel
     {
-        /// <summary>
-        /// Content measurement.
-        /// </summary>
-        /// <param name="constraint">Constraint</param>
-        /// <returns>Desired size</returns>
+        
         protected override Size MeasureOverride(Size constraint)
         {
             Size gridDesiredSize = new Size();
@@ -31,10 +24,7 @@ protected override Size MeasureOverride(Size constraint)
             }
             return (gridDesiredSize);
         }
-        /// <summary>
-        /// Content arrangement.
-        /// </summary>
-        /// <param name="arrangeSize">Arrange size</param>
+        
         protected override Size ArrangeOverride(Size arrangeSize)
         {
             UIElementCollection children = InternalChildren;
diff --git a/src/WPFDevelopers.Shared/Controls/State.cs b/src/WPFDevelopers.Shared/Controls/State.cs
new file mode 100644
index 00000000..18d564cf
--- /dev/null
+++ b/src/WPFDevelopers.Shared/Controls/State.cs
@@ -0,0 +1,16 @@
+﻿namespace WPFDevelopers.Controls
+{
+    public enum StepState
+    {
+        Waiting,
+        InProgress,
+        Complete
+    }
+
+    public enum GestureState
+    {
+        None,
+        Success,
+        Error
+    }
+}
diff --git a/src/WPFDevelopers.Shared/Controls/Status.cs b/src/WPFDevelopers.Shared/Controls/Status.cs
deleted file mode 100644
index 75bfa8a0..00000000
--- a/src/WPFDevelopers.Shared/Controls/Status.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-﻿namespace WPFDevelopers.Controls
-{
-    /// <summary>
-    ///状态值
-    /// </summary>
-    public enum Status
-    {
-        /// <summary>
-        /// 等待中
-        /// </summary>
-        Waiting,
-        /// <summary>
-        /// 正在进行中
-        /// </summary>
-        InProgress,
-        /// <summary>
-        /// 完成
-        /// </summary>
-        Complete
-    }
-}
diff --git a/src/WPFDevelopers.Shared/Controls/Step/Step.cs b/src/WPFDevelopers.Shared/Controls/Step/Step.cs
index 495302b3..1911658b 100644
--- a/src/WPFDevelopers.Shared/Controls/Step/Step.cs
+++ b/src/WPFDevelopers.Shared/Controls/Step/Step.cs
@@ -54,15 +54,15 @@ void UpdateStepItemState(int stepIndex)
             for (var i = 0; i < stepIndex; i++)
             {
                 if (ItemContainerGenerator.ContainerFromIndex(i) is StepItem stepItem)
-                    stepItem.Status = Status.Complete;
+                    stepItem.Status = StepState.Complete;
             }
 
             if (ItemContainerGenerator.ContainerFromIndex(stepIndex) is StepItem itemInProgress)
-                itemInProgress.Status = Status.InProgress;
+                itemInProgress.Status = StepState.InProgress;
             for (var i = stepIndex + 1; i < Items.Count; i++)
             {
                 if (ItemContainerGenerator.ContainerFromIndex(i) is StepItem stepItem)
-                    stepItem.Status = Status.Waiting;
+                    stepItem.Status = StepState.Waiting;
             }
         }
         public override void OnApplyTemplate()
diff --git a/src/WPFDevelopers.Shared/Controls/Step/StepItem.cs b/src/WPFDevelopers.Shared/Controls/Step/StepItem.cs
index b72ac175..c0ef2c45 100644
--- a/src/WPFDevelopers.Shared/Controls/Step/StepItem.cs
+++ b/src/WPFDevelopers.Shared/Controls/Step/StepItem.cs
@@ -17,12 +17,12 @@ public int Index
 
 
         public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
-            "Status", typeof(Status), typeof(StepItem), new PropertyMetadata(Status.Waiting));
+            "Status", typeof(StepState), typeof(StepItem), new PropertyMetadata(StepState.Waiting));
 
 
-        public Status Status
+        public StepState Status
         {
-            get => (Status)GetValue(StatusProperty);
+            get => (StepState)GetValue(StatusProperty);
             internal set => SetValue(StatusProperty, value);
         }
     }
diff --git a/src/WPFDevelopers.Shared/Controls/Tag/Tag.cs b/src/WPFDevelopers.Shared/Controls/Tag/Tag.cs
index 4be6235c..1762b874 100644
--- a/src/WPFDevelopers.Shared/Controls/Tag/Tag.cs
+++ b/src/WPFDevelopers.Shared/Controls/Tag/Tag.cs
@@ -4,49 +4,46 @@
 
 namespace WPFDevelopers.Controls
 {
-    public class Tag :ContentControl
+    public class Tag : ContentControl
     {
-        private static RoutedCommand _closeCommand = null;
-        public bool IsClose
-        {
-            get { return (bool)GetValue(IsCloseProperty); }
-            set { SetValue(IsCloseProperty, value); }
-        }
-
         public static readonly DependencyProperty IsCloseProperty =
             DependencyProperty.Register("IsClose", typeof(bool), typeof(Tag), new PropertyMetadata(true));
 
+        public static readonly RoutedEvent CloseEvent =
+            EventManager.RegisterRoutedEvent("Close", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Tag));
 
-        public event RoutedEventHandler Close
+        static Tag()
         {
-            add { AddHandler(CloseEvent, value); }
-            remove { RemoveHandler(CloseEvent, value); }
+            CloseCommand = new RoutedCommand("Close", typeof(Tag));
+            DefaultStyleKeyProperty.OverrideMetadata(typeof(Tag), new FrameworkPropertyMetadata(typeof(Tag)));
+            CommandManager.RegisterClassCommandBinding(typeof(Tag), new CommandBinding(CloseCommand, OnCloseExecuted));
         }
 
-        public static readonly RoutedEvent CloseEvent =
-            EventManager.RegisterRoutedEvent("Close", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Tag));
-
-        public static RoutedCommand CloseCommand
+        public bool IsClose
         {
-            get { return _closeCommand; }
+            get => (bool) GetValue(IsCloseProperty);
+            set => SetValue(IsCloseProperty, value);
         }
 
-        static Tag()
+        public static RoutedCommand CloseCommand { get; }
+
+
+        public event RoutedEventHandler Close
         {
-            _closeCommand = new RoutedCommand("Close", typeof(Tag));
-            DefaultStyleKeyProperty.OverrideMetadata(typeof(Tag), new FrameworkPropertyMetadata(typeof(Tag)));
-            CommandManager.RegisterClassCommandBinding(typeof(Tag),new CommandBinding(CloseCommand, OnCloseExecuted));
+            add => AddHandler(CloseEvent, value);
+            remove => RemoveHandler(CloseEvent, value);
         }
+
         private static void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e)
         {
             if (sender is Tag tag)
-                tag.OnClose();  
+                tag.OnClose();
         }
 
         protected virtual void OnClose()
         {
-            var args = new RoutedEventArgs(CloseEvent,this);
+            var args = new RoutedEventArgs(CloseEvent, this);
             RaiseEvent(args);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Core/Helpers/ControlsHelper.cs b/src/WPFDevelopers.Shared/Core/Helpers/ControlsHelper.cs
index 6051a286..3d7e8079 100644
--- a/src/WPFDevelopers.Shared/Core/Helpers/ControlsHelper.cs
+++ b/src/WPFDevelopers.Shared/Core/Helpers/ControlsHelper.cs
@@ -142,6 +142,17 @@ public static T FindVisualChild<T>(DependencyObject parent) where T : Dependency
             return null;
         }
 
+        public static T FindParent<T>(DependencyObject child) where T : DependencyObject
+        {
+            var parent = VisualTreeHelper.GetParent(child);
+            if (parent == null) return null;
+
+            if (parent is T tParent)
+                return tParent;
+
+            return FindParent<T>(parent);
+        }
+
         public static object GetXmlReader(object Content)
         {
             try
diff --git a/src/WPFDevelopers.Shared/Core/Helpers/ElementHelper.cs b/src/WPFDevelopers.Shared/Core/Helpers/ElementHelper.cs
index 612e0098..6557d25e 100644
--- a/src/WPFDevelopers.Shared/Core/Helpers/ElementHelper.cs
+++ b/src/WPFDevelopers.Shared/Core/Helpers/ElementHelper.cs
@@ -1,6 +1,8 @@
 ﻿using System;
+using System.Collections;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
 using WPFDevelopers.Controls;
 
 namespace WPFDevelopers.Helpers
@@ -91,25 +93,32 @@ private static void OnIsClearChanged(DependencyObject d, DependencyPropertyChang
 
         private static void OnButtonClear_Click(object sender, RoutedEventArgs e)
         {
-            if (sender is Button button)
+            if (sender is Button button && button.TemplatedParent != null)
             {
-                if (button.TemplatedParent is TextBox textBox)
-                    textBox.Clear();
-                else if (button.TemplatedParent is PasswordBox passwordBox)
-                    passwordBox.Clear();
-                else if (button.TemplatedParent is TabItem tabItem)
+                switch (button.TemplatedParent)
                 {
-                    var tabControl = tabItem.Parent as TabControl;
-                    if (tabControl != null)
-                        tabControl.Items.Remove(tabItem); 
-                }
-                else if(button.TemplatedParent is DateRangePicker dateRangePicker)
-                {
-                    dateRangePicker.StartDate = null;
-                    dateRangePicker.EndDate = null;
+                    case TextBox textBox:
+                        textBox.Clear();
+                        break;
+                    case PasswordBox passwordBox:
+                        passwordBox.Clear();
+                        break;
+                    case TabItem tabItem:
+                        var tabControl = ControlsHelper.FindParent<TabControl>(tabItem);
+                        if (tabControl != null)
+                        {
+                            if (tabControl.ItemsSource is IList itemsSource)
+                                itemsSource.Remove(tabItem.DataContext);
+                            else
+                                tabControl.Items.Remove(tabItem);
+                        }
+                        break;
+                    case DateRangePicker dateRangePicker:
+                        dateRangePicker.StartDate = null;
+                        dateRangePicker.EndDate = null;
+                        break;
                 }
             }
         }
-        
     }
 }
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Core/Helpers/MonitorHelper.cs b/src/WPFDevelopers.Shared/Core/Helpers/MonitorHelper.cs
deleted file mode 100644
index 77bff2e6..00000000
--- a/src/WPFDevelopers.Shared/Core/Helpers/MonitorHelper.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-﻿using System;
-using System.Runtime.InteropServices;
-using WPFDevelopers.Helpers;
-
-namespace WPFDevelopers.Core.Helpers
-{
-    public static class MonitorHelper
-    {
-        internal class WindowsMessageCodes
-        {
-            public const int SC_RESTORE = 0xF120;
-            public const int SC_MINIMIZE = 0xF020;
-            public const int WM_SYSCOMMAND = 0x0112;
-            public const int WM_DEADCHAR = 0x0024;
-        }
-
-        [DllImport(Win32.User32)]
-        internal static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
-
-    }
-}
diff --git a/src/WPFDevelopers.Shared/Core/Helpers/OSVersionHelper.cs b/src/WPFDevelopers.Shared/Core/Helpers/OSVersionHelper.cs
new file mode 100644
index 00000000..5f8ba495
--- /dev/null
+++ b/src/WPFDevelopers.Shared/Core/Helpers/OSVersionHelper.cs
@@ -0,0 +1,119 @@
+﻿using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Interop;
+using System.Windows.Media;
+using Microsoft.Win32;
+using WPFDevelopers.Helpers;
+
+namespace WPFDevelopers.Core.Helpers
+{
+    public class OSVersionHelper
+    {
+        private const double LogicalDpi = 96.0;
+
+        private static bool? _isSnapLayoutSupported;
+
+
+        static OSVersionHelper()
+        {
+            var dC = Win32.GetDC(IntPtr.Zero);
+            if (dC != IntPtr.Zero)
+            {
+                const int logicPixelsX = 88;
+                const int logicPixelsY = 90;
+                DeviceDpiX = Win32.GetDeviceCaps(dC, logicPixelsX);
+                DeviceDpiY = Win32.GetDeviceCaps(dC, logicPixelsY);
+                Win32.ReleaseDC(IntPtr.Zero, dC);
+            }
+            else
+            {
+                DeviceDpiX = LogicalDpi;
+                DeviceDpiY = LogicalDpi;
+            }
+
+            var identity = Matrix.Identity;
+            var identity2 = Matrix.Identity;
+            identity.Scale(DeviceDpiX / LogicalDpi, DeviceDpiY / LogicalDpi);
+            identity2.Scale(LogicalDpi / DeviceDpiX, LogicalDpi / DeviceDpiY);
+            TransformFromDevice = new MatrixTransform(identity2);
+            TransformFromDevice.Freeze();
+            TransformToDevice = new MatrixTransform(identity);
+            TransformToDevice.Freeze();
+        }
+
+        public static MatrixTransform TransformFromDevice { get; }
+        public static MatrixTransform TransformToDevice { get; }
+
+        public static double DeviceDpiX { get; }
+
+        public static double DeviceDpiY { get; }
+        public static double DeviceUnitsScalingFactorX => TransformToDevice.Matrix.M11;
+
+        public static double DeviceUnitsScalingFactorY => TransformToDevice.Matrix.M22;
+
+        public static bool IsSnapLayoutSupported()
+        {
+            if (_isSnapLayoutSupported.HasValue) return _isSnapLayoutSupported.Value;
+
+            _isSnapLayoutSupported = CheckSnapLayoutSupport();
+            return _isSnapLayoutSupported.Value;
+        }
+
+        private static bool CheckSnapLayoutSupport()
+        {
+            var version = GetWindowsBuildNumber();
+            return version >= 22000;
+        }
+
+        private static int GetWindowsBuildNumber()
+        {
+            try
+            {
+                using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"))
+                {
+                    if (key != null)
+                    {
+                        var buildNumber = key.GetValue("CurrentBuildNumber");
+                        if (buildNumber != null && int.TryParse(buildNumber.ToString(), out var result)) return result;
+                    }
+                }
+            }
+            catch
+            {
+            }
+
+            return 0;
+        }
+
+        #region SnapLayout
+
+        private const double DPI_SCALE = 1.5;
+        public const int HTMAXBUTTON = 9;
+
+        private static HwndSource GetWindowHwndSource(DependencyObject dependencyObject)
+        {
+            if (dependencyObject is Window window) return PresentationSource.FromVisual(window) as HwndSource;
+
+            if (dependencyObject is ToolTip tooltip) return PresentationSource.FromVisual(tooltip) as HwndSource;
+
+            if (dependencyObject is Popup popup)
+            {
+                if (popup.Child is null)
+                    return null;
+
+                return PresentationSource.FromVisual(popup.Child) as HwndSource;
+            }
+
+            if (dependencyObject is Visual visual)
+            {
+                return PresentationSource.FromVisual(visual) as HwndSource;
+            }
+
+            return null;
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Core/Helpers/TreeViewHelper.cs b/src/WPFDevelopers.Shared/Core/Helpers/TreeViewHelper.cs
index b72a5670..319b77a0 100644
--- a/src/WPFDevelopers.Shared/Core/Helpers/TreeViewHelper.cs
+++ b/src/WPFDevelopers.Shared/Core/Helpers/TreeViewHelper.cs
@@ -1,9 +1,20 @@
-﻿using System.Windows;
+﻿using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Threading;
+using WPFDevelopers.Controls;
 
 namespace WPFDevelopers.Helpers
 {
     public class TreeViewHelper
     {
+        private static readonly DependencyProperty MouseHandlerProperty =
+    DependencyProperty.RegisterAttached("MouseHandler", typeof(MouseButtonEventHandler), typeof(TreeViewHelper), new PropertyMetadata(null));
+
+        private static readonly DependencyProperty ExpandHandlerProperty =
+            DependencyProperty.RegisterAttached("ExpandHandler", typeof(RoutedEventHandler), typeof(TreeViewHelper), new PropertyMetadata(null));
+
         public static readonly DependencyProperty IsScrollAnimationProperty =
             DependencyProperty.RegisterAttached("IsScrollAnimation", typeof(bool), typeof(TreeViewHelper),
                 new FrameworkPropertyMetadata(false));
@@ -17,5 +28,79 @@ public static void SetIsScrollAnimation(DependencyObject obj, object value)
         {
             obj.SetValue(IsScrollAnimationProperty, value);
         }
+
+        public static readonly DependencyProperty PreserveScrollOnExpandProperty =
+            DependencyProperty.RegisterAttached(
+                "PreserveScrollOnExpand",
+                typeof(bool),
+                typeof(TreeViewHelper),
+                new PropertyMetadata(false, OnPreserveScrollOnExpandChanged));
+
+        public static void SetPreserveScrollOnExpand(DependencyObject element, bool value) =>
+           element.SetValue(PreserveScrollOnExpandProperty, value);
+
+        public static bool GetPreserveScrollOnExpand(DependencyObject element) =>
+            (bool)element.GetValue(PreserveScrollOnExpandProperty);
+
+
+        public static readonly DependencyProperty LastOffsetProperty =
+    DependencyProperty.RegisterAttached("LastOffset", typeof(double), typeof(TreeViewHelper), new PropertyMetadata(0.0));
+
+        internal static void SetLastOffset(DependencyObject obj, double value) => obj.SetValue(LastOffsetProperty, value);
+        public static double GetLastOffset(DependencyObject obj) => (double)obj.GetValue(LastOffsetProperty);
+
+        private static void OnPreserveScrollOnExpandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            if (d is TreeView treeView)
+            {
+                if ((bool)e.NewValue)
+                {
+                    var mouseHandler = new MouseButtonEventHandler(OnMouseDown);
+                    var expandHandler = new RoutedEventHandler(OnItemExpanded);
+
+                    treeView.SetValue(MouseHandlerProperty, mouseHandler);
+                    treeView.SetValue(ExpandHandlerProperty, expandHandler);
+
+                    treeView.AddHandler(TreeViewItem.PreviewMouseLeftButtonDownEvent, mouseHandler, true);
+                    treeView.AddHandler(TreeViewItem.ExpandedEvent, expandHandler, true);
+                }
+                else
+                {
+                    if (treeView.GetValue(MouseHandlerProperty) is MouseButtonEventHandler mouseHandler)
+                        treeView.RemoveHandler(TreeViewItem.PreviewMouseLeftButtonDownEvent, mouseHandler);
+
+                    if (treeView.GetValue(ExpandHandlerProperty) is RoutedEventHandler expandHandler)
+                        treeView.RemoveHandler(TreeViewItem.ExpandedEvent, expandHandler);
+                }
+            }
+        }
+        private static void OnMouseDown(object sender, MouseButtonEventArgs args)
+        {
+            if (sender is TreeView treeView)
+            {
+                var viewer = ControlsHelper.FindVisualChild<ScrollViewer>(treeView);
+                if (viewer != null)
+                    SetLastOffset(treeView, viewer.VerticalOffset);
+            }
+        }
+
+        private static void OnItemExpanded(object sender, RoutedEventArgs args)
+        {
+            if (sender is TreeView treeView)
+            {
+                var scrollViewer = ControlsHelper.FindVisualChild<ScrollViewer>(treeView);
+                if (scrollViewer == null)
+                    return;
+
+                var lastOffset = GetLastOffset(treeView);
+                treeView.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
+                {
+                    if (scrollViewer is WDScrollViewer wd)
+                        wd.AnimateScroll(lastOffset);
+                    else
+                        scrollViewer.ScrollToVerticalOffset(lastOffset);
+                }));
+            }
+        }
     }
 }
diff --git a/src/WPFDevelopers.Shared/Core/Helpers/Win32.cs b/src/WPFDevelopers.Shared/Core/Helpers/Win32.cs
index 9f4cd120..6e056c24 100644
--- a/src/WPFDevelopers.Shared/Core/Helpers/Win32.cs
+++ b/src/WPFDevelopers.Shared/Core/Helpers/Win32.cs
@@ -17,7 +17,7 @@ public const string
             NTdll = "ntdll.dll",
             DwmApi = "dwmapi.dll",
             Winmm = "winmm.dll",
-            Shcore = "Shcore.dll";
+            Shcore = "shcore.dll";
         //查找窗口的委托 查找逻辑
         public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
 
@@ -28,6 +28,9 @@ public const string
         public static extern IntPtr SendMessageTimeout(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam,
             uint fuFlage, uint timeout, IntPtr result);
 
+        [DllImport(User32)]
+        internal static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
+
         [DllImport(User32)]
         public static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam);
 
@@ -78,6 +81,9 @@ public static extern IntPtr CreateBitmap(int nWidth, int nHeight, uint cPlanes,
         [DllImport(User32)]
         public static extern IntPtr GetDC(IntPtr hWnd);
 
+        [DllImport(Gdi32)]
+        public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
+
         [DllImport(User32)]
         public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
 
@@ -168,16 +174,60 @@ public static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth,
         public extern static void SetCursorPos(int x, int y);
 
         [DllImport(DwmApi)]
-        public static extern int DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttribute attr, ref int attrValue, int attrSize);
-        public enum DwmWindowAttribute : uint
-        {
-            UseImmersiveDarkMode = 20,
-        }
+        public static extern int DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttributes attr, ref int attrValue, int attrSize);
+
         public static bool EnableDarkModeForWindow(HwndSource source, bool enable)
         {
             int darkMode = enable ? 1 : 0;
-            int hr = DwmSetWindowAttribute(source.Handle, DwmWindowAttribute.UseImmersiveDarkMode, ref darkMode, sizeof(int));
+            int hr = DwmSetWindowAttribute(source.Handle, DwmWindowAttributes.UseImmersiveDarkMode, ref darkMode, sizeof(int));
             return hr >= 0;
         }
+
+        [DllImport(DwmApi)]
+        public static extern int DwmSetIconicThumbnail(IntPtr hwnd, IntPtr hbmp, int dwSITFlags);
+
+        [DllImport(DwmApi)]
+        public static extern int DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttributes dwAttribute, IntPtr pvAttribute, int cbAttribute);
+
+        [DllImport(DwmApi)]
+        public static extern int DwmInvalidateIconicBitmaps(IntPtr hwnd);
+
+        [DllImport(User32)]
+        public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
+
+        [DllImport(User32)]
+        public static extern int GetDpiForWindow(IntPtr hwnd);
+
+        [StructLayout(LayoutKind.Sequential)]
+        public struct RECT
+        {
+            public int Left;
+            public int Top;
+            public int Right;
+            public int Bottom;
+        }
     }
+
+    internal class WindowsMessageCodes
+    {
+        public const int SC_RESTORE = 0xF120;
+        public const int SC_MINIMIZE = 0xF020;
+        public const int WM_SYSCOMMAND = 0x0112;
+        public const int WM_DEADCHAR = 0x0024;
+        public const int WM_NCLBUTTONDOWN = 0x00A1;
+        public const int WM_NCHITTEST = 0x0084;
+
+        public const int WM_DWMSENDICONICTHUMBNAIL = 0x0323;
+    }
+
+    [Flags]
+    public enum DwmWindowAttributes : uint
+    {
+        None = 0, 
+        DISPLAYFRAME = 1,
+        FORCE_ICONIC_REPRESENTATION = 7,
+        HAS_ICONIC_BITMAP = 10,
+        UseImmersiveDarkMode = 20
+    }
+
 }
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Core/Helpers/WindowHelpers.cs b/src/WPFDevelopers.Shared/Core/Helpers/WindowHelpers.cs
index 29cf48fb..8cb6b036 100644
--- a/src/WPFDevelopers.Shared/Core/Helpers/WindowHelpers.cs
+++ b/src/WPFDevelopers.Shared/Core/Helpers/WindowHelpers.cs
@@ -1,7 +1,14 @@
-﻿using System.Windows;
+﻿using System;
+using System.Drawing;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Interop;
 using System.Windows.Media;
+using System.Windows.Threading;
 using WPFDevelopers.Controls;
 using WPFDevelopers.Utilities;
+using Size = System.Drawing.Size;
 
 namespace WPFDevelopers.Helpers
 {
@@ -12,11 +19,13 @@ public static void MaskShow(this Window outputWindow)
             CreateMask(outputWindow);
             outputWindow.Show();
         }
+
         public static bool? MaskShowDialog(this Window outputWindow)
         {
             CreateMask(outputWindow);
             return outputWindow.ShowDialog();
         }
+
         public static void CreateMask(this Window outputWindow)
         {
             Visual parent = ControlsHelper.GetDefaultWindow();
@@ -36,5 +45,69 @@ public static void CreateMask(this Window outputWindow)
                 };
             }
         }
+
+        public static void SetIconicThumbnail(this Window window, string imagePath)
+        {
+            if (window == null || string.IsNullOrWhiteSpace(imagePath)) return;
+            if (!File.Exists(imagePath)) return;
+            IntPtr hwnd = new WindowInteropHelper(window).Handle;
+            int size = Marshal.SizeOf(typeof(int));
+            IntPtr pBool = Marshal.AllocHGlobal(size);
+            try
+            {
+                Marshal.WriteInt32(pBool, 1);
+                Win32.DwmSetWindowAttribute(hwnd, DwmWindowAttributes.FORCE_ICONIC_REPRESENTATION, pBool, size);
+                Win32.DwmSetWindowAttribute(hwnd, DwmWindowAttributes.HAS_ICONIC_BITMAP, pBool, size);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pBool);
+            }
+            var source = HwndSource.FromHwnd(hwnd);
+            if (source != null)
+            {
+                source.AddHook(new HwndSourceHook((IntPtr hwnd2, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
+                {
+                    if (msg == WindowsMessageCodes.WM_DWMSENDICONICTHUMBNAIL)
+                    {
+                        int width = ((int)((((long)lParam) >> 16) & 0xFFFF));
+                        int height = ((int)((long)lParam & 0xFFFF));
+                        try
+                        {
+                            using (var bmp = new Bitmap(imagePath))
+                            using (var resized = new Bitmap(bmp, new Size(width, height)))
+                            {
+                                IntPtr hBitmap = resized.GetHbitmap();
+                                Win32.DwmSetIconicThumbnail(hwnd2, hBitmap, (int)DwmWindowAttributes.None);
+                                Win32.DeleteObject(hBitmap);
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            throw new Exception($"DwmSetIconicThumbnail error :{ex.Message}!");
+                        }
+
+                        handled = true;
+                    }
+
+                    return IntPtr.Zero;
+                }));
+            }
+            Win32.DwmInvalidateIconicBitmaps(hwnd);
+            window.ShowInTaskbar = true;
+        }
+
+        public static Rect GetWindowBounds(IntPtr hWnd)
+        {
+            Win32.RECT rect;
+            Win32.GetWindowRect(hWnd, out rect);
+            int dpi = Win32.GetDpiForWindow(hWnd);
+            double scale = dpi / 96.0;
+            return new Rect(
+                rect.Left / scale,
+                rect.Top / scale,
+                (rect.Right - rect.Left) / scale,
+                (rect.Bottom - rect.Top) / scale);
+        }
     }
 }
diff --git a/src/WPFDevelopers.Shared/Resources.cs b/src/WPFDevelopers.Shared/Resources.cs
index 8d6799cb..10256f52 100644
--- a/src/WPFDevelopers.Shared/Resources.cs
+++ b/src/WPFDevelopers.Shared/Resources.cs
@@ -26,7 +26,7 @@ public ThemeType Theme
             get => _theme;
             set => InitializeTheme(value);
         }
-        
+
         private Color _color;
         public Color Color
         {
@@ -61,7 +61,7 @@ void AddTheme()
                 ApplyTheme();
                 return;
             }
-            if(Theme == ThemeType.Default)
+            if (Theme == ThemeType.Default)
                 Theme = ThemeType.Light;
         }
 
@@ -79,7 +79,7 @@ protected void InitializeTheme(ThemeType themeType)
             }
             var path = GetResourceUri(GetThemeResourceName(themeType));
             var newResourceDictionary = new ResourceDictionary { Source = path };
-           
+
             MergedDictionaries.Insert(0, newResourceDictionary);
             ThemeChanged?.Invoke(themeType);
             UpdateColorOnThemeChange();
@@ -93,11 +93,11 @@ bool IsDarkMode()
             try
             {
                 var value = (int)Registry.GetValue(registryKey, registryValue, 1);
-                return value == 0; 
+                return value == 0;
             }
             catch
             {
-                return false; 
+                return false;
             }
         }
 
@@ -105,7 +105,7 @@ void ApplyTheme()
         {
             var isDarkMode = IsDarkMode();
             var theme = isDarkMode == true ? ThemeType.Dark : ThemeType.Light;
-            if(Theme != theme)
+            if (Theme != theme)
                 Theme = theme;
         }
 
@@ -120,7 +120,7 @@ bool IsWindows10OrLater()
                 }
             }
             Version version = Environment.OSVersion.Version;
-            return version.Major >= 10; 
+            return version.Major >= 10;
         }
 
         private void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
@@ -160,7 +160,7 @@ void KillExistingProcess(string processName)
                 try
                 {
                     process.Kill();
-                    process.WaitForExit(); 
+                    process.WaitForExit();
                 }
                 catch { }
             }
@@ -236,7 +236,7 @@ public T TryFindResource<T>(string resourceKey)
             {
                 return typedResource;
             }
-            return default; 
+            return default;
         }
 
 
@@ -263,8 +263,8 @@ void UpdateResourceDictionaryColor(string key = "Primary", Color color = default
                 else
                 {
                     if (Color != null
-                            &&
-                            !Array.Exists(resourceKeys, i => newKey.EndsWith(i)))
+                        &&
+                        !Array.Exists(resourceKeys, i => newKey.EndsWith(i)))
                     {
                         var brightnessColor = new Color
                         {
@@ -294,7 +294,7 @@ void UpdateResourceDictionaryColor(string key = "Primary", Color color = default
             }
         }
 
-        void SetResourceColorAndBrush(string key,Color color)
+        void SetResourceColorAndBrush(string key, Color color)
         {
             UpdateResource(key, color);
             var newBrush = new SolidColorBrush(color);
diff --git a/src/WPFDevelopers.Shared/Styles/Styles.DatePicker.xaml b/src/WPFDevelopers.Shared/Styles/Styles.DatePicker.xaml
index 7d31f7fe..0a57d0d5 100644
--- a/src/WPFDevelopers.Shared/Styles/Styles.DatePicker.xaml
+++ b/src/WPFDevelopers.Shared/Styles/Styles.DatePicker.xaml
@@ -50,19 +50,6 @@
                             HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                             VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                             TextElement.Foreground="{DynamicResource WD.RegularTextBrush}" />
-                        <Line
-                            x:Name="Blackout"
-                            Margin="8,3,8,0"
-                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
-                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
-                            Opacity=".4"
-                            Stroke="{DynamicResource WD.PrimaryTextBrush}"
-                            StrokeThickness="1.5"
-                            Visibility="Collapsed"
-                            X1="0"
-                            X2="{TemplateBinding Width}"
-                            Y1="0"
-                            Y2="0" />
                     </controls:SmallPanel>
                     <ControlTemplate.Triggers>
                         <Trigger Property="IsToday" Value="True">
@@ -117,7 +104,8 @@
                             <Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource WD.BaseBrush}" />
                         </MultiTrigger>
                         <Trigger Property="IsBlackedOut" Value="True">
-                            <Setter TargetName="Blackout" Property="Visibility" Value="Visible" />
+                            <Setter Property="Opacity" Value=".4" />
+                            <Setter Property="Cursor" Value="No" />
                         </Trigger>
                         <Trigger Property="helpers:DatePickerHelper.IsHighlight" Value="True">
                             <Setter TargetName="SelectedBackground" Property="Visibility" Value="Collapsed" />
diff --git a/src/WPFDevelopers.Shared/Styles/Styles.Grid.xaml b/src/WPFDevelopers.Shared/Styles/Styles.Grid.xaml
deleted file mode 100644
index a8da8092..00000000
--- a/src/WPFDevelopers.Shared/Styles/Styles.Grid.xaml
+++ /dev/null
@@ -1,12 +0,0 @@
-﻿<ResourceDictionary
-    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-    xmlns:sys="clr-namespace:System;assembly=mscorlib">
-    <ResourceDictionary.MergedDictionaries>
-        <ResourceDictionary Source="../Themes/Basic/Colors.xaml" />
-    </ResourceDictionary.MergedDictionaries>
-    <Style x:Key="WD.DefaultGrid" TargetType="{x:Type Grid}">
-        <Setter Property="Background" Value="{DynamicResource WD.BackgroundBrush}" />
-    </Style>
-    <Style BasedOn="{StaticResource WD.DefaultGrid}" TargetType="{x:Type Grid}" />
-</ResourceDictionary>
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Styles/Styles.Slider.xaml b/src/WPFDevelopers.Shared/Styles/Styles.Slider.xaml
index 1b2fa4c3..70be753f 100644
--- a/src/WPFDevelopers.Shared/Styles/Styles.Slider.xaml
+++ b/src/WPFDevelopers.Shared/Styles/Styles.Slider.xaml
@@ -87,16 +87,16 @@
                         Background="{TemplateBinding Background}" />
                     <ControlTemplate.Triggers>
                         <Trigger Property="RadiusOrientation" Value="Right">
-                            <Setter TargetName="PART_Border" Property="CornerRadius" Value="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.CornerRadiusToSurroundConverter}, ConverterParameter=Right}" />
+                            <Setter TargetName="PART_Border" Property="CornerRadius" Value="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource AncestorType=Slider}, Converter={StaticResource WD.CornerRadiusToSurroundConverter}, ConverterParameter=Right}" />
                         </Trigger>
                         <Trigger Property="RadiusOrientation" Value="Left">
-                            <Setter TargetName="PART_Border" Property="CornerRadius" Value="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.CornerRadiusToSurroundConverter}, ConverterParameter=Left}" />
+                            <Setter TargetName="PART_Border" Property="CornerRadius" Value="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource AncestorType=Slider}, Converter={StaticResource WD.CornerRadiusToSurroundConverter}, ConverterParameter=Left}" />
                         </Trigger>
                         <Trigger Property="RadiusOrientation" Value="Down">
-                            <Setter TargetName="PART_Border" Property="CornerRadius" Value="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.CornerRadiusToSurroundConverter}, ConverterParameter=Down}" />
+                            <Setter TargetName="PART_Border" Property="CornerRadius" Value="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource AncestorType=Slider}, Converter={StaticResource WD.CornerRadiusToSurroundConverter}, ConverterParameter=Down}" />
                         </Trigger>
                         <Trigger Property="RadiusOrientation" Value="Up">
-                            <Setter TargetName="PART_Border" Property="CornerRadius" Value="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.CornerRadiusToSurroundConverter}, ConverterParameter=Up}" />
+                            <Setter TargetName="PART_Border" Property="CornerRadius" Value="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource AncestorType=Slider}, Converter={StaticResource WD.CornerRadiusToSurroundConverter}, ConverterParameter=Up}" />
                         </Trigger>
                     </ControlTemplate.Triggers>
                 </ControlTemplate>
@@ -249,6 +249,7 @@
         BasedOn="{StaticResource WD.ControlBasicStyle}"
         TargetType="{x:Type Slider}">
         <Setter Property="Stylus.IsPressAndHoldEnabled" Value="False" />
+        <Setter Property="IsMoveToPointEnabled" Value="True" />
         <Setter Property="Background" Value="Transparent" />
         <Setter Property="BorderBrush" Value="Transparent" />
         <Setter Property="SelectionEnd" Value="{Binding RelativeSource={RelativeSource Self}, Path=Value}" />
diff --git a/src/WPFDevelopers.Shared/Themes/DateRangePicker.xaml b/src/WPFDevelopers.Shared/Themes/DateRangePicker.xaml
index 26823ad7..0bd4507c 100644
--- a/src/WPFDevelopers.Shared/Themes/DateRangePicker.xaml
+++ b/src/WPFDevelopers.Shared/Themes/DateRangePicker.xaml
@@ -141,7 +141,10 @@
         </Setter>
     </Style>
 
-    <Style x:Key="WD.DateRangePicker" TargetType="{x:Type controls:DateRangePicker}">
+    <Style
+        x:Key="WD.DateRangePicker"
+        BasedOn="{StaticResource WD.ControlBasicStyle}"
+        TargetType="{x:Type controls:DateRangePicker}">
         <Setter Property="HorizontalContentAlignment" Value="Center" />
         <Setter Property="VerticalContentAlignment" Value="Center" />
         <Setter Property="HorizontalAlignment" Value="Stretch" />
@@ -192,7 +195,7 @@
                                     <ColumnDefinition Width="Auto" />
                                 </Grid.ColumnDefinitions>
                                 <controls:PathIcon
-                                    Margin="15,0,0,0"
+                                    Margin="6,0"
                                     HorizontalAlignment="Center"
                                     VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                     Kind="Date" />
@@ -209,13 +212,13 @@
                                     SelectionBrush="{DynamicResource WD.WindowBorderBrush}" />
                                 <controls:PathIcon
                                     Grid.Column="2"
+                                    Margin="6,0"
                                     VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                     Kind="DateRangeRight" />
                                 <DatePickerTextBox
                                     x:Name="PART_TextBoxEnd"
                                     Grid.Column="3"
                                     Width="Auto"
-                                    Margin="10,0,0,0"
                                     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                     VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                     helpers:DatePickerHelper.Watermark="{Binding EndWatermark, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
diff --git a/src/WPFDevelopers.Shared/Themes/GestureUnlock.xaml b/src/WPFDevelopers.Shared/Themes/GestureUnlock.xaml
new file mode 100644
index 00000000..5199f50d
--- /dev/null
+++ b/src/WPFDevelopers.Shared/Themes/GestureUnlock.xaml
@@ -0,0 +1,94 @@
+﻿<ResourceDictionary
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:controls="clr-namespace:WPFDevelopers.Controls"
+    xmlns:helpers="clr-namespace:WPFDevelopers.Helpers"
+    xmlns:resx="clr-namespace:WPFDevelopers">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="Basic/ControlBasic.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+    <Style
+        x:Key="WD.GestureItem"
+        BasedOn="{StaticResource WD.ControlBasicStyle}"
+        TargetType="{x:Type controls:GestureItem}">
+        <Setter Property="Width" Value="60" />
+        <Setter Property="VerticalAlignment" Value="Center" />
+        <Setter Property="HorizontalAlignment" Value="Center" />
+        <Setter Property="VerticalContentAlignment" Value="Stretch" />
+        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+        <Setter Property="Height" Value="60" />
+        <Setter Property="BorderThickness" Value="1.5" />
+        <Setter Property="Background" Value="#80FFFFFF" />
+        <Setter Property="BorderBrush" Value="{DynamicResource WD.PrimaryBrush}" />
+        <Setter Property="Padding" Value="15" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type controls:GestureItem}">
+                    <Border
+                        x:Name="PART_Border"
+                        Width="{TemplateBinding Width}"
+                        Height="{TemplateBinding Height}"
+                        Background="{TemplateBinding Background}"
+                        BorderBrush="{TemplateBinding BorderBrush}"
+                        BorderThickness="{TemplateBinding BorderThickness}"
+                        CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"
+                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
+                        UseLayoutRounding="{TemplateBinding UseLayoutRounding}">
+                        <Ellipse
+                            x:Name="PART_Ellipse"
+                            Margin="{TemplateBinding Padding}"
+                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
+                            Fill="{TemplateBinding BorderBrush}"
+                            Visibility="Collapsed" />
+                    </Border>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsSelected" Value="True">
+                            <Setter TargetName="PART_Border" Property="Background" Value="{DynamicResource WD.BackgroundBrush}" />
+                            <Setter TargetName="PART_Ellipse" Property="Visibility" Value="Visible" />
+                        </Trigger>
+                        <MultiDataTrigger>
+                            <MultiDataTrigger.Conditions>
+                                <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True" />
+                                <Condition Binding="{Binding State, RelativeSource={RelativeSource AncestorType=controls:GestureUnlock}}" Value="Error" />
+                            </MultiDataTrigger.Conditions>
+                            <Setter Property="BorderBrush" Value="{DynamicResource WD.DangerBrush}" />
+                        </MultiDataTrigger>
+                        <MultiDataTrigger>
+                            <MultiDataTrigger.Conditions>
+                                <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True" />
+                                <Condition Binding="{Binding State, RelativeSource={RelativeSource AncestorType=controls:GestureUnlock}}" Value="Success" />
+                            </MultiDataTrigger.Conditions>
+                            <Setter Property="BorderBrush" Value="{DynamicResource WD.SuccessBrush}" />
+                        </MultiDataTrigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style
+        x:Key="WD.GestureUnlock"
+        BasedOn="{StaticResource WD.ControlBasicStyle}"
+        TargetType="{x:Type controls:GestureUnlock}">
+        <Setter Property="Background" Value="{DynamicResource WD.BackgroundBrush}" />
+        <Setter Property="Width" Value="300" />
+        <Setter Property="VerticalAlignment" Value="Center" />
+        <Setter Property="HorizontalAlignment" Value="Center" />
+        <Setter Property="Height" Value="300" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type controls:GestureUnlock}">
+                    <controls:WDBorder CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}">
+                        <Canvas
+                            x:Name="PART_GestureUnlockCanvas"
+                            Background="{TemplateBinding Background}"
+                            Clip="{Binding RelativeSource={RelativeSource AncestorType=controls:WDBorder}, Path=ContentClip}"
+                            SnapsToDevicePixels="True" />
+                    </controls:WDBorder>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style BasedOn="{StaticResource WD.GestureItem}" TargetType="{x:Type controls:GestureItem}" />
+    <Style BasedOn="{StaticResource WD.GestureUnlock}" TargetType="{x:Type controls:GestureUnlock}" />
+</ResourceDictionary>
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Themes/MultiSelectComboBox.xaml b/src/WPFDevelopers.Shared/Themes/MultiSelectComboBox.xaml
index f4a5f19d..3708bc9b 100644
--- a/src/WPFDevelopers.Shared/Themes/MultiSelectComboBox.xaml
+++ b/src/WPFDevelopers.Shared/Themes/MultiSelectComboBox.xaml
@@ -158,7 +158,8 @@
                                 Focusable="True"
                                 IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                                 Placement="Bottom"
-                                PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
+                                PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
+                                StaysOpen="False">
                                 <controls:SmallPanel
                                     x:Name="PART_DropDown"
                                     MinWidth="{TemplateBinding FrameworkElement.ActualWidth}"
diff --git a/src/WPFDevelopers.Shared/Themes/MultiSelectSearchComboBox.xaml b/src/WPFDevelopers.Shared/Themes/MultiSelectSearchComboBox.xaml
index abcafc9d..14308e66 100644
--- a/src/WPFDevelopers.Shared/Themes/MultiSelectSearchComboBox.xaml
+++ b/src/WPFDevelopers.Shared/Themes/MultiSelectSearchComboBox.xaml
@@ -101,7 +101,8 @@
                                 Focusable="True"
                                 IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                                 Placement="Bottom"
-                                PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
+                                PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
+                                StaysOpen="False">
                                 <controls:SmallPanel
                                     x:Name="PART_DropDown"
                                     MinWidth="{TemplateBinding FrameworkElement.ActualWidth}"
diff --git a/src/WPFDevelopers.Shared/Themes/NavScrollPanel.xaml b/src/WPFDevelopers.Shared/Themes/NavScrollPanel.xaml
index 202ec018..2e27c5f6 100644
--- a/src/WPFDevelopers.Shared/Themes/NavScrollPanel.xaml
+++ b/src/WPFDevelopers.Shared/Themes/NavScrollPanel.xaml
@@ -7,23 +7,35 @@
     <ResourceDictionary.MergedDictionaries>
         <ResourceDictionary Source="Basic/ControlBasic.xaml" />
     </ResourceDictionary.MergedDictionaries>
-
-    <DataTemplate x:Key="WD.NavScrollPanelTemplate">
-        <StackPanel Margin="0,0,0,20">
-            <TextBlock
-                Margin="0,0,0,20"
-                FontSize="{DynamicResource WD.TitleFontSize}"
-                FontWeight="Black"
-                Text="{Binding Title}" />
-            <Border
-                Padding="20"
-                BorderBrush="{DynamicResource WD.BaseBrush}"
-                BorderThickness="1"
-                CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource AncestorType=controls:NavScrollPanel}}">
-                <ContentPresenter Content="{Binding Content}" />
-            </Border>
-        </StackPanel>
-    </DataTemplate>
+    <Style
+        x:Key="WD.NavScrollPanelItem"
+        BasedOn="{StaticResource WD.ControlBasicStyle}"
+        TargetType="{x:Type controls:NavScrollPanelItem}">
+        <Setter Property="BorderThickness" Value="1" />
+        <Setter Property="BorderBrush" Value="{DynamicResource WD.BaseBrush}" />
+        <Setter Property="Margin" Value="0,0,0,20" />
+        <Setter Property="Padding" Value="20" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type controls:NavScrollPanelItem}">
+                    <StackPanel Margin="{TemplateBinding Margin}">
+                        <TextBlock
+                            Margin="{TemplateBinding Margin}"
+                            FontSize="{DynamicResource WD.TitleFontSize}"
+                            FontWeight="Black"
+                            Text="{TemplateBinding Header}" />
+                        <Border
+                            Padding="{TemplateBinding Padding}"
+                            BorderBrush="{TemplateBinding BorderBrush}"
+                            BorderThickness="{TemplateBinding BorderThickness}"
+                            CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource AncestorType=controls:NavScrollPanel}}">
+                            <ContentPresenter Content="{TemplateBinding Content}" />
+                        </Border>
+                    </StackPanel>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
 
     <Style
         x:Key="WD.NavScrollPanelListBoxItem"
@@ -70,10 +82,10 @@
         x:Key="WD.NavScrollPanel"
         BasedOn="{StaticResource WD.ControlBasicStyle}"
         TargetType="{x:Type controls:NavScrollPanel}">
-        <Setter Property="BorderThickness" Value="1" />
+        <Setter Property="BorderThickness" Value="0" />
         <Setter Property="BorderBrush" Value="{DynamicResource WD.BaseBrush}" />
         <Setter Property="Background" Value="{DynamicResource WD.BackgroundBrush}" />
-        <Setter Property="ItemTemplate" Value="{DynamicResource WD.NavScrollPanelTemplate}" />
+        <Setter Property="ItemContainerStyle" Value="{DynamicResource WD.NavScrollPanelListBoxItem}" />
         <Setter Property="VerticalContentAlignment" Value="Center" />
         <Setter Property="HorizontalContentAlignment" Value="Stretch" />
         <Setter Property="Padding" Value="{DynamicResource WD.Padding}" />
@@ -96,8 +108,7 @@
                                 Padding="10,8"
                                 VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                 BorderThickness="0"
-                                ItemContainerStyle="{DynamicResource WD.NavScrollPanelListBoxItem}"
-                                ItemsSource="{TemplateBinding ItemsSource}" />
+                                ItemContainerStyle="{TemplateBinding ItemContainerStyle}" />
                             <controls:WDScrollViewer
                                 x:Name="PART_ScrollViewer"
                                 Grid.Column="2"
@@ -111,5 +122,6 @@
             </Setter.Value>
         </Setter>
     </Style>
+    <Style BasedOn="{StaticResource WD.NavScrollPanelItem}" TargetType="{x:Type controls:NavScrollPanelItem}" />
     <Style BasedOn="{StaticResource WD.NavScrollPanel}" TargetType="{x:Type controls:NavScrollPanel}" />
 </ResourceDictionary>
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Themes/Theme40.txt b/src/WPFDevelopers.Shared/Themes/Theme40.txt
index da2461e1..75cabb63 100644
--- a/src/WPFDevelopers.Shared/Themes/Theme40.txt
+++ b/src/WPFDevelopers.Shared/Themes/Theme40.txt
@@ -33,7 +33,6 @@ Basic\ControlBasic.xaml
 ..\Styles\Styles.GridSplitter.xaml
 ..\Styles\Styles.Label.xaml
 ..\Styles\Styles.RepeatButton.xaml
-..\Styles\Styles.Grid.xaml
 
 ..\Microsoft.Expression.Controls\Themes\Generic.xaml
 ..\Microsoft.Expression.Drawing\Themes\Generic.xaml
@@ -70,4 +69,6 @@ TimePicker.xaml
 Drawer.xaml
 DateRangePicker.xaml
 Tag.xaml
-NavScrollPanel.xaml
\ No newline at end of file
+NavScrollPanel.xaml
+GestureUnlock.xaml
+WDUserControl.xaml
diff --git a/src/WPFDevelopers.Shared/Themes/Theme45x.txt b/src/WPFDevelopers.Shared/Themes/Theme45x.txt
index e99fa592..59021114 100644
--- a/src/WPFDevelopers.Shared/Themes/Theme45x.txt
+++ b/src/WPFDevelopers.Shared/Themes/Theme45x.txt
@@ -33,7 +33,6 @@ Basic\ControlBasic.xaml
 ..\Styles\Styles.GridSplitter.xaml
 ..\Styles\Styles.Label.xaml
 ..\Styles\Styles.RepeatButton.xaml
-..\Styles\Styles.Grid.xaml
 
 ..\Microsoft.Expression.Controls\Themes\Generic.xaml
 ..\Microsoft.Expression.Drawing\Themes\Generic.xaml
@@ -71,4 +70,6 @@ TimePicker.xaml
 Drawer.xaml
 DateRangePicker.xaml
 Tag.xaml
-NavScrollPanel.xaml
\ No newline at end of file
+NavScrollPanel.xaml
+GestureUnlock.xaml
+WDUserControl.xaml
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/Themes/TimePicker.xaml b/src/WPFDevelopers.Shared/Themes/TimePicker.xaml
index e2de6dbb..62926d01 100644
--- a/src/WPFDevelopers.Shared/Themes/TimePicker.xaml
+++ b/src/WPFDevelopers.Shared/Themes/TimePicker.xaml
@@ -216,7 +216,8 @@
                             AllowsTransparency="True"
                             IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                             Placement="Bottom"
-                            PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
+                            PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
+                            StaysOpen="False">
                             <controls:SmallPanel
                                 x:Name="PART_DropDown"
                                 MinWidth="{TemplateBinding FrameworkElement.ActualWidth}"
diff --git a/src/WPFDevelopers.Shared/Themes/WDUserControl.xaml b/src/WPFDevelopers.Shared/Themes/WDUserControl.xaml
new file mode 100644
index 00000000..d8e8686c
--- /dev/null
+++ b/src/WPFDevelopers.Shared/Themes/WDUserControl.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:controls="clr-namespace:WPFDevelopers.Controls"
+    xmlns:helpers="clr-namespace:WPFDevelopers.Helpers"
+    xmlns:resx="clr-namespace:WPFDevelopers">
+    <ResourceDictionary.MergedDictionaries>
+        <ResourceDictionary Source="Basic/ControlBasic.xaml" />
+    </ResourceDictionary.MergedDictionaries>
+    <Style
+        x:Key="WD.WDUserControl"
+        BasedOn="{StaticResource WD.ControlBasicStyle}"
+        TargetType="{x:Type controls:WDUserControl}">
+        <Setter Property="Background" Value="{DynamicResource WD.BackgroundBrush}" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type controls:WDUserControl}">
+                    <Border Background="{TemplateBinding Background}">
+                        <ContentPresenter />
+                    </Border>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style BasedOn="{StaticResource WD.WDUserControl}" TargetType="{x:Type controls:WDUserControl}" />
+
+</ResourceDictionary>
\ No newline at end of file
diff --git a/src/WPFDevelopers.Shared/WPFDevelopers.Shared.projitems b/src/WPFDevelopers.Shared/WPFDevelopers.Shared.projitems
index d4fbf8fe..dd5ba353 100644
--- a/src/WPFDevelopers.Shared/WPFDevelopers.Shared.projitems
+++ b/src/WPFDevelopers.Shared/WPFDevelopers.Shared.projitems
@@ -12,6 +12,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)Controls\BaseControls\ScaleBase.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\BaseControls\SliderRepeatButton.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\BaseControls\WDBorder.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Controls\BaseControls\WDUserControl.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Charts\ChartBase.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Charts\ChartLine.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Charts\ChartPie.cs" />
@@ -23,6 +24,8 @@
     <Compile Include="$(MSBuildThisFileDirectory)Controls\DateRangePicker\DateRangePicker.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Drawer\Drawer.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Gauge\Gauge.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Controls\GestureUnlock\GestureItem.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Controls\GestureUnlock\GestureUnlock.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\IPEditBox\IPEditBox.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Loadings\LoadingBase.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Loading\LoadingExt.cs" />
@@ -59,6 +62,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)Core\Converts\ColorConverter.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Converts\ColorTypeToVisibilityConverter.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Converts\CornerRadiusToSurroundConverter.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Core\Helpers\OSVersionHelper.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Helpers\TreeViewHelper.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)ThemeManager.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Converts\DatePickerToCurrentConverter.cs" />
@@ -69,7 +73,6 @@
     <Compile Include="$(MSBuildThisFileDirectory)Core\Helpers\Helper.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Helpers\ImagingHelper.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Converts\WidthHeightToRectConverter.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)Core\Helpers\MonitorHelper.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Helpers\PanelHelper.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Helpers\TextBoxHelper.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Core\Utilities\FormatExtensions.cs" />
@@ -146,7 +149,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)Controls\ScreenCut\ScreenCutAdorner.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\SpotLight\SpotLight.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\StarrySky\StarrySky.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)Controls\Status.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Controls\State.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Step\Step.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Step\StepItem.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Controls\Thermometer\Thermometer.cs" />
@@ -321,10 +324,6 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
-    <Page Include="$(MSBuildThisFileDirectory)Styles\Styles.Grid.xaml">
-      <Generator>MSBuild:Compile</Generator>
-      <SubType>Designer</SubType>
-    </Page>
     <Page Include="$(MSBuildThisFileDirectory)Styles\Styles.GridSplitter.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
@@ -545,6 +544,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="$(MSBuildThisFileDirectory)Themes\GestureUnlock.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
     <Page Include="$(MSBuildThisFileDirectory)Themes\Tag.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
@@ -557,6 +560,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="$(MSBuildThisFileDirectory)Themes\WDUserControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="$(MSBuildThisFileDirectory)Languages\Language.en-US.resx" />
