Skip to content

Commit e8ac6e6

Browse files
author
wenjia
committed
[add]:界面库代码
1 parent 5cb8e0f commit e8ac6e6

File tree

3 files changed

+211
-0
lines changed

3 files changed

+211
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
using System;
2+
using System.Reflection;
3+
using System.Windows;
4+
using System.Windows.Input;
5+
using System.Windows.Threading;
6+
7+
namespace ControlzEx
8+
{
9+
/// <summary>
10+
/// Helper class for a common focusing problem.
11+
/// The focus itself isn't the problem. If we use the common focusing methods the control get the focus
12+
/// but it doesn't get the focus visual style.
13+
/// The KeyboardNavigation class handles the visual style only if the control get the focus from a keyboard
14+
/// device or if the SystemParameters.KeyboardCues is true.
15+
/// </summary>
16+
public sealed class KeyboardNavigationEx
17+
{
18+
private static KeyboardNavigationEx _instance;
19+
//internal static bool AlwaysShowFocusVisual
20+
private readonly PropertyInfo _alwaysShowFocusVisual;
21+
//internal static void ShowFocusVisual()
22+
private readonly MethodInfo _showFocusVisual;
23+
24+
// Explicit static constructor to tell C# compiler
25+
// not to mark type as beforefieldinit
26+
static KeyboardNavigationEx()
27+
{
28+
}
29+
30+
private KeyboardNavigationEx()
31+
{
32+
var type = typeof(KeyboardNavigation);
33+
_alwaysShowFocusVisual = type.GetProperty("AlwaysShowFocusVisual", BindingFlags.NonPublic | BindingFlags.Static);
34+
_showFocusVisual = type.GetMethod("ShowFocusVisual", BindingFlags.NonPublic | BindingFlags.Static);
35+
}
36+
37+
/// <summary>
38+
/// Gets the KeyboardNavigationEx singleton instance.
39+
/// </summary>
40+
internal static KeyboardNavigationEx Instance => _instance ?? (_instance = new KeyboardNavigationEx());
41+
42+
/// <summary>
43+
/// Shows the focus visual of the current focused UI element.
44+
/// Works only together with AlwaysShowFocusVisual property.
45+
/// </summary>
46+
internal void ShowFocusVisualInternal()
47+
{
48+
_showFocusVisual.Invoke(null, null);
49+
}
50+
51+
internal bool AlwaysShowFocusVisualInternal
52+
{
53+
get { return (bool) _alwaysShowFocusVisual.GetValue(null, null); }
54+
set { _alwaysShowFocusVisual.SetValue(null, value, null); }
55+
}
56+
57+
/// <summary>
58+
/// Focuses the specified element and shows the focus visual style.
59+
/// </summary>
60+
/// <param name="element">The element which will be focused.</param>
61+
public static void Focus(UIElement element)
62+
{
63+
element?.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
64+
{
65+
var keybHack = KeyboardNavigationEx.Instance;
66+
var alwaysShowFocusVisual = keybHack.AlwaysShowFocusVisualInternal;
67+
keybHack.AlwaysShowFocusVisualInternal = true;
68+
try
69+
{
70+
Keyboard.Focus(element);
71+
keybHack.ShowFocusVisualInternal();
72+
}
73+
finally
74+
{
75+
keybHack.AlwaysShowFocusVisualInternal = alwaysShowFocusVisual;
76+
}
77+
}));
78+
}
79+
80+
/// <summary>
81+
/// Attached DependencyProperty for setting AlwaysShowFocusVisual for a UI element.
82+
/// </summary>
83+
public static readonly DependencyProperty AlwaysShowFocusVisualProperty
84+
= DependencyProperty.RegisterAttached("AlwaysShowFocusVisual",
85+
typeof(bool),
86+
typeof(KeyboardNavigationEx),
87+
new FrameworkPropertyMetadata(default(bool), AlwaysShowFocusVisualPropertyChangedCallback));
88+
89+
private static void AlwaysShowFocusVisualPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
90+
{
91+
var fe = dependencyObject as UIElement;
92+
if (fe != null && args.NewValue != args.OldValue)
93+
{
94+
fe.GotFocus -= FrameworkElementGotFocus;
95+
if ((bool)args.NewValue)
96+
{
97+
fe.GotFocus += FrameworkElementGotFocus;
98+
}
99+
}
100+
}
101+
102+
private static void FrameworkElementGotFocus(object sender, RoutedEventArgs e)
103+
{
104+
KeyboardNavigationEx.Focus(sender as UIElement);
105+
}
106+
107+
/// <summary>
108+
/// Gets a the value which indicates if the UI element always show the focus visual style.
109+
/// </summary>
110+
[AttachedPropertyBrowsableForType(typeof(UIElement))]
111+
public static bool GetAlwaysShowFocusVisual(UIElement element)
112+
{
113+
return (bool)element.GetValue(AlwaysShowFocusVisualProperty);
114+
}
115+
116+
/// <summary>
117+
/// Sets a the value which indicates if the UI element always show the focus visual style.
118+
/// </summary>
119+
public static void SetAlwaysShowFocusVisual(UIElement element, bool value)
120+
{
121+
element.SetValue(AlwaysShowFocusVisualProperty, value);
122+
}
123+
}
124+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.Windows;
5+
using System.Windows.Controls;
6+
using System.Windows.Media;
7+
8+
namespace ControlzEx
9+
{
10+
public abstract class PackIconBase : Control
11+
{
12+
internal abstract void UpdateData();
13+
}
14+
15+
/// <summary>
16+
/// Base class for creating an icon control for icon packs.
17+
/// </summary>
18+
/// <typeparam name="TKind"></typeparam>
19+
public abstract class PackIconBase<TKind> : PackIconBase
20+
{
21+
private static Lazy<IDictionary<TKind, string>> _dataIndex;
22+
23+
/// <param name="dataIndexFactory">
24+
/// Inheritors should provide a factory for setting up the path data index (per icon kind).
25+
/// The factory will only be utilised once, across all closed instances (first instantiation wins).
26+
/// </param>
27+
protected PackIconBase(Func<IDictionary<TKind, string>> dataIndexFactory)
28+
{
29+
if (dataIndexFactory == null) throw new ArgumentNullException(nameof(dataIndexFactory));
30+
31+
if (_dataIndex == null)
32+
_dataIndex = new Lazy<IDictionary<TKind, string>>(dataIndexFactory);
33+
}
34+
35+
public static readonly DependencyProperty KindProperty = DependencyProperty.Register(
36+
"Kind", typeof(TKind), typeof(PackIconBase<TKind>), new PropertyMetadata(default(TKind), KindPropertyChangedCallback));
37+
38+
private static void KindPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
39+
{
40+
((PackIconBase)dependencyObject).UpdateData();
41+
}
42+
43+
/// <summary>
44+
/// Gets or sets the icon to display.
45+
/// </summary>
46+
public TKind Kind
47+
{
48+
get { return (TKind)GetValue(KindProperty); }
49+
set { SetValue(KindProperty, value); }
50+
}
51+
52+
private static readonly DependencyPropertyKey DataPropertyKey =
53+
DependencyProperty.RegisterReadOnly(
54+
"Data", typeof(string), typeof(PackIconBase<TKind>),
55+
new PropertyMetadata(default(string)));
56+
57+
// ReSharper disable once StaticMemberInGenericType
58+
public static readonly DependencyProperty DataProperty =
59+
DataPropertyKey.DependencyProperty;
60+
61+
/// <summary>
62+
/// Gets the icon path data for the current <see cref="Kind"/>.
63+
/// </summary>
64+
[TypeConverter(typeof(GeometryConverter))]
65+
public string Data
66+
{
67+
get { return (string)GetValue(DataProperty); }
68+
private set { SetValue(DataPropertyKey, value); }
69+
}
70+
71+
public override void OnApplyTemplate()
72+
{
73+
base.OnApplyTemplate();
74+
75+
UpdateData();
76+
}
77+
78+
internal override void UpdateData()
79+
{
80+
string data = null;
81+
if (_dataIndex.Value != null)
82+
_dataIndex.Value.TryGetValue(Kind, out data);
83+
Data = data;
84+
}
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
72aa238cd565ef63e8d52c29982a587e039d04ec

0 commit comments

Comments
 (0)