![]() |
| Рис. 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 полей класса и создание его экземпляра
///
/// Тип результата
///
Преобразуемый элемент
/// Возвращает объект класса с теми заполнеными полями, которые были в исходном 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;
}
}
}
Модель:
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"?
