diff --git a/src/Shared/HandyControl_Shared/Controls/Base/AdornerElement.cs b/src/Shared/HandyControl_Shared/Controls/Base/AdornerElement.cs
new file mode 100644
index 00000000..c3fa3241
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Controls/Base/AdornerElement.cs
@@ -0,0 +1,87 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using HandyControl.Data;
+
+namespace HandyControl.Controls
+{
+ public abstract class AdornerElement : Control, IDisposable
+ {
+ protected FrameworkElement ElementTarget { get; set; }
+
+ public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
+ "Target", typeof(FrameworkElement), typeof(AdornerElement), new PropertyMetadata(default(FrameworkElement), OnTargetChanged));
+
+ private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var ctl = (AdornerElement)d;
+ ctl.OnTargetChanged(ctl.ElementTarget, false);
+ ctl.OnTargetChanged((FrameworkElement)e.NewValue, true);
+ }
+
+ [Bindable(true), Category("Layout")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public FrameworkElement Target
+ {
+ get => (FrameworkElement) GetValue(TargetProperty);
+ set => SetValue(TargetProperty, value);
+ }
+
+ public static readonly DependencyProperty InstanceProperty = DependencyProperty.RegisterAttached(
+ "Instance", typeof(AdornerElement), typeof(AdornerElement), new PropertyMetadata(default(AdornerElement), OnInstanceChanged));
+
+ private static void OnInstanceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (!(d is FrameworkElement target)) return;
+ var element = (AdornerElement)e.NewValue;
+ element.OnInstanceChanged(target);
+ }
+
+ protected virtual void OnInstanceChanged(FrameworkElement target) => Target = target;
+
+ public static void SetInstance(DependencyObject element, AdornerElement value)
+ => element.SetValue(InstanceProperty, value);
+
+ public static AdornerElement GetInstance(DependencyObject element)
+ => (AdornerElement) element.GetValue(InstanceProperty);
+
+ public static readonly DependencyProperty IsInstanceProperty = DependencyProperty.RegisterAttached(
+ "IsInstance", typeof(bool), typeof(AdornerElement), new PropertyMetadata(ValueBoxes.TrueBox));
+
+ public static void SetIsInstance(DependencyObject element, bool value)
+ => element.SetValue(IsInstanceProperty, value);
+
+ public static bool GetIsInstance(DependencyObject element)
+ => (bool) element.GetValue(IsInstanceProperty);
+
+ protected virtual void OnTargetChanged(FrameworkElement element, bool isNew)
+ {
+ if (element == null) return;
+
+ if (!isNew)
+ {
+ element.Unloaded -= TargetElement_Unloaded;
+ ElementTarget = null;
+ }
+ else
+ {
+ element.Unloaded += TargetElement_Unloaded;
+ ElementTarget = element;
+ }
+ }
+
+ private void TargetElement_Unloaded(object sender, RoutedEventArgs e)
+ {
+ if (sender is FrameworkElement element)
+ {
+ element.Unloaded -= TargetElement_Unloaded;
+ Dispose();
+ }
+ }
+
+ protected abstract void Dispose();
+
+ void IDisposable.Dispose() => Dispose();
+ }
+}
diff --git a/src/Shared/HandyControl_Shared/Controls/Other/Magnifier.cs b/src/Shared/HandyControl_Shared/Controls/Other/Magnifier.cs
index 407adeb1..d80c0e26 100644
--- a/src/Shared/HandyControl_Shared/Controls/Other/Magnifier.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Other/Magnifier.cs
@@ -1,5 +1,4 @@
using System.Windows;
-using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
@@ -11,14 +10,12 @@ using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementVisualBrush, Type = typeof(VisualBrush))]
- public class Magnifier : Control
+ public class Magnifier : AdornerElement
{
+ private AdornerContainer _adornerContainer;
+
private Size _viewboxSize;
- private AdornerContainer _adorner;
-
- private UIElement _elementTarget;
-
private const string ElementVisualBrush = "PART_VisualBrush";
private VisualBrush _visualBrush = new VisualBrush();
@@ -43,40 +40,8 @@ namespace HandyControl.Controls
set => SetValue(VerticalOffsetProperty, value);
}
- public static readonly DependencyProperty InstanceProperty = DependencyProperty.RegisterAttached(
- "Instance", typeof(Magnifier), typeof(Magnifier), new PropertyMetadata(default(Magnifier), OnMagnifierChanged));
-
- private static void OnMagnifierChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (!(d is UIElement target)) return;
- var magnifier = (Magnifier)e.NewValue;
- magnifier.Target = target;
- }
-
- public static void SetInstance(DependencyObject element, Magnifier value)
- => element.SetValue(InstanceProperty, value);
-
- public static Magnifier GetInstance(DependencyObject element)
- => (Magnifier) element.GetValue(InstanceProperty);
-
public static Magnifier Default => new Magnifier();
- internal static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
- "Target", typeof(UIElement), typeof(Magnifier), new PropertyMetadata(default(UIElement), OnTargetChanged));
-
- private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var ctl = (Magnifier) d;
- ctl.UpdateTarget(ctl._elementTarget, false);
- ctl.UpdateTarget((UIElement)e.NewValue, true);
- }
-
- internal UIElement Target
- {
- get => (UIElement)GetValue(TargetProperty);
- set => SetValue(TargetProperty, value);
- }
-
public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register(
"Scale", typeof(double), typeof(Magnifier), new PropertyMetadata(5.0, OnScaleChanged), ValidateHelper.IsInRangeOfPosDouble);
@@ -111,8 +76,10 @@ namespace HandyControl.Controls
private void UpdateViewboxSize() => _viewboxSize = new Size(ActualWidth / Scale, ActualHeight / Scale);
- private void UpdateTarget(UIElement element , bool isNew)
+ protected sealed override void OnTargetChanged(FrameworkElement element , bool isNew)
{
+ base.OnTargetChanged(element, isNew);
+
if (element == null) return;
if (!isNew)
@@ -120,17 +87,19 @@ namespace HandyControl.Controls
element.MouseEnter -= Element_MouseEnter;
element.MouseLeave -= Element_MouseLeave;
element.MouseMove -= Element_MouseMove;
- _elementTarget = null;
+ ElementTarget = null;
}
else
{
element.MouseEnter += Element_MouseEnter;
element.MouseLeave += Element_MouseLeave;
element.MouseMove += Element_MouseMove;
- _elementTarget = element;
+ ElementTarget = element;
}
}
+ protected override void Dispose() => HideAdornerElement();
+
private void UpdateLocation()
{
var targetPoint = Mouse.GetPosition(Target);
@@ -140,33 +109,48 @@ namespace HandyControl.Controls
var targetVector = VisualTreeHelper.GetOffset(Target);
_visualBrush.Viewbox = new Rect(new Point(subX + targetVector.X, subY + targetVector.Y), _viewboxSize);
- var adornerPoint = Mouse.GetPosition(_adorner);
+ var adornerPoint = Mouse.GetPosition(_adornerContainer);
_translateTransform.X = adornerPoint.X + HorizontalOffset;
_translateTransform.Y = adornerPoint.Y + VerticalOffset;
}
private void Element_MouseMove(object sender, MouseEventArgs e) => UpdateLocation();
- private void Element_MouseLeave(object sender, MouseEventArgs e)
+ private void Element_MouseLeave(object sender, MouseEventArgs e) => HideAdornerElement();
+
+ private void Element_MouseEnter(object sender, MouseEventArgs e) => ShowAdornerElement();
+
+ private void HideAdornerElement()
{
var layer = AdornerLayer.GetAdornerLayer(Target);
- if (layer == null) return;
- layer.Remove(_adorner);
- _adorner.Child = null;
- _adorner = null;
+ if (layer != null)
+ {
+ layer.Remove(_adornerContainer);
+ }
+ else if(_adornerContainer != null && _adornerContainer.Parent is AdornerLayer parent)
+ {
+ parent.Remove(_adornerContainer);
+ }
+
+ if (_adornerContainer != null)
+ {
+ _adornerContainer.Child = null;
+ _adornerContainer = null;
+ }
}
- private void Element_MouseEnter(object sender, MouseEventArgs e)
+ private void ShowAdornerElement()
{
- if (_adorner == null)
+ if (_adornerContainer == null)
{
var layer = AdornerLayer.GetAdornerLayer(Target);
if (layer == null) return;
- _adorner = new AdornerContainer(layer)
+
+ _adornerContainer = new AdornerContainer(layer)
{
Child = this
};
- layer.Add(_adorner);
+ layer.Add(_adornerContainer);
}
this.Show();
}
diff --git a/src/Shared/HandyControl_Shared/Controls/Other/Poptip.cs b/src/Shared/HandyControl_Shared/Controls/Other/Poptip.cs
index 65ec968c..4da52653 100644
--- a/src/Shared/HandyControl_Shared/Controls/Other/Poptip.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Other/Poptip.cs
@@ -1,5 +1,4 @@
using System;
-using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
@@ -10,12 +9,10 @@ using HandyControl.Data.Enum;
namespace HandyControl.Controls
{
- public class Poptip : Control
+ public class Poptip : AdornerElement
{
private readonly Popup _popup;
- private UIElement _elementTarget;
-
public Poptip()
{
_popup = new Popup
@@ -42,15 +39,6 @@ namespace HandyControl.Controls
set => SetValue(HitModeProperty, value);
}
- private static readonly DependencyProperty IsInstanceProperty = DependencyProperty.RegisterAttached(
- "IsInstance", typeof(bool), typeof(Poptip), new PropertyMetadata(ValueBoxes.TrueBox));
-
- private static void SetIsInstance(DependencyObject element, bool value)
- => element.SetValue(IsInstanceProperty, value);
-
- private static bool GetIsInstance(DependencyObject element)
- => (bool) element.GetValue(IsInstanceProperty);
-
public static readonly DependencyProperty ContentProperty = DependencyProperty.RegisterAttached(
"Content", typeof(object), typeof(Poptip), new PropertyMetadata(default, OnContentChanged));
@@ -144,7 +132,7 @@ namespace HandyControl.Controls
}
else
{
- GetInstance(d)?.SwitchPoptip((bool)e.NewValue);
+ ((Poptip)GetInstance(d))?.SwitchPoptip((bool)e.NewValue);
}
}
@@ -160,44 +148,12 @@ namespace HandyControl.Controls
set => SetValue(IsOpenProperty, value);
}
- public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
- "Target", typeof(UIElement), typeof(Poptip), new PropertyMetadata(default(UIElement), OnTargetChanged));
-
- private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var ctl = (Poptip)d;
- ctl.UpdateTarget(ctl._elementTarget, false);
- ctl.UpdateTarget((UIElement)e.NewValue, true);
- }
-
- [Bindable(true), Category("Layout")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public UIElement Target
- {
- get => (UIElement) GetValue(TargetProperty);
- set => SetValue(TargetProperty, value);
- }
-
- public static readonly DependencyProperty InstanceProperty = DependencyProperty.RegisterAttached(
- "Instance", typeof(Poptip), typeof(Poptip), new PropertyMetadata(default(Poptip), OnPoptipChanged));
-
- private static void OnPoptipChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (!(d is UIElement target)) return;
- var poptip = (Poptip)e.NewValue;
- poptip.Target = target;
- }
-
- public static void SetInstance(DependencyObject element, Poptip value)
- => element.SetValue(InstanceProperty, value);
-
- public static Poptip GetInstance(DependencyObject element)
- => (Poptip)element.GetValue(InstanceProperty);
-
public static Poptip Default => new Poptip();
- private void UpdateTarget(UIElement element, bool isNew)
+ protected sealed override void OnTargetChanged(FrameworkElement element, bool isNew)
{
+ base.OnTargetChanged(element, isNew);
+
if (element == null) return;
if (!isNew)
@@ -206,7 +162,7 @@ namespace HandyControl.Controls
element.MouseLeave -= Element_MouseLeave;
element.GotFocus -= Element_GotFocus;
element.LostFocus -= Element_LostFocus;
- _elementTarget = null;
+ ElementTarget = null;
}
else
{
@@ -214,11 +170,13 @@ namespace HandyControl.Controls
element.MouseLeave += Element_MouseLeave;
element.GotFocus += Element_GotFocus;
element.LostFocus += Element_LostFocus;
- _elementTarget = element;
- _popup.PlacementTarget = _elementTarget;
+ ElementTarget = element;
+ _popup.PlacementTarget = ElementTarget;
}
}
+ protected override void Dispose() => SwitchPoptip(false);
+
private void UpdateLocation()
{
var targetWidth = Target.RenderSize.Width;
@@ -233,7 +191,7 @@ namespace HandyControl.Controls
var offsetX = .0;
var offsetY = .0;
- var poptip = GetInstance(Target);
+ var poptip = (Poptip)GetInstance(Target);
var popupPlacement = poptip.Placement;
var popupOffset = poptip.Offset;
diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
index 9c8cb1eb..6c2ea7c9 100644
--- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
+++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
@@ -20,6 +20,7 @@
+