При разработке собственных рабочих процессов, вам придётся самим программно создавать задания. При использовании Activity CreateTaskWithContentType, указывая тип контента, можно использовать свои формы инициации, ассоциации и редактирования для задания. В данной статье решил показать как создать форму для редактирования задания.
Создание формы
Открываем Visual Studio (я использую Visual Studio 2010) — Открываем “File Menu” — Выбираем “New” — Выбираем “Web Site” — Выбираем “ASP.NET Web Site” — Меняем тип на HTTP (это очень важно) — Выбираем местоположение: http://localhost/_layouts/AgreementTaskEditForm. IIS скопирует ваши файлы в директорию C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS
— Жмём “OK”, для создания. — Удаляем файлы About.aspx, Default.aspx и SiteMaster
— Создаём папку TaskEditForm. — Жмём на неё правой кнопкой и выбираем “Add New Item” — Выбираем “Web Form” — Называем форму “TaskEditForm.aspx” — Выбираем “Place code in separate file” — Жмём “Add”
После манипуляций проект выглядит как-то так:
Добавляем вверху aspx файла:
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Всё остальное удаляем. Добавляем:
<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server"> <%-- Начало кода контрола --%> <%-- Конец кода контрола --%> <%-- Тэг, который указывает SharePoint, что мы будем постить данные в форму--%> <SharePoint:FormDigest ID="FormDigest1" runat="server" /> </asp:Content>
Теперь внутрь управляющего коннтрола добавляем элементы управления, которые нам нужны. Более-менее в приличный вид для отображения приведём. В итоге файл выглядит примерно так:
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register TagPrefix="spuc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Page Language="C#" AutoEventWireup="true" CodeFile="TaskEditForm.aspx.cs" Inherits="TaskEditForm_TaskEditForm" %> <asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server"> <div id="ApproveForm" style="margin-left: auto; margin-top:50px; margin-right: auto; width:800px; "> <div id="DataField" style=" -moz-box-sizing: border-box;"> <table id="DataT"> <tr> <td style="width:200px;" class="DataTtd DataTLabelTd"> <p style="margin-right:20px; margin-left:20px;">Состояние:</p> </td> <td class="DataTDataTd DataTtd" > <asp:TextBox CssClass="tbx" ID="TaskStatus" Width="500" runat="server" Text="" Enabled="false"> </asp:TextBox> </td> </tr> <tr> <td style="width:200px;" class="DataTtd DataTLabelTd"> <p style="margin-right:20px; margin-left:20px;">Срок выполнения:</p> </td> <td class="DataTDataTd DataTtd "> <spuc:DateTimeControl Enabled="false" runat="server" ID="DueDate" CssClassTextBox="DataTimePicerCSS" DateOnly="true" /> </td> </tr> <tr> <td style="width:200px;" class="DataTtd DataTLabelTd"> <p style="margin-right:20px; margin-left:20px;">Примечание:</p> </td> <td class="DataTDataTd DataTtd "> <asp:TextBox CssClass="tbx" ID="Note" runat="server" rows="5" TextMode="multiline" Text=""></asp:TextBox> </td> </tr> </table> </div> <div id="BtnsField"> <asp:Panel ID="Btns_Panel" runat="server" > <asp:Button ID="btnApprove" onclick="btnApprove_Click" runat="server" Text="Утвердить" /> <asp:Button ID="btnCancel" onclick="btnCancel_Click" runat="server" Text="Отмена" /> </asp:Panel> </div> </div> <SharePoint:FormDigest ID="FormDigest1" runat="server" /> </asp:Content>
Где-то сверху css-стили добавим:
<style type="text/css"> #DataT tr, #DataT, #DataTReAssigned, #DataTReAssigned tr { padding:0px; border-collapse: collapse; } #DataT .DataTtd { padding-bottom:10px; padding-left:0px; padding-right:0px; border-bottom: 1pt solid #D8D8D8; border-top: 1pt solid #D8D8D8; } .DataTDataTd { background-color: #F5F6F7; width:600px; } .DataTLabelTd { width:200px; } .tbx, .DataTimePicerCSS { -moz-box-sizing: border-box; font-family: Times New Roman; font-size: 12pt; font-style: normal; font-weight: normal; text-align: left; white-space: normal; width: 500px; margin-left:20px; } #ctl00_PlaceHolderMain_Author_upLevelDiv, #ctl00_PlaceHolderMain_AssignedToPE_upLevelDiv { height:20px !important; width:500px; border: 1px solid #828790; padding-top: 5px; margin-left:20px; } #ctl00_PlaceHolderMain_FileUpload1 { margin-left:20px; } #BtnsField, #BtnsFieldReAssigned { border-left: 1pt solid #D8D8D8; border-right: 1pt solid #D8D8D8; border-bottom: 1pt solid #D8D8D8; padding-top:15px; text-align:center; padding-bottom:20px; } </style>
Написание кода для формы
Форма редактирования вне проекта рабочего процесса. Поэтому необходимо использовать внешние методы для работы со списками и заданиями. Для начала подключаем соответствующие библиотеки:
using System.Web.UI.WebControls; using Microsoft.SharePoint; using Microsoft.SharePoint.Workflow; using Microsoft.SharePoint.Utilities;
Вы увидите так же методы для обработки действий кнопок и метод, вызывающийся при загрузке страницы:
protected void Page_Load(object sender, EventArgs e) { } protected void btnCancel_Click(object sender, EventArgs e) { } protected void btnApprove_Click(object sender, EventArgs e) { }
Они то и реализуют всю магию. Но для начала необходимо переменные для работы определить.
#region переменные задания protected SPList _TaskListAttachedTo; // список задания рабочего процесса protected SPListItem _TaskListItem; // список в задании protected string _myTaskData; // данные от юзера, которые посланы в р.б. string _paramTaskListItemID; // ID Task List Item #endregion #region параметры рабочего процесса string _paramSPListGuid = string.Empty; // GUID списка, с которым заатачились SPWorkflow _activeWorkflow; // Текущий р.б. Guid _workflowInstanceGuid; // Айдишник р.б. public Microsoft.SharePoint.Workflow. SPWorkflowActivationProperties workflowProperties = new Microsoft.SharePoint.Workflow. SPWorkflowActivationProperties(); #endregion
Получение параметров рабочего процесса
Для начала нам необходимо параметры получить.
private void getWorkflowParameters() { this._paramSPListGuid = Request.Params["List"]; // The SharePoint Document Libary ID this._paramTaskListItemID = Request.Params["ID"]; // The associated Task Lists ID }
Загрузка MasterPage
// Переопределение метода. Запускатеся при иницилазации. // ммм...здесь программно можно задать, какой мастер юзать protected override void OnPreInit(EventArgs e) { base.OnPreInit(e); // Текущая страница string pageName = Page.AppRelativeVirtualPath.Substring( Page.AppRelativeVirtualPath.LastIndexOf('/') + 1); // Если в десижнере if (pageName.Substring(0, 6).ToUpper() == "Design".ToUpper()) { this._myPoratlSite = new SPSite("http://localhost/"); SPControl.SetContextSite(Context, this._myPoratlSite); this._myTeamSite = SPControl.GetContextWeb(Context).Webs["Site1"]; } else { this._myTeamSite = SPControl.GetContextWeb(Context); this.MasterPageFile = _myTeamSite.MasterUrl; } }
Получение информации о списке и рабочем процессе
Теперь необходимо получить параметры рабочего процесса и задания.
private void getTaskListInformation() { // Получаем Task List that, к которму приатачены this._TaskListAttachedTo = this._myTeamSite.Lists[new Guid(this._paramSPListGuid)]; // Получаем Task Item Object, который WF создал this._TaskListItem = this._TaskListAttachedTo.GetItemById( System.Convert.ToInt16(this._paramTaskListItemID)); // Получаем ID Workflow Instance this._workflowInstanceGuid = new Guid(Convert.ToString( this._TaskListItem["WorkflowInstanceID"])); this._activeWorkflow = new SPWorkflow(this._TaskListItem, this._workflowInstanceGuid); }
Получение информации из списка
Теперь, когда нам известна общая информация о списке и рабочем процессе, можно получить информацию о нашем конкретном задании.
private void getTaskInformation() { // Получаем статус if (this._TaskListItem["ows_Status"] != null) { TaskStatus.Text = this._TaskListItem["ows_Status"].ToString(); } // Получаем информацию о сроках if (this._TaskListItem["ows_DueDate"] != null) DueDate.SelectedDate = Convert.ToDateTime( this._TaskListItem["ows_DueDate"]); // Получаем комментарий string sNote = GetParam("ows_Note"); if (sNote != string.Empty) Note.Text = sNote; }
Добавляем в Page_load метод
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) RBList.SelectedIndex = 0; getWorkflowParameters(); getTaskListInformation(); getTaskInformation(); }
Методы для обработки действий кнопок
Осталось лишь написать методы, которые будут обрабатывать действия кнопок.
// Отмена protected void btnCancel_Click(object sender, EventArgs e) { // просто делаем редирет в библиотеку SPUtility.Redirect( this._TaskListAttachedTo.DefaultViewUrl, SPRedirectFlags.UseSource, HttpContext.Current); } // При утверждении protected void btnApprove_Click(object sender, EventArgs e) { Hashtable taskHash = new Hashtable(); taskHash["Result"] = "Утвёрждён"; // кастомное поле "Результат" taskHash["PercentComplete"] = "1"; // 1 = 100%. .9 = 90% taskHash["Note"] = Note.Text; // кастомное поле "Примечание" // обновляем информации о задании SPWorkflowTask.AlterTask(this._TaskListItem, taskHash, true); SPUtility.Redirect( this._TaskListAttachedTo.DefaultViewUrl, SPRedirectFlags.UseSource, HttpContext.Current); }
По аналогии можно новые элементы на форму добавлять. Теперь необходимо тип контента свой создать (который мы завяжем на эту форму), чтобы в рабочем процессе при создании указать наш тип контента с нашей формой редактирования.