refactor Poptip & Magnifier

This commit is contained in:
NaBian committed 2019-11-19 23:16:24 +08:00
1 parent 6fd86496a2
commit d0dc957c81
4 files changed
+134 -104

No files matched your search

@@ -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();
}
}
@@ -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();
}
@@ -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;
@@ -20,6 +20,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\PasswordBoxAttach.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\RectangleAttach.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\TextBlockAttach.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Base\AdornerElement.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Block\FloatingBlock.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Button\SplitButton.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Growl\GrowlWindow.cs" />