Страницы

Tuesday, May 22, 2012

Sharepoint 2010 - Пишем свой Custom lookup picker field with search

Всем привет. Сегодня я расскажу о том, как cделать свой собственный "custom lookup picker field with search". Основная цель данной публикации, показать методику создания Custom Field's в SharePoint 2010. Итак приступим:

Часть 1: Реализация

- Создаем проект SharePoint 2010.

- Добавляем SharePoint mapped folder - "XML".

- В папку "XML" добавляем файл - "fldtypes_LookupFieldWithSearch.xml".

<?xml version="1.0" encoding="utf-8" ?>
<FieldTypes>
    <FieldType>
        <Field Name="Sortable">TRUE</Field>
        <Field Name="Filterable">TRUE</Field>
        <Field Name="ParentType">Lookup</Field>
        <Field Name="UserCreatable">TRUE</Field>
        <Field Name="InternalType">Lookup</Field>
        <Field Name="TypeName">LookupFieldWithSearch</Field>
        <Field Name="TypeDisplayName">Lookup field with search</Field>
        <Field Name="TypeShortDescription">Lookup field with search</Field>
        <Field Name="FieldTypeClass">MyProject.CustomFields.LookupFieldWithSearch.LookupFieldWithSearch, $SharePoint.Project.AssemblyFullName$</Field>
    </FieldType>
</FieldTypes>
Листинг 1 - fldtypes_LookupFieldWithSearch.xml.

- Определим класс LookupFieldWithSearch

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace MyProject.CustomFields.LookupFieldWithSearch
{
   public class LookupFieldWithSearch : SPFieldLookup
   {
       public LookupFieldWithSearch(SPFieldCollection fields, string fieldName)
        : base(fields, fieldName) { }

       public LookupFieldWithSearch(SPFieldCollection fields, string typeName, string displayName)
        : base(fields, typeName, displayName) { }

       public override BaseFieldControl FieldRenderingControl
       {
          get
          {
              BaseFieldControl fieldControl = new LookupFieldWithSearchControl();
              fieldControl.FieldName = InternalName;
              return fieldControl;
          }
       }
   }
}
Листинг 2 - LookupFieldWithSearch.cs.

- У класса LookupFieldWithSearch перегружаем метод FieldRenderingControl (см. листинг 1).

- Определим класс "LookupFieldWithSearchControl" (см. листинг 3).

using System;
using System.Web;
using System.Text;
using System.Linq;
using System.Collections;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;
using System.Text.RegularExpressions;
using Microsoft.SharePoint.WebControls;

namespace MyProject.CustomFields.LookupFieldWithSearch
{
    public class LookupFieldWithSearchControl : BaseFieldControl
    {
        #region Конструктор
        public LookupFieldWithSearchControl()
            : base()
        {
        }
        #endregion

        #region Свойства

        public SPList LookupList
        {
            get
            {
                var web = SPControl.GetContextWeb(base.Context);
                var field = Field as LookupFieldWithSearch;
                var m_lookupList = web.Lists.GetList(new Guid(field.LookupList), true);
                return m_lookupList;
            }
        }
        public override string DisplayTemplateName
        {
            get
            {
                if (ControlMode == SPControlMode.Edit || ControlMode == SPControlMode.New)
                {
                    return "LookupFieldWithSearchEditTemplate";
                }
                else
                {
                    return "LookupFieldWithSearchDisplayTemplate";
                }
            }
            set
            {
                base.DisplayTemplateName = value;
            }
        }
        protected override string DefaultTemplateName
        {
            get
            {
                return DisplayTemplateName;
            }
        }
        public override object Value
        {
            get
            {
                if (ControlMode == SPControlMode.New || ControlMode == SPControlMode.Edit)
                {
                    var field = (LookupFieldWithSearch)base.Field;
                    if (field == null) return null;

                    var m_displayValue = (TextBox)TemplateContainer.FindControl("m_displayValue");
                    var m_hiddenValue = (HiddenField)TemplateContainer.FindControl("m_hiddenValue");
                    var m_hiddenDisplayValue = (HiddenField)TemplateContainer.FindControl("m_hiddenDisplayValue");

                    if (string.IsNullOrEmpty(m_hiddenValue.Value) || m_hiddenValue.Value.Trim() == string.Empty)
                    {
                        return null;
                    }
                    else
                    {
                        return new SPFieldLookupValue(int.Parse(m_hiddenValue.Value), m_hiddenDisplayValue.Value);
                    }
                }
                else
                {
                    return null;
                }
            }
            set
            {
                if (ControlMode == SPControlMode.New || ControlMode == SPControlMode.Edit)
                {
                    var m_displayValue = (TextBox)TemplateContainer.FindControl("m_displayValue");
                    var m_hiddenValue = (HiddenField)TemplateContainer.FindControl("m_hiddenValue");
                    var m_hiddenDisplayValue = (HiddenField)TemplateContainer.FindControl("m_hiddenDisplayValue");

                    var _value = value as SPFieldLookupValue;

                    if (_value != null)
                    {
                        m_displayValue.Text = m_hiddenDisplayValue.Value = _value.LookupValue;
                        m_hiddenValue.Value = _value.LookupId.ToString();
                    }
                    else
                    {
                        m_displayValue.Text = string.Empty;
                        m_hiddenValue.Value = string.Empty;
                        m_hiddenDisplayValue.Value = string.Empty;
                    }
                }
            }
        }

        #endregion

        #region Методы

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if ((ControlMode == SPControlMode.Edit || ControlMode == SPControlMode.New) && Value == null)
            {
                var m_hiddenValue = TemplateContainer.FindControl("m_hiddenValue") as HiddenField;
                var m_displayValue = TemplateContainer.FindControl("m_displayValue") as TextBox;

                var m_hiddenDisplayValue = TemplateContainer.FindControl("m_hiddenDisplayValue") as HiddenField;

                m_displayValue.Text = string.Empty;
                m_hiddenValue.Value = string.Empty;
                m_hiddenDisplayValue.Value = string.Empty;
            }
        }
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            var field = (LookupFieldWithSearch)Field;
            if (field == null) return;

            if (ControlMode == SPControlMode.Display)
            {
                #region Display mode

                var item = field.ParentList.GetItemById(SPContext.Current.ItemId);

                if (item[field.Id] != null)
                {
                    var m_displayFieldValue = TemplateContainer.FindControl("m_displayFieldValue") as Literal;
                    var urlToListItem = LookupList.DefaultDisplayFormUrl;

                    m_displayFieldValue.Text = string.Format("<a href=\"{0}{1}{2}{3}&RootFolder=*\">{4}</a>",
                        SPContext.Current.Site.Url,
                        urlToListItem,
                        "?ID=",
                        (item[field.Id] as SPFieldLookupValue).LookupId,
                        (item[field.Id] as SPFieldLookupValue).LookupValue);
                }

                #endregion
            }

            if (ControlMode == SPControlMode.Edit || ControlMode == SPControlMode.New)
            {
                #region New/Edit mode

                var m_webUrl = TemplateContainer.FindControl("m_webUrl") as EncodedLiteral;
                var m_params = TemplateContainer.FindControl("m_params") as EncodedLiteral;
                var m_displayValue = TemplateContainer.FindControl("m_displayValue") as TextBox;
                var m_hiddenValue = TemplateContainer.FindControl("m_hiddenValue") as HiddenField;
                var m_hiddenDisplayValue = TemplateContainer.FindControl("m_hiddenDisplayValue") as HiddenField;

                var m_fieldPrefix1 = TemplateContainer.FindControl("m_fieldPrefix1") as EncodedLiteral;
                var m_fieldPrefix2 = TemplateContainer.FindControl("m_fieldPrefix2") as EncodedLiteral;
                var m_fieldPrefix3 = TemplateContainer.FindControl("m_fieldPrefix3") as EncodedLiteral;
                var m_fieldPrefix4 = TemplateContainer.FindControl("m_fieldPrefix4") as EncodedLiteral;
                var m_fieldPrefix5 = TemplateContainer.FindControl("m_fieldPrefix5") as EncodedLiteral;
                var m_fieldPrefix6 = TemplateContainer.FindControl("m_fieldPrefix6") as EncodedLiteral;
                var m_fieldPrefix7 = TemplateContainer.FindControl("m_fieldPrefix7") as EncodedLiteral;
                var m_fieldPrefix8 = TemplateContainer.FindControl("m_fieldPrefix8") as EncodedLiteral;
                var m_fieldPrefix9 = TemplateContainer.FindControl("m_fieldPrefix9") as EncodedLiteral;
                var m_fieldPrefix10 = TemplateContainer.FindControl("m_fieldPrefix10") as EncodedLiteral;
                var m_fieldPrefix11 = TemplateContainer.FindControl("m_fieldPrefix11") as EncodedLiteral;
                var m_fieldPrefix12 = TemplateContainer.FindControl("m_fieldPrefix12") as EncodedLiteral;
                var m_fieldPrefix13 = TemplateContainer.FindControl("m_fieldPrefix13") as EncodedLiteral;
                var m_fieldPrefix14 = TemplateContainer.FindControl("m_fieldPrefix14") as EncodedLiteral;
                var m_fieldPrefix15 = TemplateContainer.FindControl("m_fieldPrefix15") as EncodedLiteral;
                var m_fieldPrefix16 = TemplateContainer.FindControl("m_fieldPrefix16") as EncodedLiteral;
                var m_fieldPrefix17 = TemplateContainer.FindControl("m_fieldPrefix17") as EncodedLiteral;


                m_fieldPrefix1.Text = m_fieldPrefix2.Text = m_fieldPrefix3.Text = m_fieldPrefix4.Text = m_fieldPrefix5.Text = m_fieldPrefix6.Text
                    = m_fieldPrefix7.Text = m_fieldPrefix8.Text = m_fieldPrefix9.Text = m_fieldPrefix10.Text = m_fieldPrefix11.Text = m_fieldPrefix12.Text
                        = m_fieldPrefix13.Text = m_fieldPrefix14.Text = m_fieldPrefix15.Text = m_fieldPrefix16.Text = m_fieldPrefix17.Text = field.StaticName;

                var m_hiddenValueClientID = TemplateContainer.FindControl("m_hiddenValueClientID") as EncodedLiteral;
                var m_displayValueClientID = TemplateContainer.FindControl("m_displayValueClientID") as EncodedLiteral;
                var m_hiddenDisplayValueClientID = TemplateContainer.FindControl("m_hiddenDisplayValueClientID") as EncodedLiteral;

                m_webUrl.Text = SPContext.Current.Web.Url;
                m_hiddenValueClientID.Text = m_hiddenValue.ClientID;
                m_displayValueClientID.Text = m_displayValue.ClientID;
                m_hiddenDisplayValueClientID.Text = m_hiddenDisplayValue.ClientID;

                m_params.Text = "?listId=" + field.LookupList;

                #endregion
            }
        }
        public override void Validate()
        {
            base.Validate();
            try
            {
                if ((this.ControlMode == SPControlMode.New || this.ControlMode == SPControlMode.Edit) && this.Field.Required && this.Value == null)
                {
                    this.IsValid = false;
                    throw new Exception("Необходимо задать значение для этого обязательного поля.");
                }
            }
            catch (Exception ex)

            {
                this.ErrorMessage = ex.Message;
            }
        }

        #endregion
    }
}
Листинг 3 - LookupFieldWithSearchControl.cs.

- Перегрузим свойства DisplayTemplateName и DefaultTemplateName, отвечающих за выбор шаблона во время редактирования/создания/отображения значений поля.

- Добавляем в проект SharePoint mapped folder - "CONTROLTEMPLATES".

- В папке "CONTROLTEMPLATES" - создаем файл "LookupFieldWithSearchTemplate.ascx" (см. листинг 4).

<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="pa" Namespace="MyProject.CustomFields.LookupFieldWithSearch" Assembly="$SharePoint.Project.AssemblyFullName$" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" %>
<SharePoint:RenderingTemplate ID="LookupFieldWithSearchDisplayTemplate" runat="server">
    <Template>
        <asp:Literal Mode="PassThrough" runat="server" ID="m_displayFieldValue" />
    </Template>
</SharePoint:RenderingTemplate>
<SharePoint:RenderingTemplate ID="LookupFieldWithSearchEditTemplate" runat="server">
    <Template>
        <script language="javascript" type="text/javascript">

            var <SharePoint:EncodedLiteral ID='m_fieldPrefix10' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />webUrl = "<SharePoint:EncodedLiteral ID='m_webUrl' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />"
                         + "/_layouts/MyProject/LookupFieldWithSearch/SelectItem.aspx"
                         + "<SharePoint:EncodedLiteral ID='m_params' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />";
            var <SharePoint:EncodedLiteral ID='m_fieldPrefix1' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />displayValueClientID = "<SharePoint:EncodedLiteral ID='m_displayValueClientID' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />";
            var <SharePoint:EncodedLiteral ID='m_fieldPrefix2' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />hiddenValueClientID = "<SharePoint:EncodedLiteral ID='m_hiddenValueClientID' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />";
            var <SharePoint:EncodedLiteral ID='m_fieldPrefix15' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />hiddenDisplayValueClientID = "<SharePoint:EncodedLiteral ID='m_hiddenDisplayValueClientID' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />";

            function <SharePoint:EncodedLiteral ID='m_fieldPrefix9' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />openPickerDialog() {
                var options = {
                    title: 'Выбор',
                    width: 600,
                    height: 435,
                    url: <SharePoint:EncodedLiteral ID='m_fieldPrefix13' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />webUrl,
                    dialogReturnValueCallback: Function.createDelegate(null, <SharePoint:EncodedLiteral ID='m_fieldPrefix14' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />pickerDialogClosedCallback)
                };
                SP.UI.ModalDialog.showModalDialog(options);
            }

            function <SharePoint:EncodedLiteral ID='m_fieldPrefix8' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />pickerDialogClosedCallback(result, value) {
                if (result == 1) {
                    document.getElementById(<SharePoint:EncodedLiteral ID='m_fieldPrefix3' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />hiddenValueClientID).value = value.hiddenValue;
                    document.getElementById(<SharePoint:EncodedLiteral ID='m_fieldPrefix4' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />displayValueClientID).value = value.displayValue;
                    document.getElementById(<SharePoint:EncodedLiteral ID='m_fieldPrefix17' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />hiddenDisplayValueClientID).value = value.displayValue;
                }
            }

            function <SharePoint:EncodedLiteral ID='m_fieldPrefix7' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />clearPicker() {
                document.getElementById(<SharePoint:EncodedLiteral ID='m_fieldPrefix5' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />hiddenValueClientID).value = "";
                document.getElementById(<SharePoint:EncodedLiteral ID='m_fieldPrefix6' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />displayValueClientID).value = "";
                document.getElementById(<SharePoint:EncodedLiteral ID='m_fieldPrefix16' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />hiddenDisplayValueClientID).value = "";
            }
        </script>

        <table cellpadding="0" cellspacing="0" style="border-style: none; border-collapse: collapse; border-width: 0px; width: 100%;">
            <tr>
                <td align="left" valign="middle">
                    <asp:TextBox ID="m_displayValue" runat="server" Enabled="false" />
                    <asp:HiddenField ID="m_hiddenValue" runat="server" />
                    <asp:HiddenField ID="m_hiddenDisplayValue" runat="server" />
                    <img onclick="<SharePoint:EncodedLiteral ID='m_fieldPrefix11' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />openPickerDialog()" alt="Выбрать" src="_layouts/images/MyProject/funnel-pencil.png" style="border-width: 0px; border-style: none; cursor: pointer;" />
                    <img onclick="<SharePoint:EncodedLiteral ID='m_fieldPrefix12' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />clearPicker()" alt="Очистить" src="_layouts/images/MyProject/cross.png" style="border-width: 0px; border-style: none; cursor: pointer;" />
                </td>
            </tr>
        </table>
    </Template>
</SharePoint:RenderingTemplate>
Листинг 4 - LookupFieldWithSearchTemplate.ascx.

- В файле шаблонов (см. листинг 4) определим две области:  "LookupFieldWithSearchDisplayTemplate" и "LookupFieldWithSearchEditTemplate".

- В "LookupFieldWithSearchDisplayTemplate" помещаем литерал с Mode="PassThrough" (Mode="PassThrough" нужно для того, чтобы литерал не экранировал html тэги) (см. листинг 4).

- В  "LookupFieldWithSearchEditTemplate" помещаем несколько элементов управления: TextBox, 2 HiddenField и 2 картинки кнопки (см. рис. 1).



Рисунок 1 - Вид LookupFieldWithSearch в режиме редактирования элемента списка.
Наверное вы уже заметили, что в блоке с JavaScript кодом перед каждой переменной стоят литералы, в которые приходят значение статического имени текущего поля - это нужно для того, чтобы javascript обвязки не путались между полями одного и того же типа, в Edit и New форме (избавляемся от дублирующихся переменных). В блоке JavaScript кода (см. листинг 4) есть переменная webUrl (Обязательно получайте значение webUrl с сервера, JS Client Object Model - приходит ссылка на родительский сайт).
- Добавляем SharePoint mapped folder "Images".

- В "Images" создаем папку "MyProject" и в нее помещаем все нужные картинки, которые будет использовать наше поле (фильтр, крест...).

- Добавляем SharePoint mapped folder "Layouts".

- В папке "Layouts" добавляем файл "MyProject\LookupFieldWithSearch\SelectItem.aspx" (Это страница диалога).

- По нажатию на фильтр (см. рис. 1) будет выполняться JavaScript метод openPickerDialog() (см. листинг 4) - открывающий в диалоговом окне страницу "SelectItem.aspx" (см. листинг 5).

<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
    Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SelectItem.aspx.cs" Inherits="MyProject.Layouts.LookupFieldWithSearch.SelectItem"
    MasterPageFile="~/_layouts/dialog.master" %>

<asp:Content ID="DialogHeader" ContentPlaceHolderID="PlaceHolderDialogHeaderSection" runat="server"></asp:Content>
<asp:Content ID="DialogBodyMain" ContentPlaceHolderID="PlaceHolderDialogBodyMainSection" runat="server">
    <script type="text/javascript">
        var hiddenValueClientID = "<SharePoint:EncodedLiteral ID='m_hiddenValueClientID' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />";
        var displayValueClientID = "<SharePoint:EncodedLiteral ID='m_displayValueClientID' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />";
        function commit() {
            if (document.getElementById(hiddenValueClientID).value != "") {
                window.frameElement.commitPopup(getSelectedItem());
            }
            else {
                alert("<SharePoint:EncodedLiteral ID='m_okError' runat='server' EncodeMethod='EcmaScriptStringLiteralEncode' />");
            }
        }

        function getSelectedItem() {
            var item = {
                hiddenValue: document.getElementById(hiddenValueClientID).value,
                displayValue: document.getElementById(displayValueClientID).value
            };

            return item;
        }

    </script>
    <style type="text/css">
        .searchResults
        {
            margin-left: 2px;
            height: 310px;
            width: 99%;
        }
        .displayValue
        {
            margin-left: 2px;
            width: 99%;
        }
        .searchTextBox
        {
            margin-left: 3px;
        }
    </style>
    <table width="570" cellpadding="0" cellspacing="0" style="border-collapse: collapse; border-style: none; border-width: 0px; margin: 5px 5px 5px 5px;">
        <tr>
            <td>
                <asp:TextBox ID="m_searchTextBox" runat="server" Width="540px" CssClass="searchTextBox" />
            </td>
            <td align="center" style="width: 25px; vertical-align: middle;">
                <asp:ImageButton ImageUrl="~/_layouts/images/MyProject/magnifier.png" runat="server" OnClick="Search_Click" />
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <asp:ListBox AutoPostBack="true" ID="m_searchResults" runat="server" CssClass="searchResults" OnSelectedIndexChanged="m_searchResults_SelectedIndexChanged">
                </asp:ListBox>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <asp:TextBox ID="m_displayValue" CssClass="displayValue" runat="server" Enabled="false" />
                <asp:HiddenField ID="m_hiddenValue" runat="server" />
            </td>
        </tr>
    </table>
</asp:Content>
Листинг 5 - SelectItem.aspx.
Обратите внимание, что на странице SelectItem.aspx, MasterPageFile="~/_layouts/dialog.master". Это специализированный MasterPage для диалоговых окон.
Рисунок 2 - Вид диалогового окна.


using System;
using System.Linq;
using System.Web.UI;
using Microsoft.SharePoint;
using PrivateAffairs.Models;
using System.Collections.Generic;
using Microsoft.SharePoint.WebControls;
using MyProject.CustomFields.LookupFieldWithSearch;

namespace MyProject.Layouts.LookupFieldWithSearch
{
    public partial class SelectItem : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                m_hiddenValueClientID.Text = m_hiddenValue.ClientID;
                m_displayValueClientID.Text = m_displayValue.ClientID;

                ((DialogMaster)this.Page.Master).OkButton.OnClientClick = "commit()";
                m_okError.Text = "Вы не выбрали элемент!";
            }
        }

        private List<LookupItem> m_foundItems
        {
            get
            {
                if (ViewState["m_foundItems"] == null)
                {
                    return null;
                }
                else
                {
                    return (List<LookupItem>)ViewState["m_foundItems"];
                }
            }
            set
            {
                ViewState["m_foundItems"] = value;
            }
        }

        protected void Search_Click(object sender, ImageClickEventArgs e)
        {
            if (m_searchTextBox.Text.Trim() != string.Empty)
            {
                var query = new SPQuery()
                {
                    Query = string.Format("<Where><Contains><FieldRef Name='Title' /><Value Type='Text'>{0}</Value></Contains></Where>", m_searchTextBox.Text.Trim()),
                    ViewAttributes = "Scope='Recursive'",
                    QueryThrottleMode = SPQueryThrottleOption.Override
                };
                var list = SPContext.Current.Web.Lists.GetList(new Guid(Request.QueryString["listId"]), true);
                var items = list.GetItems(query);
                if (m_foundItems == null)
                    m_foundItems = new List<LookupItem>();
                m_foundItems.Clear();
                foreach (SPListItem item in items)
                {
                    m_foundItems.Add(new LookupItem() { ID = item.ID, Title = item["Title"].ToString() });
                }
                m_searchResults.DataSource = m_foundItems;
                m_searchResults.DataValueField = "ID";
                m_searchResults.DataTextField = "Title";
                m_searchResults.DataBind();
            }
        }
        protected void m_searchResults_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (m_searchResults.SelectedValue != null && m_foundItems != null)
            {
                var item = (from q in m_foundItems where q.ID == int.Parse(m_searchResults.SelectedValue) select q).FirstOrDefault();
                if (item != null)
                {
                    m_hiddenValue.Value = item.ID.ToString();
                    m_displayValue.Text = item.Title;
                }
            }
        }
    }
}
Листинг 6 - SelectItem.aspx.cs.

- В методе "PageLoad" страницы "SelectItem.aspx", переопределяем клиентский метод нажатия на OK в диалоговом окне (см. листинг 6).
Я не буду описывать все блоки кода. Код не сложный, и в нем все итак тривиально и понятно. Если будут вопросы, вы можете задать их мне в комментариях к этому посту, и я постараюсь ответить на них.
Часть 2: Возможные проблемы и их решения


Проблема: Создал шаблон с Display и Edit представлениями, но после delpoy-я они не появляются.
Решение: SharePoint загружает все ".ascx" файлы c шаблонами, парсит их и получает оттуда массив RenderingTemplate's. В процессе запроса, выбирается нужный RenderingTemplate по ID. Если вы назовете свой edit template например так: "SharePoint:RenderingTemplate ID='EditTemplate'", то ваш шаблон может быть перекрыт другим шаблоном. Поэтому старайтесь выбирать для своего шаблона уникальный ID (можно даже Guid для надежности).
 Проблема: При открытии диалогового окна вылетает ошибка.
Решение: Все, что открывается в диалоговом окне, должно быть помечено как SafeControl (SelectItem.aspx тоже нужно пометить как SafeControl).

PS. В данном примере не реализована поддержка MultiLookup.