Skip to content

Commit 2b35e4b

Browse files
committed
chore: add ControlTokenManager.
1 parent f998282 commit 2b35e4b

File tree

8 files changed

+287
-310
lines changed

8 files changed

+287
-310
lines changed

src/Shared/HandyControlDemo_Shared/MainWindow.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
Background="{DynamicResource SecondaryRegionBrush}"
1212
ResizeMode="CanResizeWithGrip"
1313
WindowStartupLocation="CenterScreen"
14-
d:DesignHeight="800"
14+
d:DesignHeight="800"
1515
d:DesignWidth="1400"
1616
hc:Empty.ShowEmpty="True"
1717
Icon="/HandyControlDemo;component/Resources/Img/icon.ico">

src/Shared/HandyControlDemo_Shared/UserControl/Styles/NativeScrollViewerDemo.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
xmlns:hc="https://handyorg.github.io/handycontrol"
55
xmlns:langs="clr-namespace:HandyControlDemo.Properties.Langs"
66
xmlns:ex="clr-namespace:HandyControlDemo.Tools.Extension"
7-
Background="{DynamicResource RegionBrush}"
7+
Background="{DynamicResource RegionBrush}"
88
MaxWidth="550"
99
Height="600">
1010
<hc:TransitioningContentControl>
@@ -45,7 +45,7 @@
4545
</ScrollViewer>
4646
</Border>
4747
<Border Grid.Row="1" BorderThickness="1" BorderBrush="{DynamicResource BorderBrush}" Margin="0,16,0,0">
48-
<ScrollViewer>
48+
<ScrollViewer hc:ScrollViewerAttach.IsHoverResizingEnabled="False" hc:ScrollViewerAttach.AutoHide="False">
4949
<WrapPanel Orientation="Horizontal">
5050
<Border Style="{StaticResource BorderRegion}" Width="200" Height="200" Margin="10,10,32,10">
5151
<Border Background="{DynamicResource PrimaryBrush}">

src/Shared/HandyControl_Shared/Controls/ConfettiCannon/ConfettiCannon.cs

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ namespace HandyControl.Controls;
1313

1414
public class ConfettiCannon
1515
{
16+
private static readonly ControlTokenManager<FrameworkElement> TokenManager =
17+
new(unregisterCallback: OnTokenUnregistered);
18+
1619
public static readonly DependencyProperty TokenProperty = DependencyProperty.RegisterAttached(
17-
"Token", typeof(string), typeof(ConfettiCannon), new PropertyMetadata(null, OnTokenChanged));
20+
"Token", typeof(string), typeof(ConfettiCannon), new PropertyMetadata(null, TokenManager.OnTokenChanged));
1821

1922
public static void SetToken(DependencyObject element, string value)
2023
=> element.SetValue(TokenProperty, value);
@@ -23,7 +26,6 @@ public static string GetToken(DependencyObject element)
2326
=> (string) element.GetValue(TokenProperty);
2427

2528
private static readonly ConcurrentDictionary<string, ConfettiCannon> ConfettiCannons = new();
26-
private static readonly Dictionary<string, FrameworkElement> ContainerDict = new();
2729
private static readonly Lazy<ConfettiCannon> DefaultConfettiCannon = new(() => new ConfettiCannon(), true);
2830
private static readonly Random Random = new();
2931

@@ -50,35 +52,8 @@ public static void Fire(Options options)
5052
confettiCannon.StartAnimation();
5153
}
5254

53-
public static void Register(string token, FrameworkElement element)
54-
{
55-
if (string.IsNullOrEmpty(token) || element is null)
56-
{
57-
return;
58-
}
59-
60-
ContainerDict[token] = element;
61-
}
62-
63-
public static void Unregister(FrameworkElement element)
55+
private static void OnTokenUnregistered(string token, FrameworkElement element)
6456
{
65-
if (element is null)
66-
{
67-
return;
68-
}
69-
70-
var first = ContainerDict.FirstOrDefault(item => ReferenceEquals(element, item.Value));
71-
Unregister(first.Key);
72-
}
73-
74-
public static void Unregister(string token)
75-
{
76-
if (string.IsNullOrEmpty(token))
77-
{
78-
return;
79-
}
80-
81-
ContainerDict.Remove(token);
8257
ConfettiCannons.TryRemove(token, out _);
8358
}
8459

@@ -98,23 +73,6 @@ private static ConfettiCannon EnsureConfettiCannon(string token)
9873
return ConfettiCannons[token];
9974
}
10075

101-
private static void OnTokenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
102-
{
103-
if (d is not FrameworkElement element)
104-
{
105-
return;
106-
}
107-
108-
if (e.NewValue is null)
109-
{
110-
Unregister(element);
111-
}
112-
else
113-
{
114-
Register(e.NewValue.ToString(), element);
115-
}
116-
}
117-
11876
private static AdornerLayer GetAdornerLayer(string token)
11977
{
12078
AdornerDecorator decorator;
@@ -125,7 +83,7 @@ private static AdornerLayer GetAdornerLayer(string token)
12583
}
12684
else
12785
{
128-
ContainerDict.TryGetValue(token, out FrameworkElement element);
86+
TokenManager.TryGetControl(token, out FrameworkElement element);
12987
decorator = element is System.Windows.Window
13088
? VisualHelper.GetChild<AdornerDecorator>(element)
13189
: VisualHelper.GetChild<ConfettiCannonContainer>(element);

src/Shared/HandyControl_Shared/Controls/Dialog/Dialog.cs

Lines changed: 10 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Generic;
2-
using System.Linq;
32
using System.Windows;
43
using System.Windows.Controls;
54
using System.Windows.Documents;
@@ -20,7 +19,7 @@ public class Dialog : ContentControl
2019
private Border _backElement;
2120
private AdornerContainer _container;
2221

23-
private static readonly Dictionary<string, FrameworkElement> ContainerDict = new();
22+
private static readonly ControlTokenManager<FrameworkElement> TokenManager = new();
2423
private static readonly Dictionary<string, Dialog> DialogDict = new();
2524

2625
public static readonly DependencyProperty IsClosedProperty = DependencyProperty.Register(
@@ -33,7 +32,8 @@ public bool IsClosed
3332
}
3433

3534
public static readonly DependencyProperty MaskCanCloseProperty = DependencyProperty.RegisterAttached(
36-
"MaskCanClose", typeof(bool), typeof(Dialog), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
35+
"MaskCanClose", typeof(bool), typeof(Dialog),
36+
new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
3737

3838
public static void SetMaskCanClose(DependencyObject element, bool value)
3939
=> element.SetValue(MaskCanCloseProperty, ValueBoxes.BooleanBox(value));
@@ -51,22 +51,7 @@ public Brush MaskBrush
5151
}
5252

5353
public static readonly DependencyProperty TokenProperty = DependencyProperty.RegisterAttached(
54-
"Token", typeof(string), typeof(Dialog), new PropertyMetadata(default(string), OnTokenChanged));
55-
56-
private static void OnTokenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
57-
{
58-
if (d is FrameworkElement element)
59-
{
60-
if (e.NewValue == null)
61-
{
62-
Unregister(element);
63-
}
64-
else
65-
{
66-
Register(e.NewValue.ToString(), element);
67-
}
68-
}
69-
}
54+
"Token", typeof(string), typeof(Dialog), new PropertyMetadata(null, TokenManager.OnTokenChanged));
7055

7156
public static void SetToken(DependencyObject element, string value)
7257
=> element.SetValue(TokenProperty, value);
@@ -79,45 +64,6 @@ public Dialog()
7964
CommandBindings.Add(new CommandBinding(ControlCommands.Close, (s, e) => Close()));
8065
}
8166

82-
public static void Register(string token, FrameworkElement element)
83-
{
84-
if (string.IsNullOrEmpty(token) || element == null) return;
85-
ContainerDict[token] = element;
86-
}
87-
88-
public static void Unregister(string token, FrameworkElement element)
89-
{
90-
if (string.IsNullOrEmpty(token) || element == null) return;
91-
92-
if (ContainerDict.ContainsKey(token))
93-
{
94-
if (ReferenceEquals(ContainerDict[token], element))
95-
{
96-
ContainerDict.Remove(token);
97-
}
98-
}
99-
}
100-
101-
public static void Unregister(FrameworkElement element)
102-
{
103-
if (element == null) return;
104-
var first = ContainerDict.FirstOrDefault(item => ReferenceEquals(element, item.Value));
105-
if (!string.IsNullOrEmpty(first.Key))
106-
{
107-
ContainerDict.Remove(first.Key);
108-
}
109-
}
110-
111-
public static void Unregister(string token)
112-
{
113-
if (string.IsNullOrEmpty(token)) return;
114-
115-
if (ContainerDict.ContainsKey(token))
116-
{
117-
ContainerDict.Remove(token);
118-
}
119-
}
120-
12167
public static Dialog Show<T>(string token = "") where T : new() => Show(new T(), token);
12268

12369
public static Dialog Show(object content, string token = "")
@@ -140,10 +86,10 @@ public static Dialog Show(object content, string token = "")
14086
{
14187
Close(token);
14288
DialogDict[token] = dialog;
143-
ContainerDict.TryGetValue(token, out element);
144-
decorator = element is System.Windows.Window ?
145-
VisualHelper.GetChild<AdornerDecorator>(element) :
146-
VisualHelper.GetChild<DialogContainer>(element);
89+
TokenManager.TryGetControl(token, out element);
90+
decorator = element is System.Windows.Window
91+
? VisualHelper.GetChild<AdornerDecorator>(element)
92+
: VisualHelper.GetChild<DialogContainer>(element);
14793
}
14894

14995
if (decorator != null)
@@ -183,7 +129,7 @@ public void Close()
183129
{
184130
Close(WindowHelper.GetActiveWindow());
185131
}
186-
else if (ContainerDict.TryGetValue(_token, out var element))
132+
else if (TokenManager.TryGetControl(_token, out var element))
187133
{
188134
Close(element);
189135
DialogDict.Remove(_token);
@@ -216,6 +162,7 @@ private void Close(DependencyObject element)
216162
{
217163
decorator.Child.IsEnabled = true;
218164
}
165+
219166
var layer = decorator.AdornerLayer;
220167
layer?.Remove(_container);
221168
IsClosed = true;

0 commit comments

Comments
 (0)