Рис. 1. |
Доброго времени суток, дорогие коллеги и просто читатели. Как часто, работая с SharePoint 2010 вам приходится, слышать просьбы, о создании голосований с изображениями? Для тех кому ("хватит это терпеть" (c) Жириновский) надоело, представляю прототип решения для SharePoint 2010 в виде веб части, подключаемой к любой библиотеке документов с изображениями.
Данная веб часть, подключается к любой библиотеке документов, и выводит список изображений для голосования (см. Рис. 1). Результаты голосования записываются в автоматически создаваемое поле SPListItem-a. В представленной версии отсутвует AJAX кнопка, и механизм запоминания проголосовавшего (он сделан на основе coockies, в полной версии).
Отрисовка списка, выполнена по статье сайта artlebedev.ru - "Блоки картинок, с подписями выровненныe по центру".
Еще одним из интересных моментов, является способ получения данных из библиотеки документов, и приведения SPListItemCollection к списку строго типизированных объектов. Методика выполнена в виде Extension методов для SPListItemCollection (см. код ниже).
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using Microsoft.SharePoint; namespace ImageVotingWebPart { public static class SPListItemCollectionExtension { ///Модель:/// Преобразование элементов коллекции ///к /// Тип результирующей коллекции /// Исходная коллекция ///public static IEnumerable<T> Select<T>(this SPListItemCollection collection) where T : new() { return collection .Cast<SPListItem>() .Select(item => item.Cast<T>()); } /// /// Извлечение из SPListItem полей класса ///и создание его экземпляра /// Тип результата /// Преобразуемый элемент ///Возвращает объект класса public static T Cast<T>(this SPListItem item) where T : new() { var result = new T(); Type type = typeof(T); PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo property in properties) { try { object value = item[property.Name]; property.SetValue(result, value, null); } catch (Exception exc) { Debug.WriteLine(exc); } } return result; } } }с теми заполнеными полями, которые были в исходном SPListItem
namespace ImageVotingWebPart.ImageVotingWebPart { public class ImageVotingItem { public int ID { get; set; } public string EncodedAbsThumbnailUrl { get; set; } public string FileLeafRef { get; set; } public string FileRef { get; set; } public int Rating { get; set; } public string Title { get; set; } public string TitleOrName { get { return !string.IsNullOrEmpty(Title) ? Title : FileLeafRef; } } } }Код веб части:
using System.ComponentModel; using System.Web.UI; using System.Web.UI.WebControls.WebParts; namespace ImageVotingWebPart.ImageVotingWebPart { [ToolboxItemAttribute(false)] public class ImageVotingWebPart : WebPart { // Visual Studio might automatically update this path when you change the Visual Web Part project item. private const string _ascxPath = @"~/_CONTROLTEMPLATES/ImageVotingWebPart/ImageVotingWebPart/ImageVotingWebPartUserControl.ascx"; protected override void CreateChildControls() { Control control = Page.LoadControl(_ascxPath); Controls.Add(control); } [Personalizable] [WebBrowsable] [WebDisplayName("Адрес библиотеки")] public string LibraryUrl { get; set; } } }Код контрола ImageVotingWebPartUserControl:
using System; using System.Linq; using System.Linq.Expressions; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using ImageVotingWebPart.Properties; using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; namespace ImageVotingWebPart.ImageVotingWebPart { public partial class ImageVotingWebPartUserControl : UserControl { #region Constants private const string c_ratingFieldName = "Rating"; protected const string c_voteCommandName = "Vote"; #endregion protected ImageVotingWebPart WebPart { get { return (ImageVotingWebPart)Parent; } } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); if (string.IsNullOrEmpty((WebPart.LibraryUrl ?? string.Empty).Trim())) { return; } bindImageList(); } protected void OnImageListItemCommand(object sender, RepeaterCommandEventArgs e) { if (e.CommandName != c_voteCommandName) { return; } int id; if (!int.TryParse((string)e.CommandArgument, out id)) { return; } if (SPUtility.ValidateFormDigest()) { SPSecurity.RunWithElevatedPrivileges(() => increaseImageRating(id)); } } private void increaseImageRating(int id) { try { using (SPSite site = new SPSite(WebPart.LibraryUrl)) { string webRelativeUrl = WebPart.LibraryUrl.Replace(site.Url, String.Empty); using (SPWeb web = site.OpenWeb(webRelativeUrl)) { SPList list = web.GetList(WebPart.LibraryUrl); if (!list.Fields.ContainsField(c_ratingFieldName)) { list.Fields.Add(c_ratingFieldName, SPFieldType.Integer, true); } else { SPField field = list.Fields.GetField(c_ratingFieldName); if (field.Type != SPFieldType.Integer) { throw new ApplicationException(ImageVotingResources.RatingFieldWrongTypeError); } } SPItem item = list.GetItemById(id); int rating = (int)(item[c_ratingFieldName] ?? 0); item[c_ratingFieldName] = rating + 1; item.Update(); } } } catch (Exception e) { setError(e.Message); } } private void bindImageList() { string[] usingFields = new[] { "ID", "EncodedAbsThumbnailUrl", "FileRef", "FileLeafRef", c_ratingFieldName, "Title", }; try { using (SPSite site = new SPSite(WebPart.LibraryUrl)) { string webRelativeUrl = WebPart.LibraryUrl.Replace(site.Url, String.Empty); using (SPWeb web = site.OpenWeb(webRelativeUrl)) { SPList list = web.GetList(WebPart.LibraryUrl); SPQuery query = new SPQuery(); query.ViewFields = string.Join("", usingFields.Select(name => string.Format("<FieldRef Name='{0}' />", name)).ToArray()); query.ViewAttributes = "Scope='Recursive'"; ImageList.DataSource = list.GetItems(query).Select<ImageVotingItem>(); ImageList.DataBind(); } } } catch (Exception exc) { setError(string.Format(ImageVotingResources.LoadImagesError, exc.Message)); } } private void setError(string error) { ErrorLabel.Text = error; } } }Разметка контрола ImageVotingWebPartUserControl.ascx:
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %> <%@ Register TagPrefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %> <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ImageVotingWebPartUserControl.ascx.cs" Inherits="ImageVotingWebPart.ImageVotingWebPart.ImageVotingWebPartUserControl" %> <%@ Import Namespace="ImageVotingWebPart.Properties" %> <style type="text/css"> .thumbnail { /* Убираем подчеркивание у элемента ins, который был использован для совместимости со старыми версиями Internet Explorer */ text-decoration: none; /* Следующее правило для Firefox 2 */ display: -moz-inline-box; /* а это для остальных */ display: inline-block; vertical-align: top; /* Отступы между блоками */ margin: 2em 0 0 5px; } .thumbnail .r { background-color: #D6E4FE; height: 164px; width: 164px; text-align: center; /*layout magic*/ display: table; /*# - is hack for ie7*/ #position: relative; overflow: hidden; } .centered { /*# - is hack for ie7*/ #position: absolute; #top: 50%; #left: 50%; display: table-cell; vertical-align: middle; } </style> <asp:Label ID="ErrorLabel" runat="server" ForeColor="Red" /><br /> <asp:Repeater ID="ImageList" runat="server" OnItemCommand="OnImageListItemCommand"> <ItemTemplate> <ins class="thumbnail"> <div class="r"> <div class="centered"> <div style=" #position: relative; #top: -50%; #left: -50%;"> <a href='<%# Eval("FileRef") %>' target="_blank" title='<%# Eval("TitleOrName") %>'> <img alt='' src='<%# Eval("EncodedAbsThumbnailUrl") %>' style="border-style: none;" title='<%# Eval("TitleOrName") %>' /> </a> </div> </div> </div> <br /> <table width="164px"> <col width="80%" /> <col /> <tr> <td style="text-align: center"> <asp:Literal ID="Literal2" runat="server" Text='<%# Eval("TitleOrName") %>' /> </td> </tr> <tr> <td style="text-align: center"> <asp:Literal ID="Literal3" runat="server" Text='<%# ImageVotingResources.RatingLabelText %>' />: <asp:Literal ID="Literal4" runat="server" Text='<%# Eval("Rating") %>' /> <asp:ImageButton ID="ImageButton1" runat="server" CommandName='<%# c_voteCommandName %>' CommandArgument='<%# Eval("ID") %>' ImageUrl="~/_layouts/images/ImageVotingWebPart/vote.png" Width="20" Height="20" Style="vertical-align: middle;" Title='<%# ImageVotingResources.VoteButtonText %>' /> </td> </tr> </table> </ins> </ItemTemplate> </asp:Repeater>
Пост написан, в ответ на многочисленные просьбы пользователей форума www.gotdotnet.ru, на тему - "КАК МНЕ СДЕЛАТЬ ГОЛОСОВАНИЕ ДЛЯ КАРТИНОК В SHAREPOINT"?
Стандартный механизм голосования чем не устроил?
ReplyDelete"Не красиво" (c) Отдел пиара.
ReplyDeleteА можно поподробнее, как подключить данный код?
ReplyDeleteПривет. Просто создаешь проект SharePoint в нем создаешь WebPart вставляешь туда код. Собираешь проект деплоишь wsp и все работает. Потом на сайте подключаешь webpart.
ReplyDelete