Sharepoint SP1下创建自定义字段应注意的问题
Sharepoint SP1创建自定义字段下面有一个Bug,我不知道SP2解决了这个问题没有:
通过调用自定义字段类型父类的SetCustomProperty(string propertyName,object propertyValue)来修改属性却不能保存,因此通常的做法是创建一个静态Field来缓存这些设置,利用WSPBuilder来创建的自定义字段在模版中重写SetCustomProperty和GetCustomProperty方法,而不用手工完成,只需调用this.SetCustomProperty或者this.GetCustomProperty就可以了,不能调用base.SetCustomProperty和base.GetCustomProperty方法。
字段定义文件如下:
代码
1 <?xml version="1.0" encoding="utf-8" ?>
2 <FieldTypes>
3 <FieldType>
4 <Field Name="TypeName">RegularField</Field>
5 <Field Name="ParentType">Text</Field>
6 <Field Name="TypeDisplayName">A Regular Field</Field>
7 <Field Name="TypeShortDescription">A field type for regular expression</Field>
8 <Field Name="UserCreatable">TRUE</Field>
9 <Field Name="Sortable">TRUE</Field>
10 <Field Name="AllowBaseTypeRendering">TRUE</Field>
11 <Field Name="Filterable">TRUE</Field>
12 <Field Name="FieldTypeClass">SingTel.SharePoint.CustomFields.RegularField,
SingTel.SharePoint.CustomFields, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=fc0c17e3617723dd</Field>
13 <PropertySchema>
14 <Fields>
15 <Field Hidden="FALSE" Name="RegularExpression" DisplayName="Regular Expression" Type="Text" Required="TRUE">
</Field>
16 <Field Hidden="FALSE" Name="ErrorMessage" DisplayName="Error Message" Type="Text" Required="TRUE">
</Field>
17 </Fields>
18 <Fields></Fields>
19 </PropertySchema>
20 <RenderPattern Name="DisplayPattern">
21 <HTML><![CDATA[<font style="color:red;">]]></HTML>
22 <Column/>
23 <HTML><![CDATA[</font>]]></HTML>
24 </RenderPattern>
25 </FieldType>
26 </FieldTypes>
字段类型代码:
代码
1 using System;
2 using System.Collections.Generic;
3 using System.Text.RegularExpressions;
4 using Microsoft.SharePoint;
5 using Microsoft.SharePoint.WebControls;
6
7 namespace SingTel.SharePoint.CustomFields
8 {
9 public class RegularField : SPFieldText
10 {
11 private static string[] CustomPropertyNames = new string[] { "RegularExpression", "ErrorMessage" };
12 public RegularField(SPFieldCollection fields, string fieldName)
13 : base(fields, fieldName)
14 {
15 InitProperties();
16 }
17 public RegularField(SPFieldCollection fields, string typeName, string displayName)
18 : base(fields, typeName, displayName)
19 {
20 InitProperties();
21 }
22 #region Property storage and bug workarounds - do not edit
23 /// <summary>
24 /// Indicates that the field is being created rather than edited. This is necessary to
25 /// work around some bugs in field creation.
26 /// </summary>
27 public bool IsNew
28 {
29 get { return _IsNew; }
30 set { _IsNew = value; }
31 }
32 private bool _IsNew = false;
33 /// <summary>
34 /// Backing fields for custom properties. Using a dictionary to make it easier to abstract
35 /// details of working around SharePoint bugs.
36 /// </summary>
37 private Dictionary<string, string> CustomProperties = new Dictionary<string, string>();
38 /// <summary>
39 /// Static store to transfer custom properties between instances. This is needed to allow
40 /// correct saving of custom properties when a field is created - the custom property
41 /// implementation is not used by any out of box SharePoint features so is really buggy.
42 /// </summary>
43 private static Dictionary<string, string> CustomPropertiesForNewFields = new Dictionary<string, string>();
44 /// <summary>
45 /// Initialise backing fields from base property store
46 /// </summary>
47 private void InitProperties()
48 {
49 foreach (string propertyName in CustomPropertyNames)
50 {
51 CustomProperties[propertyName] = base.GetCustomProperty(propertyName) + "";
52 }
53 }
54 /// <summary>
55 /// Take properties from either the backing fields or the static store and
56 /// put them in the base property store
57 /// </summary>
58 private void SaveProperties()
59 {
60 foreach (string propertyName in CustomPropertyNames)
61 {
62 base.SetCustomProperty(propertyName, GetCustomProperty(propertyName));
63 }
64 }
65 /// <summary>
66 /// Get an identifier for the field being added/edited that will be unique even if
67 /// another user is editing a property of the same name.
68 /// </summary>
69 /// <param name="propertyName"></param>
70 /// <returns></returns>
71 private string GetCacheKey(string propertyName)
72 {
73 return SPContext.Current.GetHashCode() + "_" + (ParentList == null ? "SITE" : ParentList.ID.ToString()) + "_" + propertyName;
74 }
75 /// <summary>
76 /// Replace the buggy base implementation of SetCustomProperty
77 /// </summary>
78 /// <param name="propertyName"></param>
79 /// <param name="propertyValue"></param>
80 new public void SetCustomProperty(string propertyName, object propertyValue)
81 {
82 if (IsNew)
83 {
84 // field is being added - need to put property in cache
85 CustomPropertiesForNewFields[GetCacheKey(propertyName)] = propertyValue + "";
86 }
87 CustomProperties[propertyName] = propertyValue + "";
88 }
89 /// <summary>
90 /// Replace the buggy base implementation of GetCustomProperty
91 /// </summary>
92 /// <param name="propertyName"></param>
93 /// <param name="propertyValue"></param>
94 new public object GetCustomProperty(string propertyName)
95 {
96 if (!IsNew && CustomPropertiesForNewFields.ContainsKey(GetCacheKey(propertyName)))
97 {
98 string s = CustomPropertiesForNewFields[GetCacheKey(propertyName)];
99 CustomPropertiesForNewFields.Remove(GetCacheKey(propertyName));
100 CustomProperties[propertyName] = s;
101 return s;
102 }
103 else
104 {
105 return CustomProperties[propertyName];
106 }
107 }
108 /// <summary>
109 /// Called when a field is created. Without this, update is not called and custom properties
110 /// are not saved.
111 /// </summary>
112 /// <param name="op"></param>
113 public override void OnAdded(SPAddFieldOptions op)
114 {
115 base.OnAdded(op);
116 Update();
117 }
118 #endregion
119 public override BaseFieldControl FieldRenderingControl
120 {
121 get
122 {
123 BaseFieldControl fieldControl = new RegularFieldControl();
124
125 fieldControl.FieldName = InternalName;
126
127 return fieldControl;
128 }
129 }
130 public override void Update()
131 {
132 SaveProperties();
133 base.Update();
134 }
135 public string RegularExpression
136 {
137 get { return this.GetCustomProperty("RegularExpression") + ""; }
138 set { this.SetCustomProperty("RegularExpression", value); }
139 }
140 public String ErrorMessage
141 {
142 get
143 {
144 return this.GetCustomProperty("ErrorMessage") + "";
145 }
146 set
147 {
148 this.SetCustomProperty("ErrorMessage", value);
149 }
150 }
151 public override string GetValidatedString(object value)
152 {
153 if(value==null || String.IsNullOrEmpty(value.ToString())) throw new SPFieldValidationException("Value is null or empty");
154 if(!Regex.IsMatch(value.ToString(),RegularExpression)) throw new SPFieldValidationException(ErrorMessage);
155 return base.GetValidatedString(value);
156 }
157 }
158 }
UI控件如下:
代码
1 using System.Web.UI;
2 using System.Web.UI.WebControls;
3 using Microsoft.SharePoint.WebControls;
4
5 namespace SingTel.SharePoint.CustomFields
6 {
7 public class RegularFieldControl : BaseFieldControl
8 {
9 private TextBox textBox;
10 public RegularFieldControl() { }
11
12 protected override void CreateChildControls()
13 {
14 base.CreateChildControls();
15 if (this.ControlMode == SPControlMode.Display)
16 {
17 this.Controls.Add(new LiteralControl("" + this.Value));
18 }
19 else
20 {
21 textBox = new TextBox();
22 this.Controls.Add(textBox);
23 }
24 }
25 public override object Value
26 {
27 get
28 {
29 EnsureChildControls();
30 if (this.textBox != null)
31 return this.textBox.Text;
32 else
33 return null;
34 }
35 set
36 {
37 EnsureChildControls();
38 if (this.textBox != null)
39 {
40 this.textBox.Text = "" + value;
41 }
42 }
43 }
44 }
45 }
补充:上面字段类型代码中有点错误,应该在该字段必须填写的情况下才执行验证,改正如下:
代码
1 public override string GetValidatedString(object value)
2 {
3 if (base.Required)
4 {
5 if (value == null || String.IsNullOrEmpty(value.ToString())) throw new SPFieldValidationException("Value is null or empty");
6 if (!Regex.IsMatch(value.ToString(), RegularExpression)) throw new SPFieldValidationException(ErrorMessage);
7 }
8 return base.GetValidatedString(value);
9 }