设为首页 收藏本站
查看: 937|回复: 0

[经验分享] [SharePoint开发详解] 自定义字段开发: 投票字段

[复制链接]

尚未签到

发表于 2015-9-25 07:26:26 | 显示全部楼层 |阅读模式
  需求:
  在公司使用SharePoint的过程中,常常有这样的需求,要为一个Document Library或者List中的某一个Item进行打分,投票,根据投票高低来作决策。 比如优秀员工的评比,用户可以直接在页面上点击投票按钮,并得到当前的投票状态。
  现状:
  在CodePlex上找了一个现成的Content  type(HighLight), 安装使用后,发现普通用户不太会使用,而且投票页面没有直接的结果显示,不能完全满足用户的需求,所以想自己开发一个custom field,让普通用户可以象添加一般的field一样添加,并且容易使用。
  开发:
  要实现投票的功能,需要开发2个相关联的custom field。一个负责记录当前所有已投票的用户的信息,这样防止用户多次点击后重复投票,我们称这个field为voting field。另一个field负责计数,显示当前总共的投票数,称为Voting Result field。可能有人要问,为什么不把这两个合而为一呢? 这里主要考虑到排序的问题,因为要记录用户投票信息的字段的type不能是text的,因为text类型有255的长度限制,只能是note型,而note型是不支持在view的页面中排序的。
  下面详细介绍具体的开发
  1 Voting Field
  首先是字段类ItemVoting的代码
  

DSC0000.gif DSC0001.gif 代码

  1  public class ItemVoting : SPFieldText
  2     {
  3         private static string[] CustomPropertyNames = new string[] { "FieldNameProperty" };
  4
  5         public ItemVoting(SPFieldCollection fields, string fieldName)
  6             : base(fields, fieldName)
  7         {
  8             InitProperties();
  9             this.ShowInNewForm = true;
10             this.ShowInEditForm = true;
11            
12         }
13
14         public ItemVoting(SPFieldCollection fields, string typeName, string displayName)
15             : base(fields, typeName, displayName)
16         {
17             InitProperties();
18             this.ShowInNewForm = true;
19             this.ShowInEditForm = true;
20         }
21
22         #region Property storage and bug workarounds - do not edit
23
24         /// <summary>
25         /// Indicates that the field is being created rather than edited. This is necessary to
26         /// work around some bugs in field creation.
27         /// </summary>
28         public bool IsNew
29         {
30             get { return _IsNew; }
31             set { _IsNew = value; }
32         }
33         private bool _IsNew = false;
34
35         /// <summary>
36         /// Backing fields for custom properties. Using a dictionary to make it easier to abstract
37         /// details of working around SharePoint bugs.
38         /// </summary>
39         private Dictionary<string, string> CustomProperties = new Dictionary<string, string>();
40
41         /// <summary>
42         /// Static store to transfer custom properties between instances. This is needed to allow
43         /// correct saving of custom properties when a field is created - the custom property
44         /// implementation is not used by any out of box SharePoint features so is really buggy.
45         /// </summary>
46         private static Dictionary<string, string> CustomPropertiesForNewFields = new Dictionary<string, string>();
47
48         /// <summary>
49         /// Initialise backing fields from base property store
50         /// </summary>
51         private void InitProperties()
52         {
53             foreach (string propertyName in CustomPropertyNames)
54             {
55                 CustomProperties[propertyName] = base.GetCustomProperty(propertyName) + "";
56             }
57         }
58
59         /// <summary>
60         /// Take properties from either the backing fields or the static store and
61         /// put them in the base property store
62         /// </summary>
63         private void SaveProperties()
64         {
65             foreach (string propertyName in CustomPropertyNames)
66             {
67                 base.SetCustomProperty(propertyName, GetCustomProperty(propertyName));
68             }
69         }
70
71         /// <summary>
72         /// Get an identifier for the field being added/edited that will be unique even if
73         /// another user is editing a property of the same name.
74         /// </summary>
75         /// <param name="propertyName"></param>
76         /// <returns></returns>
77         private string GetCacheKey(string propertyName)
78         {
79             return SPContext.Current.GetHashCode() + "_" + (ParentList == null ? "SITE" : ParentList.ID.ToString()) + "_" + propertyName;
80         }
81
82         /// <summary>
83         /// Replace the buggy base implementation of SetCustomProperty
84         /// </summary>
85         /// <param name="propertyName"></param>
86         /// <param name="propertyValue"></param>
87         new public void SetCustomProperty(string propertyName, object propertyValue)
88         {
89             if (IsNew)
90             {
91                 // field is being added - need to put property in cache
92                 CustomPropertiesForNewFields[GetCacheKey(propertyName)] = propertyValue + "";
93             }
94
95             CustomProperties[propertyName] = propertyValue + "";
96         }
97
98         /// <summary>
99         /// Replace the buggy base implementation of GetCustomProperty
100         /// </summary>
101         /// <param name="propertyName"></param>
102         /// <param name="propertyValue"></param>
103         new public object GetCustomProperty(string propertyName)
104         {
105             if (!IsNew && CustomPropertiesForNewFields.ContainsKey(GetCacheKey(propertyName)))
106             {
107                 string s = CustomPropertiesForNewFields[GetCacheKey(propertyName)];
108                 CustomPropertiesForNewFields.Remove(GetCacheKey(propertyName));
109                 CustomProperties[propertyName] = s;
110                 return s;
111             }
112             else
113             {
114                 return CustomProperties[propertyName];
115             }
116         }
117
118         /// <summary>
119         /// Called when a field is created. Without this, update is not called and custom properties
120         /// are not saved.
121         /// </summary>
122         /// <param name="op"></param>
123         public override void OnAdded(SPAddFieldOptions op)
124         {
125             base.OnAdded(op);
126             Update();  
127         }
128
129         #endregion
130
131
132         public override BaseFieldControl FieldRenderingControl
133         {
134             get
135             {
136                 BaseFieldControl fieldControl = new ItemVotingControl(this);
137                 fieldControl.FieldName = InternalName;
138                 if(String.IsNullOrEmpty(fieldControl.ItemFieldValue as string))
139                 {
140                     fieldControl.ItemFieldValue = "<Root><Item><CurrentFieldName Type=\"String\">[" + fieldControl.FieldName + "]</CurrentFieldName><Account Type=\"String\">ads\\mossadmin</Account></Item></Root>";
141                 }
142                 return fieldControl;
143             }
144         }
145
146         public override void Update()
147         {
148             SaveProperties();
149             base.Update();
150         }
151
152         public string FieldNameProperty
153         {
154             get { return this.GetCustomProperty("HiddenFieldName") + ""; }
155             set { this.SetCustomProperty("HiddenFieldName", value); }
156         }
157
158
159
160     }  
  为了能够在view页面得到当前字段的internal name(需要提供给投票处理页面voting.aspx),我们为字段赋的初始值中包含了当前field的internal name( fieldControl.ItemFieldValue = "<Root><Item><CurrentFieldName Type=\"String\">[" + fieldControl.FieldName + "]</CurrentFieldName><Account Type=\"String\">ads\\mossadmin</Account></Item></Root>";),为了在页面中,能够使得我们开发的2个自定义字段发生联系,我们在自定义字段的xml文件中为这个字段中添加了一个field property-- HiddenFieldName
  接下来是呈现类代码:
  

代码

public class ItemVotingControl : BaseFieldControl
    {
        private ItemVoting field;
        private List<Voter> voterList;
        private LiteralControl ltcNumber;
        private bool isVoted = false;
        public ItemVotingControl(ItemVoting parentField)
        {
            this.field = parentField;
        }
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (this.ListItemFieldValue != null)
            {
                this.voterList = SerializeUtility.Deserialize(this.ListItemFieldValue.ToString());
            }
            else
            {
                this.voterList = new List<Voter>();
            }
        }
        protected override void CreateChildControls()
        {
            ltcNumber = new LiteralControl();
            this.Controls.Add(ltcNumber);
        }
        public override void UpdateFieldValueInItem()
        {
           
        }

        protected override void RenderFieldForDisplay(HtmlTextWriter output)
        {
            int countValue = voterList.Count > 0 ? voterList.Count - 1 : voterList.Count;
            output.Write(countValue.ToString());
        }
        protected override void Render(HtmlTextWriter output)
        {
            RenderFieldForDisplay(output);
        }
    }  呈现控件取出了序列化后的投票结果,并反序列化,然后显示. 注意这里的显示只是指在New.aspx,edit.aspx,display.aspx这三个页面的显示,当然用户要求直接在view的页面上投票,所以我们要提供字段在view页面的现示实现。于是我们修改了field_字段.xml文件中的<RenderPattern Name="DisplayPattern">节。
  下面是完整的field_字段.xml 文件:
  

代码

1 <?xml version="1.0" encoding="utf-8" ?>
2 <FieldTypes>
3   <FieldType>
4     <Field Name="TypeName">ItemVoting</Field>
5     <Field Name="ParentType">Note</Field>
6     <Field Name="TypeDisplayName">Item Voting</Field>
7     <Field Name="TypeShortDescription">Item Voting</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">AECSharePoint.Field.Voting.ItemVoting, AECSharePoint.Field.Voting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c8afc6fd77dac842</Field>
13     <PropertySchema>
14       <Fields>
15         <Field Hidden="FALSE" Name="HiddenFieldName"
16         DisplayName="My Custom Property"
17         Type="Text">
18         </Field>
19       </Fields>
20       <Fields></Fields>
21     </PropertySchema>
22     <RenderPattern Name="DisplayPattern">
23       <HTML>
24         <![CDATA[
25         <a id='linkVoting' href="javascript:window.location= SetLocation(']]></HTML>
26       <ListProperty Select="Name"/>
27       <HTML>
28         <![CDATA[',']]>
29       </HTML>
30       <ListProperty Select="Title"/>
31       <HTML>
32         <![CDATA[',']]>
33       </HTML>
34       <Column Name="ID"/>
35       <HTML>
36         <![CDATA[',']]>
37       </HTML>
38         <ListProperty Select="DefaultViewUrl"/>
39       <HTML>
40         <![CDATA[',']]>
41       </HTML>
42       <Column HTMLEncode="TRUE"/>
43       <HTML>
44         <![CDATA[');"><img onerror="SetLinkDisplayContent(']]>
45       </HTML>
46       <Column HTMLEncode="TRUE"/>
47       <HTML>
48         <![CDATA[',this);" border=0 src="#"><div align="center" id="divCount" style="clear:left;display:inline;"></div></a>]]>
49       </HTML>
50       <HTML>
51         <![CDATA[
52         <script>
53         function SetLocation(listName,listTitle, itemID, listViewUrl, fieldValue)
54         {
55             var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
56             xmlDoc.loadXML(fieldValue);
57             var fieldNameNode = xmlDoc.documentElement.selectSingleNode("//Item/CurrentFieldName");
58             var fieldName = fieldNameNode.text;
59             var start = fieldName.indexOf("[");
60             var end = fieldName.indexOf("]");
61            
62             fieldName = fieldName.substring(start+1, end);
63  
64             var queryStr = "?listName=" + listName + "&amp;itemID=" + itemID + "&amp;fieldName=" + fieldName + "&amp;Source=" + window.location;
65             var currentSiteURL = "http://" + document.location.host;
66
67             var endIndex = listViewUrl.indexOf("/Lists/");
68             if(endIndex == -1)
69             {
70                 endIndex = listViewUrl.indexOf("/" + listTitle + "/")
71             }
72             var subUrl = listViewUrl.substring(0,endIndex);
73             subUrl += "/_layouts/AECSharePoint/Voting.aspx";
74             currentSiteURL += subUrl + queryStr;
75             return currentSiteURL;   
76         }
77         
78         function SetLinkDisplayContent(fieldValue,o)
79         {
80
81             o.src = "/_layouts/AECSharePoint/voting.gif";
82         }
83
84         </script>
85         ]]>
86       </HTML>
87     </RenderPattern>
88   </FieldType>
89 </FieldTypes>
90
91   
  在 <RenderPattern Name="DisplayPattern"> 中我们使得字段在view页面显示为一个图标,点击图标后跳转到我们开发的一个application page,同时为这个page传输必要的listid,itemid等信息,此页面处理此次投票,保存投票结果作为字段的值。
  下面是我们放在Template/Layout/下的自定义application page,也就是上面xml中提到的voting.aspx 代码:
  

代码

<%@ Assembly Name="Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@ Page Language="C#" Inherits="Microsoft.SharePoint.WebControls.LayoutsPageBase" MasterPageFile="~/_layouts/application.master"%>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.WebControls" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
    public Dictionary<string, object> initialParam = null;
    private List<Voter> voterList;
    private bool isVoted = false;
    class Voter
    {
        private string _currentFieldName;
        private string _account;
        public string CurrentFieldName
        {
            get
            {
                return this._currentFieldName;
            }
            set
            {
                this._currentFieldName = value;
            }
        }
        public string Account
        {
            get
            {
                return this._account;
            }
            set
            {
                this._account = value;
            }
        }
    }
   
    #region //Serialize&deserialize the voting result
    class SerializeUtility
    {
        public static string Serialize(List<Voter> GenericList)
        {
            XmlDocument result = new XmlDocument();
            result.LoadXml("<Root></Root>");
            foreach (Voter obj in GenericList)
            {
                XmlElement Item = result.CreateElement("Item");
                PropertyInfo[] properties = obj.GetType().GetProperties();
                foreach (PropertyInfo property in properties)
                {
                    if (property.GetValue(obj, null) != null)
                    {
                        XmlElement element = result.CreateElement(property.Name);
                        element.SetAttribute("Type", property.PropertyType.Name);
                        element.InnerText = property.GetValue(obj, null).ToString();
                        Item.AppendChild(element);
                    }
                }
                result.DocumentElement.AppendChild(Item);
            }
            return result.InnerXml;
        }
        public static List<Voter> Deserialize(string XmlStr)
        {
            List<Voter> result = new List<Voter>();
            XmlDocument XmlDoc = new XmlDocument();
            XmlDoc.LoadXml(XmlStr);
            foreach (XmlNode ItemNode in XmlDoc.GetElementsByTagName("Root").Item(0).ChildNodes)
            {
                Voter item = Activator.CreateInstance<Voter>();
                PropertyInfo[] properties = typeof(Voter).GetProperties();
                foreach (XmlNode propertyNode in ItemNode.ChildNodes)
                {
                    string name = propertyNode.Name;
                    string type = propertyNode.Attributes["Type"].Value;
                    string value = propertyNode.InnerXml;
                    foreach (PropertyInfo property in properties)
                    {
                        if (name == property.Name)
                        {
                            property.SetValue(item, Convert.ChangeType(value, property.PropertyType), null);
                        }
                    }
                }
                result.Add(item);
            }
            return result;
        }
    }
    #endregion
   
    class VotingBiz
    {
        internal Voter GetCurrentVoter(string fieldName, string account)
        {
            Voter currentVoter = new Voter();
            currentVoter.Account = account;
            currentVoter.CurrentFieldName = string.Empty;
            return currentVoter;
        }
        internal void UpdateListFieldValueWithElevatedPrivileges(Guid listID, int itemID, Dictionary<string, object> dicFieldValue)
        {
            if (SPContext.Current == null)
                return;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
                    {
                        web.AllowUnsafeUpdates = true;
                        SPList list = web.Lists[listID];
                        SPListItem item = list.GetItemById(itemID);
                        if (item == null)
                        {
                            return;
                        }
                        else
                        {
                            foreach(KeyValuePair<string, object> singleItem in dicFieldValue)
                            {
                                item[singleItem.Key] = singleItem.Value;
                            }
                            item.SystemUpdate(false);
                        }
                    }
                }
            });
        }
        internal bool CheckIsItemVoted(object itemValue, string fieldName, string account)
        {
            VotingBiz voteMgnt = new VotingBiz();
            List<Voter> voterList = null;
            Voter currentVoter = voteMgnt.GetCurrentVoter(fieldName, account);
            if (itemValue == null)
            {
                return false;
            }
            else
            {
                voterList = SerializeUtility.Deserialize(itemValue.ToString());
                //if (itemValue.ToString().IndexOf(currentVoter.Account) != -1)
                //{
                //    return true;
                //}
                //else
                //{
                //    return false;
                //}
                if (!voterList.Exists(delegate(Voter v) { return v.Account == currentVoter.Account; }))
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            //if (!voterList.Exists(delegate(Voter v) { return v.Account == currentVoter.Account; }))
            //{
            //    return false;
            //}
            //else
            //{
            //    return true;
            //}
        }
    }
    protected override void OnLoad(EventArgs e)
    {
        InitialParamter();
    }
    protected void InitialParamter()
    {
        try
        {
            initialParam = new Dictionary<string, object>();
            initialParam.Add("listName", Request.QueryString["listName"].ToString());
            initialParam["itemID"] = Request.QueryString["itemID"].ToString();
            initialParam["fieldName"] = Request.QueryString["fieldName"].ToString();
            initialParam["fieldValue"] = GetItemValue(initialParam["fieldName"] as string, initialParam["listName"] as string, Int32.Parse(initialParam["itemID"] as string));
        }
        catch (Exception ex)
        {
            EventLog.WriteEntry("Voting Field", SPContext.Current.Web.Title + ":" + ex.Message + "--" + ex.StackTrace);
            Response.Write("Error happend, please contact site admin");
        }
    }
   
    protected object GetItemValue(string fieldName, string listName, int itemId)
    {
        using (SPSite site = new SPSite(SPContext.Current.Site.ID))
        {
            using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
            {
                Guid listId = new Guid(listName);
                SPList list = web.Lists[listId];
                SPListItem item = list.GetItemById(itemId);
                return item[fieldName];
            }
        }
    }
    private string GetVotingResultFieldName(Guid listId)
    {
        if (SPContext.Current == null)
            return null;
        string votingFieldName = String.Empty;
        using (SPSite site = new SPSite(SPContext.Current.Site.ID))
        {
            using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
            {
                SPList list = web.Lists[listId];
                foreach (SPField field in list.Fields)
                {
                    if (null != field.GetCustomProperty("FlagFieldNameProperty"))
                    {
                        votingFieldName = field.InternalName;
                        break;
                    }
                }
            }
        }
        return votingFieldName;
    }
   
   
   
    protected void btnVote_Click(object sender, EventArgs e)
    {
        VotingBiz voteMgnt = new VotingBiz();
        if (null != initialParam)
        {
            if (!voteMgnt.CheckIsItemVoted(initialParam["fieldValue"], initialParam["fieldName"] as string, SPContext.Current.Web.CurrentUser.ID.ToString()))
            {
                Voter currentVoter = voteMgnt.GetCurrentVoter(initialParam["fieldName"] as string, SPContext.Current.Web.CurrentUser.ID.ToString());
                if (initialParam["fieldValue"] != null)
                {
                    this.voterList = SerializeUtility.Deserialize(initialParam["fieldValue"] as string);
                }
                voterList.Add(currentVoter);
                Guid listId = new Guid(initialParam["listName"] as string);
                int itemId = Int32.Parse(initialParam["itemID"] as string);
                string fieldName = initialParam["fieldName"] as string;
                string votingResultFieldName = GetVotingResultFieldName(listId);
                Dictionary<string, object> fieldNameValuePairs = new Dictionary<string, object>();
                fieldNameValuePairs[fieldName] = SerializeUtility.Serialize(voterList);
                if (!String.IsNullOrEmpty(votingResultFieldName))
                {
                    fieldNameValuePairs[votingResultFieldName] = voterList.Count - 1;
                }
                voteMgnt.UpdateListFieldValueWithElevatedPrivileges(listId, itemId, fieldNameValuePairs);
                this.isVoted = true;
            }
        }
        ReturnToSourcePage();
    }
    private void ReturnToSourcePage()
    {
        string sourceUrl = Request.QueryString["Source"].ToString();
        Response.Redirect(sourceUrl);
    }
   
    protected void btnBack_Click(object sender, EventArgs e)
    {
        ReturnToSourcePage();
    }
</script>
<asp:Content ID="Content1" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
    <h>
        Vote Here
    </h>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="PlaceHolderMain" runat="server">
    <div>
        Are you sure to vote this item? <br />
    <b>Please note that your vote would be counted only once even if you vote again!</b>
    <br/>
    <br/>
        <asp:Button ID="btnVote" runat="server" Text="Vote" OnClick="btnVote_Click" class="ms-ButtonHeightWidth" Width="80px" />
        <asp:Button ID="btnBack" runat="server" Text="Cancel" OnClick="btnBack_Click" class="ms-ButtonHeightWidth" Width="80px" />
    </div>
</asp:Content>  
  
  下面介绍统计投票的字段voting result field
  1.字段类代码
  

代码

  1  public class ItemVotingResult : SPFieldText
  2     {
  3         private static string[] CustomPropertyNames = new string[] { "MyCustomProperty" };
  4
  5         public ItemVotingResult(SPFieldCollection fields, string fieldName)
  6             : base(fields, fieldName)
  7         {
  8             InitProperties();
  9         }
10
11         public ItemVotingResult(SPFieldCollection fields, string typeName, string displayName)
12             : base(fields, typeName, displayName)
13         {
14             InitProperties();
15         }
16
17         #region Property storage and bug workarounds - do not edit
18
19         /// <summary>
20         /// Indicates that the field is being created rather than edited. This is necessary to
21         /// work around some bugs in field creation.
22         /// </summary>
23         public bool IsNew
24         {
25             get { return _IsNew; }
26             set { _IsNew = value; }
27         }
28         private bool _IsNew = false;
29
30         /// <summary>
31         /// Backing fields for custom properties. Using a dictionary to make it easier to abstract
32         /// details of working around SharePoint bugs.
33         /// </summary>
34         private Dictionary<string, string> CustomProperties = new Dictionary<string, string>();
35
36         /// <summary>
37         /// Static store to transfer custom properties between instances. This is needed to allow
38         /// correct saving of custom properties when a field is created - the custom property
39         /// implementation is not used by any out of box SharePoint features so is really buggy.
40         /// </summary>
41         private static Dictionary<string, string> CustomPropertiesForNewFields = new Dictionary<string, string>();
42
43         /// <summary>
44         /// Initialise backing fields from base property store
45         /// </summary>
46         private void InitProperties()
47         {
48             foreach (string propertyName in CustomPropertyNames)
49             {
50                 CustomProperties[propertyName] = base.GetCustomProperty(propertyName) + "";
51             }
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
66         /// <summary>
67         /// Get an identifier for the field being added/edited that will be unique even if
68         /// another user is editing a property of the same name.
69         /// </summary>
70         /// <param name="propertyName"></param>
71         /// <returns></returns>
72         private string GetCacheKey(string propertyName)
73         {
74             return SPContext.Current.GetHashCode() + "_" + (ParentList == null ? "SITE" : ParentList.ID.ToString()) + "_" + propertyName;
75         }
76
77         /// <summary>
78         /// Replace the buggy base implementation of SetCustomProperty
79         /// </summary>
80         /// <param name="propertyName"></param>
81         /// <param name="propertyValue"></param>
82         new public void SetCustomProperty(string propertyName, object propertyValue)
83         {
84             if (IsNew)
85             {
86                 // field is being added - need to put property in cache
87                 CustomPropertiesForNewFields[GetCacheKey(propertyName)] = propertyValue + "";
88             }
89
90             CustomProperties[propertyName] = propertyValue + "";
91         }
92
93         /// <summary>
94         /// Replace the buggy base implementation of GetCustomProperty
95         /// </summary>
96         /// <param name="propertyName"></param>
97         /// <param name="propertyValue"></param>
98         new public object GetCustomProperty(string propertyName)
99         {
100             if (!IsNew && CustomPropertiesForNewFields.ContainsKey(GetCacheKey(propertyName)))
101             {
102                 string s = CustomPropertiesForNewFields[GetCacheKey(propertyName)];
103                 CustomPropertiesForNewFields.Remove(GetCacheKey(propertyName));
104                 CustomProperties[propertyName] = s;
105                 return s;
106             }
107             else
108             {
109                 return CustomProperties[propertyName];
110             }
111         }
112
113         /// <summary>
114         /// Called when a field is created. Without this, update is not called and custom properties
115         /// are not saved.
116         /// </summary>
117         /// <param name="op"></param>
118         public override void OnAdded(SPAddFieldOptions op)
119         {
120             base.OnAdded(op);
121             Update();
122         }
123
124         #endregion
125
126
127         public override BaseFieldControl FieldRenderingControl
128         {
129             get
130             {
131                 BaseFieldControl fieldControl = new ItemVotingResultControl(this);
132
133                 fieldControl.FieldName = InternalName;
134
135                 return fieldControl;
136             }
137         }
138
139         public override void Update()
140         {
141             SaveProperties();
142             base.Update();
143         }
144
145         public string MyCustomProperty
146         {
147             get { return this.GetCustomProperty("FlagFieldNameProperty") + ""; }
148             set { this.SetCustomProperty("FlagFieldNameProperty", value); }
149         }
150
151     }  
  为了能够在投票处理页面voting.aspx中找到此字段,并将结果保存到此字段,我们加了field property--FlagFieldNameProperty
  2 字段显示类
  

代码

public class ItemVotingResultControl : BaseFieldControl
    {
        private ItemVotingResult field;
        private LiteralControl lcResult = null;
        public ItemVotingResultControl(ItemVotingResult parentField)
        {
            this.field = parentField;
        }
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
        }
      
      
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            lcResult = new LiteralControl();
            object currentResult = GetItemVotingResult();
            if (null != currentResult)
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(currentResult.ToString());
                lcResult.Text = (xmlDoc.DocumentElement.ChildNodes.Count - 1) + "";
            }
            else
            {
                lcResult.Text = "0";
            }
        }
        public override void UpdateFieldValueInItem()
        {
            
        }
        protected override void Render(HtmlTextWriter output)
        {
            lcResult.RenderControl(output);
        }
    }  
  3 field_VotingResult.xml
  

代码

<?xml version="1.0" encoding="utf-8" ?>
<FieldTypes>
  <FieldType>
    <Field Name="TypeName">ItemVotingResult</Field>
    <Field Name="ParentType">Text</Field>
    <Field Name="TypeDisplayName">Item Voting Result</Field>
    <Field Name="TypeShortDescription">Item Voting Result</Field>
    <Field Name="UserCreatable">TRUE</Field>
    <Field Name="Sortable">TRUE</Field>
    <Field Name="AllowBaseTypeRendering">TRUE</Field>
    <Field Name="Filterable">TRUE</Field>
    <Field Name="FieldTypeClass">AECSharePoint.Field.VotingResult.ItemVotingResult, AECSharePoint.Field.VotingResult, Version=1.0.0.0, Culture=neutral, PublicKeyToken=09a5c45e643a0621</Field>
    <PropertySchema>
      <Fields>
        <Field Hidden="FALSE" Name="FlagFieldNameProperty"
        DisplayName="My Custom Property"
        Type="Text">
        </Field>
      </Fields>
      <Fields></Fields>
    </PropertySchema>
    <RenderPattern Name="DisplayPattern">
      <Column />
    </RenderPattern>
  </FieldType>
</FieldTypes>  
  这个字段主要用来现示投票结果,比较简单。
  
  主要效果图:
  投票页面:
  
DSC0002.jpg
  
  点击vote后跳转到投票处理页面Voting.aspx
DSC0003.jpg
  
  点击OK完成投票。注意同一用户投票只记录一次,这两个custom field同时支持List和Document Library。
  代码和安装包如下:
  代码:/Files/tonnie/Code.rar
  安装包:/Files/tonnie/Deployfile.rar
  欢迎分享和指正!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-118338-1-1.html 上篇帖子: SharePoint开发从零开始 下篇帖子: SharePoint 自定义列表编辑页面,附件上传提示“此表单自定义为不处理附件”
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表