继承自System.Windows.Controls.Control是不知什么时候调用OnApplyTemplate方法的,这就有可能给你制造麻烦,例如,开发了一个PathButton控件,XAML中定义一个了Path对象,然后定义了Data这个属性,让使用者可以设置Path的Data,
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>The data.</value>
public string Data
{
get { return (string)GetValue(DataProperty); }
set
{
SetValue(DataProperty, value);
PathElement.Data = Services.PathGeometryParser.Parse(value);
}
}
其它地方使用这个控件
PathButton bt = new PathButton();
bt.Data = "....";
NullReferenceException
解决的方法就是在PathButton的构造函数里就进行加载模板,然后调用ApplyTemplate方法。下面是我的实现方法,代码很简单
1 /// <summary>
2 /// XControl
3 /// </summary>
4 public class XControl : Control
5 {
6 /// <summary>
7 /// True表示已经应用过模板
8 /// </summary>
9 protected bool _TemplateApplied;
10
11 /// <summary>
12 /// 初始化组件
13 /// </summary>
14 protected virtual void InitializeComponent()
15 {
16 var objStyle = GetStyle(this.DefaultStyleKey as Type);
17 if (objStyle != null)
18 {
19 this.Style = objStyle;
20 this.ApplyTemplate();
21 }
22 }
23 /// <summary>
24 /// 请重写此方法代替OnApplyTemplate
25 /// </summary>
26 protected virtual void OnApplyXTemplate()
27 {
28
29 }
30 /// <summary>
31 /// 请重写OnApplyXTemplate方法代替
32 /// </summary>
33 public override sealed void OnApplyTemplate()
34 {
35 if (this._TemplateApplied)
36 return;
37 this._TemplateApplied = true;
38 this.OnApplyXTemplate();
39 }
40
41 #region Static Methods
42 /// <summary>
43 /// 样式字典集合
44 /// </summary>
45 private static System.Collections.Generic.Dictionary<Type, ResourceDictionary> _ResourceDictionarys =
46 new System.Collections.Generic.Dictionary<Type, ResourceDictionary>();
47 /// <summary>
48 /// 获取样式
49 /// </summary>
50 /// <param name="styleKey"></param>
51 /// <returns></returns>
52 static public Style GetStyle(Type styleKey)
53 {
54 var rd = GetResourceDictionary(styleKey);
55 if (rd != null)
56 {
57 string strKey = styleKey.ToString();
58 if (rd.Contains(strKey))
59 return rd[strKey] as Style;
60 }
61 return null;
62 }
63 /// <summary>
64 /// 获取样式字典
65 /// </summary>
66 /// <param name="styleKey"></param>
67 /// <returns></returns>
68 static public ResourceDictionary GetResourceDictionary(Type styleKey)
69 {
70 if (_ResourceDictionarys.ContainsKey(styleKey))
71 return _ResourceDictionarys[styleKey];
72
73 string fullName = styleKey.Assembly.FullName;
74 string baseName = fullName.Substring(0, fullName.IndexOf(",")) + ".g";
75
76 System.Resources.ResourceManager manager = new System.Resources.ResourceManager(baseName, styleKey.Assembly);
77 System.IO.UnmanagedMemoryStream stream = null;
78 try
79 {
80 stream = manager.GetStream("themes/generic.xaml", System.Globalization.CultureInfo.CurrentUICulture);
81 string strTemplate = new System.IO.StreamReader(stream).ReadToEnd();
82 var rd = System.Windows.Markup.XamlReader.Load(strTemplate) as ResourceDictionary;
83 _ResourceDictionarys.Add(styleKey, rd);
84 return rd;
85 }
86 catch { }
87 finally
88 {
89 stream.Dispose();
90 }
91 return null;
92 }
93 #endregion
94 }
1 public class PathButton2 : XControl
2 {
3 public PathButton2()
4 {
5 this.DefaultStyleKey = typeof(PathButton);
6 //初始化组件
7 base.InitializeComponent();
8 }
9 /// <summary>
10 /// 重写OnApplyXTemplate代替OnApplyTemplate方法
11 /// </summary>
12 protected override void OnApplyXTemplate()
13 {
14 base.OnApplyXTemplate();
15 }
16 }
17
通过继承XControl的自定义控件与System.Windows.Controls.Control不同在于,需要重写OnApplyXTemplate代替OnApplyTemplate方法,然后在构造函数里设置DefaultStyleKey后手动调用InitializeComponent方法。
本文作者:未知