Miałem przez najbliższy czas nic nie pisać, ale jedno pytanie na forum CG zmotywowało mnie do napisania tego mam nadzieję krótkiego postu.

Ogólnie spotkałem się z kilkoma sposobami tworzenia stron dla Content Types, jednak żaden nie przypadł mi do gustu z tego względu, iż wszystkie sposoby zakładają, że ma się dostęp do SharePoint podczas developerki. W moim przypadku jest raczej na odwrót, SharePoint dopiero widzę wtedy, kiedy chcę swoje rozwiązanie wgrać i przetestować. Często także nie mam możliwości podłączenia się Remote Debbugerem by wspomóc się podczas analizowania błędów.

Moje środowiska pracy opiera się głównie na DLLkach, które zaciągnąłem z instalacji WSS lub MOSS i które następnie systematycznie używam w referencjach do projektów. Podczas pobierania DLLek nie można poprzestać na jednej Microsoft.SharePoint.dll, ale trzeba ściągnąć je wszystkie, w przeciwnym wypadku nie da się wszystkiego oprogramować, gdyż niektóre DLLki wymagają innych o których nawet byśmy nie pomyśleli by je zaciągnąć z instalatora.

To tyle słowem wstępu, postaram się teraz w miarę łatwo opisać mój sposób na tworzenie własnych stron do Content Types, który spełnia wyżej wymienione warunki środowiska pracy.

Jak większość zapewne już wie, wszystkie typy elementów na listach dziedziczą po konkretnym Conent Type, np.: elementy Custom List dziedziczą po Item Content Type, elementy listy kontaktów po Contact Content Type. Każdy Conent Type może mieć do siebie przypisaną stronę wyświetlania, edycji oraz dodania elementu. Takie strony są deklarowane w pliku XML definiującym Content Type. Plik ten wygląda mniej więcej tak:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ContentType ID="0x0108000B6624090BAD494eAB829219E5FF4970"
      Name="My Custom Task Content Type"
      Group="Gutek ContentTypes"
      Description="Content Type for displaying custom task informations"
      Version="0"
      Hidden="FALSE">
    <FieldRefs>
    </FieldRefs>
    <XmlDocuments>
     
      <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
        <FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
          <Display>ListForm</Display>
          <Edit>ListForm</Edit>
          <New>ListForm</New>
        </FormTemplates>
      </XmlDocument>
 
      <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
        <FormUrls xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
          <Display>_layouts/MyCustomPages/Display.aspx</Display>
        </FormUrls>
      </XmlDocument>
     
    </XmlDocuments>
  </ContentType>
</Elements>

Po kolei postaram się teraz wyjaśnić poszczególne tagi/atrybuty I jakie wartości powinny one przechowywać (wszystkie brakujące atrybuty można znaleźć tutaj:http://msdn2.microsoft.com/en-us/library/aa544268.aspx). Dla ułatwienia sobie pracy, w tym przypadku nie tworzę żadnych dodatkowych pól dla Conent Type, w ramach potrzeby dodam je później ze strony SharePoint i załącze do Content Type:

  • ContentType ID – ID ContentType, które musi zostać stworzone przez nas. Cały problem polega na tym, że ciężko jest się domyśleć nie znając struktury i nazewnictwa Conent Types jak takie coś stworzyć. Nie jest to tak naprawdę nic trudnego. Na początku musimy się zorientować, jakie ID ma Conent Type po którym chcemy dziedziczyć (w tym przypadku będzie to Task Content Type). Informacje o ID’kach można znaleźć tutaj. W naszym przypadku ID jest równe 0x0108, teraz do tego ID trzeba dodać dwa zera (00). Dzięki Arturowi, już wiemy dlaczego. Dwa zera (00) służą jako rozdzielenie Typu Conent Type od jego unikatowego ID (GUID). Teraz ID wygląda tak 0x010800. Teraz za pomocą VS GUID generatora, tworzymy nowy GUID, w moim przypadku jest to {0B662409-0BAD-494e-AB82-9219E5FF4970}. Z tego GUID’a usuwamy wszystkie klamry i myślniki i powstaje nam numer: 0B6624090BAD494eAB829219E5FF4970, który dodajemy do naszego ID, przez co powstaje nam takie coś: 0x0108000B6624090BAD494eAB829219E5FF4970. Ten numer ID wklejamy jako wartość atrybuty ID Tagu ContentType. Ważne w tym wszystkim jest to, że nasze Content Type MUSZĄ dziedziczyć po SharePoint Content Types.
  • ContentType Name – Nazwa Conent Type, która będzie widoczna na stronie, oraz którą będziemy się posługiwać.
  • ContentType Group – Grupa, do jakiej Content Type ma należeć. Jeżeli podamy nazwę grupy, która nie istnieje, grupa zostanie stworzona.
  • ConentType Description – Opis Conent Type, który będzie widniał na stronie.
  • ConentType Version – Aktualna wersja Content Type, w ramach potrzeby można ją zwiększać. Umożliwia to nam lepszą kontrolę, Conent Types.
  • ConentType Hidden – Powoduje, że nasz Conent Type albo jest widoczny dla użytkownika albo jest niewidoczny. Przyjmuje wartości True/False.
  • XmlDocuments – Tag umożliwia nam dodanie informacji o stronach, jakie nasz Conent Type będzie wykorzystywał. Warto zajrzeć na stronę tą stronę, by dowiedzieć się więcej o tym, co może zawierać tag XmlDocuments. W naszym przypadku, zawiera on dwie definicje XmlDocument, jedną dla FormTemplates drugą dla FormUrls. FormTemplates określa, z jakich szablonów standardowych formularzy powinien nasz Content Type korzystać. Zaś FormUrls informuje, z jakich naszych przeciążonych formularzy nasz Content Type ma korzystać.

Jak już mamy nasz XML dla Content Type gotowy, trzeba teraz stworzyć XML dla Feature, który zainstaluje nam ten Content Type.

Feature XML wygląda mniej więcej tak:

<?xml version="1.0" encoding="utf-8"?>
<Feature  Id="{07534FBE-6A20-43c8-97AA-14CDDFE4E2AF}"
          Title="Gutek's Custom Content Types Feature"
          Description="Custom Content types for blog purpose."
          Version="12.0.0.0"
          Scope="Site"
          xmlns="http://schemas.microsoft.com/sharepoint/">
  <ElementManifests>
    <ElementManifest Location="MyCustomTask ContentType.xml" />
  </ElementManifests>
  <Properties>
    <Property Key="GloballyAvailable" Value="true" />
  </Properties>
</Feature>

Poszczególne elementy tego XML’a to (więcej dostępnych pól oraz ich opis można znaleźć tutaj:http://msdn2.microsoft.com/en-us/library/ms436075.aspx):

  • Feature ID – Unikatowy GUID określający ID danego feature.
  • Feature Title – Nazwa naszego feature, która pokaże się w galerii SharePoint Features.
  • Feature Description – Opis naszego fearture, który pokaże się w galerii SharePoint Features.
  • Fearture Version – Wersja Feature.
  • Feature Scope – Określa zakres działania feature. Site odpowiedzialny jest za cały portal, Web za pod stronę.
  • ElementManifests – Zawiera listę elementów ElementManifest (bez s na końcu), które są załączone do danego feature. W naszym przypadku chcemy załączyć tylko i wyłącznie definicję naszego Content Type.
  • Properties – Służy określeniu właściwości naszego feature. W naszym przypadku chcemy, by nasz Conent Type był dostępny na wszystkich stronach portalu.

Tak przygotowane pliki zapisujemy. By przygotować instalkę, tworzymy sobie katalog MyFeature, do którego wgrywamy obydwa pliki XML. Taki gotowy katalog przegrywamy do katalogu 12 HIVETEMPLATEFEATURES, gdzie 12 HIVE przeważnie jest równy: C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12

moss_gutek_001

Następnie na systemie z SharePoint otwieramy command line, przechodzimy do katalogu 12 HIVEBIN i uruchamiamy następujące polecenia (uwaga, nie kopiujcie tych poleceń, a jak już to zrobicie to skasujcie myślnik i dodajcie go ponownie):

stsadm –o installfeature –name MyFeature

stsadm –o activatefeature –name MyFeature –url http://localhost

Gdybyśmy chcieli usunąć feature ze strony, wykonujemy następujące komendy:

stsadm –o deactivatefeature –name MyFeature –url http://localhost

stsadm –uninstallfeature –name MyFeature

Teraz po uruchomieniu komendy instalującej i aktywującej feature, możemy otworzyć naszą stronę SharePoint, kliknąć na Site Actions – Site Settings

moss_gutek_002

Następnie kliknąć na Site Collection Features

moss_gutek_003

I upewnić się czy nasz feature został poprawnie zainstalowany i zaktywowany (jeżeli nie, to należy kliknąć na przycisk Activate):

moss_gutek_004

Możemy także sprawdzić czy nasz Conent Type został poprawnie dodany, w tym celu cofamy się do strony Site Settings i klikamy na Site Conent Types:

moss_gutek_005

Nasz Conent Type powinien być wyświetlony pod nazwą grupy, do której żeśmy go dodali:

moss_gutek_006

Teraz pora przypisać go do Listy tasków, w tym celu dla naszego zapotrzebowania, tworzymy sobie listę tasków o nazwie MyTasks. Następnie otwieramy listę tasków i klikamy na Settings – List Settings:

moss_gutek_007

Z General Settings wybieramy opcję Advanced Settings:

moss_gutek_008

I zaznaczamy by list zezwalała na zarządzanie Content Types:

moss_gutek_009

Następnie w sekcji Conent Types, która powinna nam się pojawić po tym jak zaznaczyliśmy „Yes” i kliknęliśmy OK., wybieramy opcję Add from existing site conent types:

moss_gutek_010

Następnie z listy możliwych Content Types wybieramy Conent Type, który nas interesuje (czyli ten, który dodaliśmy) i klikamy OK.:

moss_gutek_011

Tym razem w sekcji Content Types klikamy na Change new button order and default content type, i na stronie, która nam się pokazała odhaczamy Task a naszemu Content Type przypisujemy wartość 1. Dzięki tej operacji wszystkie tworzone taski na naszej liście będą tworzone z naszego Content Type.

moss_gutek_012

Dla testu, dodajemy nowy element do listy MyTasks – ta operacja powinna się udać – pamiętacie ConentType XML? Teraz spróbujmy go z edytować, ta operacja też powinna się udać. Za to jak klikniecie na nazwę tasku by go wyświetlić dostaniecie mniej więcej taki opis błędu:

moss_gutek_013

Ale nie mamy, czym się martwić, ten błąd istnieje, bo jeszcze strony żeśmy nie stworzyli:)

Super, najważniejsze, że mamy już prawie wszystko gotowe, teraz trochę programowania i już jesteśmy w domu :)

Teraz potrzebujemy DLLek by móc oprogramować stronkę. W tym celu proponuje wam wyciągniecie sobie z serwera, na którym stoi SharePoint następujące DLLki:

  • Microsoft.HtmlTrans.Interface.dll
  • Microsoft.Internal.Mime.dll
  • Microsoft.SharePoint.AdministrationOperation.dll
  • Microsoft.SharePoint.ApplicationPages.Administration.dll
  • Microsoft.SharePoint.ApplicationPages.dll
  • Microsoft.SharePoint.Diagnostics.dll
  • Microsoft.SharePoint.dll
  • Microsoft.SharePoint.Dsp.dll
  • Microsoft.SharePoint.Dsp.OleDb.dll
  • Microsoft.SharePoint.Dsp.SoapPT.dll
  • Microsoft.SharePoint.Dsp.Sts.dll
  • Microsoft.SharePoint.Dsp.XmlUrl.dll
  • Microsoft.SharePoint.intl.dll
  • Microsoft.SharePoint.Library.dll
  • Microsoft.SharePoint.Msg.dll
  • microsoft.sharepoint.search.intl.dll
  • microsoft.sharepoint.search.intl.resources.dll
  • Microsoft.SharePoint.Security.dll
  • Microsoft.SharePoint.SetupConfiguration.Intl.dll
  • microsoft.sharepoint.WorkflowActions.dll
  • microsoft.sharepoint.WorkflowActions.intl.dll
  • microsoft.SharePoint.workflowactions.intl.resources.dll
  • microsoft.SharePoint.workflows.dll
  • microsoft.SharePoint.workflows.intl.dll
  • microsoft.SharePoint.workflows.intl.resources.dll
  • STSSOAP.DLL

Następnie należy wrzucić je do GAC oraz do stworzonego u siebie katalogu 12 HIVEISAPI. Jeżeli jakiś DLLek nie macie, nie przejmujcie się tym. Część z nich jest tylko i wyłącznie dostępna w MOSS.

Otwieramy VS 2005/2008 i tworzymy nowy projekt ASP.NET Web Application a w nim tworzymy nowy Web Form o nazwie Display.aspx.

Do nowo utworzonego projektu dodajemy referencje do Microsoft.SharePoint.dll. Zaś plik Display.aspx wypełniamy następującym kodem:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Display.aspx.cs" Inherits="WebApplication1.Display" %>
<%-- @ Page Language="C#" AutoEventWireup="true" Inherits="WebApplication1.Display,WebApplication1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=9bdd615dfd84016b" --%>
 
<%--Reference the SharePoint DLL for a tag that we will need later on in the script--%>
<%@ 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="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"
    Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
 
<asp:Content ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
      <SharePoint:ListProperty Property="Title" runat="server"/>
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">
      <SharePoint:ListProperty Property="Title" runat="server"/>
</asp:Content>
 
<%--This is one of the Content Place Holders named in the
    Default.Master and Applicaiton.Master files.
    It is also where most, if not all of your control code should go.   --%>
<asp:content contentplaceholderid="PlaceHolderMain" runat="server">
</asp:content>

Nasz szablon do tworzenia stron, jest już prawie gotowy. Ze względu na to, że nie mamy dostępu do SharePointa nie mamy też jego informacji na temat plików master page. Dlatego przechodzimy do edycji kodu źródłowego strony i wklejamy następujący kod:

protected override void OnPreInit(EventArgs e)
{
    // to już było tutaj i ja tego nie zmieniam
    base.OnPreInit(e);
    // Ustawienie jakiego rodzaju operacja jest wykonywana na elemencie
    // - w naszym przypadku wyświetlamy go
    SPContext.Current.FormContext.FormMode = SPControlMode.Display;
 
    // Przypisanie master page do strony w zależności od kontekstu w jakim
    // akurat się obracamy
    this.MasterPageFile = SPControl.GetContextWeb(Context).MasterUrl;
}

Kod ten wymaga dodania, dwóch using:

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

Opis działania kodu znajduje się w komentarzach, więc nie będę go tutaj powtarzał.

Żeby szablon był w 100% gotowy, dodajemy klucz by kod był podpisany. Po wszystkim nasze solution powinno wyglądać tak:

moss_gutek_014

Teraz zaczynamy zabawę. Mamy już szablon gotowy. Ma on zadeklarowane trzy ekstra tagi SharePointowe: SharePoint, Utilities oraz WebPartPages. Za pewne ze wszystkich nie będziemy korzystać a w tym przypadku będziemy korzystać tylko i wyłącznie z tagu SharePoint, ale ja je zawsze trzymam na wszelki wypadek. Łatwiej mi jest potem zacząć korzystać z tych tagów niż szukać kodu gdzie je już kiedyś deklarowałem. Na pamięć nie zamierzam się tego uczyć :)

Następnie z serwera, na którym jest MOSS z katalogu 12 HIVETEMPLATECONTROLTEMPLATES kopiujemy zawartość kontrolki DisplayPreview.ascx do naszej strony między tag <asp:content contentplaceholderid="PlaceHolderMain" runat="server"></asp:content>.

DisplayPreview zawiera standardową tabelkę wyświetlającą elementy. Dzięki czemu jeżeli chcemy mieć podobny wygląd do tego, co pokazuje SharePoint, w ten sposób to łatwo uzyskamy. Ja to jednak trochę modyfikuje i dodaje takie rzeczy jak przycisk usunięcia, edycji i dodania nowego elementu. Więc to, co ja wklejam wygląda tak:

<table border="0" cellpadding="0" cellspacing="0" width="590px">
      <tr>
            <td valign="top" style="direction:ltr;">
            <div>
                  <table class="ms-formtoolbar" cellpadding="2" cellspacing="0" border="0" width="100%">
                        <tr>
                              <td width="99%" class="ms-toolbar" nowrap>
                              <img src="/_layouts/images/blank.gif" width="1" height="18" alt=""></td>
                              <td class="ms-toolbar" nowrap="true">
                              <table cellpadding="0" cellspacing="0" width="100%">
                                    <tr>
                                          <td align="right" width="100%" nowrap>
                                         
                                          </td>
                                    </tr>
                              </table>
                              </td>
                              <td class="ms-separator">&nbsp;</td>
                              <td class="ms-toolbar" nowrap="true">
                              <table cellpadding="0" cellspacing="0" width="100%">
                                    <tr>
                                          <td align="right" width="100%" nowrap>
                                          <asp:Button runat="server" text="Close" cssclass="ms-ButtonHeightWidth" ID="btnOkTop" OnClick="btnOK_Click"></asp:Button>
                                          </td>
                                    </tr>
                              </table>
                              </td>
                        </tr>
                  </table>
                  <table class="ms-toolbar" cellpadding="2" cellspacing="0" border="0" width="100%">
                        <tr>
                              <td class="ms-toolbar" nowrap="true">
                              <table cellpadding="1" cellspacing="0">
                                    <tr>
                                          <td class="ms-toolbar" nowrap><em>
                                          <asp:Literal runat="server" id="listformpvw" Text="" /></em></td>
                                    </tr>
                              </table>
                              </td>
                              <td width="10%" class="ms-toolbar" nowrap="true">
                              <nobr>
                              <SharePoint:NewItemButton ID="NewItemButton" runat="server"/> 
                          </nobr>  
                              </td>
                              <td width="10%" class="ms-toolbar" nowrap="true">
                              <nobr>
                                    <SharePoint:EditItemButton ID="EditItemButton" runat="server"/>
                              </nobr>    
                              </td>
                              <td width="10%" class="ms-toolbar" nowrap="true">
                              <nobr>
                                    <SharePoint:DeleteItemButton ID="DeleteItemButton" runat="server"/> 
                              </nobr>    
                              </td>
                              <td class="ms-toolbar" nowrap="true" width="69%">
                              <span id="reqdFldTxt" style="white-space: nowrap;padding-right: 3px;" class="ms-descriptiontext">
                              <img src="/_layouts/images/blank.gif" width="1" height="18" alt="">
                              </span> </td>
                        </tr>
                  </table>
                  <table class="ms-formtable" style="margin-top: 8px;" border="0" cellpadding="0" cellspacing="0" width="100%">
                        <tr>
                              <td nowrap="true" valign="top" width="190px" class="ms-formlabel">
                              <nobr><asp:Literal runat="server" id="colname1" Text="<% $Resources: wss, PreviewColumnName1 %>" /></nobr> </td>
                              <td valign="top" class="ms-formbody" width="400px" id="SPFieldText">
                              <asp:Literal runat="server" id="colval1" Text="<% $Resources: wss, PreviewColumnValue1 %>" /></td>
                        </tr>
                        <tr>
                              <td nowrap="true" valign="top" width="190px" class="ms-formlabel">
                              <nobr><asp:Literal runat="server" id="colname2" Text="<% $Resources: wss, PreviewColumnName2 %>" /></nobr> </td>
                              <td valign="top" class="ms-formbody" width="400px" id="SPFieldText">
                              <asp:Literal runat="server" id="colval2" Text="<% $Resources: wss, PreviewColumnValue2 %>" /></td>
                        </tr>
                        <tr>
                              <td nowrap="true" valign="top" width="190px" class="ms-formlabel">
                              <nobr><asp:Literal runat="server" id="colname3" Text="<% $Resources: wss, PreviewColumnName3 %>" /></nobr> </td>
                              <td valign="top" class="ms-formbody" width="400px" id="SPFieldText">
                              <asp:Literal runat="server" id="colval3" Text="<% $Resources: wss, PreviewColumnValue3 %>" /></td>
                        </tr>
                  </table>
                  <table cellpadding="0" cellspacing="0" width="100%">
                        <tr>
                              <td class="ms-formline">
                              <img src="/_layouts/images/blank.gif" width="1" height="1" alt=""></td>
                        </tr>
                  </table>
                  <table cellpadding="0" cellspacing="0" width="100%" style="padding-top: 7px">
                        <tr>
                              <td width="100%">
                              <table class="ms-formtoolbar" cellpadding="2" cellspacing="0" border="0" width="100%">
                                    <tr>
                                          <td width="99%" class="ms-toolbar" nowrap>
                                          <table cellpadding="0" cellspacing="0">
                                                <tr>
                                                      <td nowrap class="ms-descriptiontext" id="onetidinfoblock1">
                                                      Created at <asp:Literal runat="server" id="lCreated" Text="" /> by <nobr><span>
                                                      <asp:HyperLink ID="hlCreatedBy" runat="server" /><img border="0" height="1" width="3" src="/_layouts/images/blank.gif" alt="" /><img name="imnmark" border="0" height="12" width="12" src="/_layouts/images/blank.gif" alt="" sip="[email protected]" id="imn0"></span></nobr>&nbsp;
                                                      </td>
                                                </tr>
                                                <tr>
                                                      <td nowrap class="ms-descriptiontext" id="onetidinfoblock2">
                                                      Last modified at <asp:Literal runat="server" id="lModified" Text="" /> by <nobr>
                                                      <span>
                                                      <asp:HyperLink ID="hlModifiedBy" runat="server" /><img border="0" height="1" width="3" src="/_layouts/images/blank.gif" alt="" /><img name="imnmark" border="0" height="12" width="12" src="/_layouts/images/blank.gif" alt="" sip="[email protected]" id="imn1"></span></nobr>&nbsp;
                                                      </td>
                                                </tr>
                                          </table>
                                          </td>
                                          <td class="ms-toolbar" nowrap="true">
                                          <table cellpadding="0" cellspacing="0" width="100%">
                                                <tr>
                                                      <td align="right" width="100%" nowrap>
                                                     
                                                      </td>
                                                </tr>
                                          </table>
                                          </td>
                                          <td class="ms-separator">&nbsp;</td>
                                          <td class="ms-toolbar" nowrap="true">
                                          <table cellpadding="0" cellspacing="0" width="100%">
                                                <tr>
                                                      <td align="right" width="100%" nowrap>
                                                      <asp:Button runat="server" text="Close" cssclass="ms-ButtonHeightWidth" ID="btnOkBottom" OnClick="btnOK_Click"></asp:Button>
                                                      </td>
                                                </tr>
                                          </table>
                                          </td>
                                    </tr>
                              </table>
                              </td>
                        </tr>
                  </table>
            </div>
            </td>
      </tr>
</table>

Proponuje sobie zachować ten fragment, ze względu na to, że zmodyfikowałem w nim także długość tabelki, która ma wyświetlać dane.

Żeby skrócić ten post bo i tak już trochę jest tego tutaj :) jak na razie 14 stron ;) to nie będę wyświetlał wszystkich pól a jedynie wyświetlę informacje o tytule tasku i osobie do której task został przypisany. W tym celu należy z edytować środkową tabelkę (tam gdzie znajdziecie element o id: colval1 i colval2). Ja zmieniłem nazwy colval1 i colval2 na lTitle i lAssignedTo i to wszystko. i dodajmy następujący kod:

/// <summary>
/// Finish URL.
/// </summary>
private string finishUrl;
/// <summary>
/// Referrer URL.
/// </summary>
private string referrerUrl;
/// <summary>
/// Finish parameter name in URL.
/// </summary>
private const string FinishUrlParameterName = "Source";
 
protected void btnOK_Click(object e, EventArgs args)
{
    RedirectToFinishUrl();
}
 
/// <summary>
/// Redirects to finish URL. If FinishUrl is null or empty method is redirecting
/// to the AlternateUrl site.
/// </summary>
public void RedirectToFinishUrl()
{
    if (!string.IsNullOrEmpty(this.FinishUrl))
    {
        SPUtility.Redirect(this.FinishUrl, SPRedirectFlags.Default, this.Context);
    }
    else
    {
        SPUtility.Redirect(this.AlternateUrl, SPRedirectFlags.Default, this.Context);
    }
}
 
/// <summary>
/// Gets or sets the finish URL.
/// </summary>
/// <value>The finish URL.</value>
public virtual string FinishUrl
{
    get
    {
        string url = SPHttpUtility.UrlPathDecode(base.Request.QueryString[Display.FinishUrlParameterName], false);
 
        if (!string.IsNullOrEmpty(url))
        {
            return url;
        }
 
        if (!string.IsNullOrEmpty(this.finishUrl))
        {
            return this.finishUrl;
        }
 
        return this.referrerUrl;
    }
    set
    {
        if (string.IsNullOrEmpty(value))
        {
            throw new ArgumentNullException("value");
        }
 
        this.finishUrl = value;
    }
}
 
/// <summary>
/// Gets the alternate URL.
/// </summary>
/// <value>The alternate URL.</value>
public virtual string AlternateUrl
{
    get
    {
        return SPContext.Current.Web.ServerRelativeUrl;
    }
}

Skoro mamy już oprogramowane wszystkie przyciski, pora wyświetlić interesujące nas dane. W tym celu wykorzystujemy metodę Page_Load:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        // Url do którego ma przekierować
        if (base.Request.UrlReferrer != null)
        {
            this.referrerUrl = base.Request.UrlReferrer.ToString();
        }
 
        // Stopka tabelki
        this.lCreated.Text = ((DateTime)SPContext.Current.ListItem["Created"]).ToShortDateString() + " " + ((DateTime)SPContext.Current.ListItem["Created"]).ToShortTimeString();
        this.lModified.Text = ((DateTime)SPContext.Current.ListItem["Modified"]).ToShortDateString() + " " + ((DateTime)SPContext.Current.ListItem["Modified"]).ToShortTimeString();
 
        SPFieldUserValue createdBy = new SPFieldUserValue(SPContext.Current.Web, SPContext.Current.ListItem["Created By"].ToString());
        SPFieldUserValue modifiedBy = new SPFieldUserValue(SPContext.Current.Web, SPContext.Current.ListItem["Modified By"].ToString());
 
        // Tworzenie linków do użytkowników w stopce tabelki
        hlCreatedBy.Text = createdBy.User.Name;
        hlCreatedBy.NavigateUrl = "~/_layouts/userdisp.aspx?ID=" + createdBy.User.ID.ToString();
        hlModifiedBy.Text = modifiedBy.User.Name;
        hlModifiedBy.NavigateUrl = "~/_layouts/userdisp.aspx?ID=" + modifiedBy.User.ID.ToString();
 
        // Przypisanie nazwy tasku
        this.lTitle.Text = SPContext.Current.ListItem.Title;
 
        // Pobranie uzytkownika do ktorego jest przypisany task
        SPFieldUserValue assignedTo = new SPFieldUserValue(SPContext.Current.Web, SPContext.Current.ListItem["Assigned To"].ToString());
        // Wyswietlenie informacji dot. uzytkownika
        this.lAssignedTo.Text = string.Format("{0}-{1}-{2}", assignedTo.User.Name, assignedTo.User.LoginName, assignedTo.User.ID);
    }
}

Teraz tylko należy wgrać to, co napisaliśmy na serwer i przetestować. W tym celu kompilujemy projekt, kopiujemy naszą DLL do GAC na serwerze, na którym stoi SharePoint zaś pliczek ASPX lekko zmodyfikowany o nagłówek z:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Display.aspx.cs" Inherits="WebApplication1.Display" %>
<%-- @ Page Language="C#" AutoEventWireup="true" Inherits="WebApplication1.Display,WebApplication1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=9bdd615dfd84016b" --%>

Na:

<%-- @ Page Language="C#" AutoEventWireup="true" CodeBehind="Display.aspx.cs" Inherits="WebApplication1.Display" --%>
<%@ Page Language="C#" AutoEventWireup="true" Inherits="WebApplication1.Display,WebApplication1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=9bdd615dfd84016b"%>

Wgrywamy do katalogu 12 HIVE TEMPLATELAYOUTSMyCustomPages. Teraz by wszystko zakończyć z sukcesem, przechodzimy do katalogu: C:InetpubwwwrootwssVirtualDirectories80 lub tam gdzie mamy naszą stronę SharePoint postawioną i edytujemy plik Web.Config dodając następujące wartość do <SafeControls></SafeControls>:

<SafeControl Assembly="WebApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9bdd615dfd84016b" Namespace="WebApplication1" TypeName="*" Safe="True" AllowRemoteDesigner="True" />

Po wszystkich aktualnych zmianach, wykonujemy polecenie z linii wiersza poleceń:

iisreset

I możemy rozkoszować się swoją nową stroną do wyświetlania Tasków.

moss_gutek_015

Jak widzimy wszystko działa :) Column Name 3 to pozostałość po DisplayPreview i możecie ją śmiało skasować z pliku Display.aspx :)

Mam nadzieję, że was za bardzo nie zanudziłem. Miał być krótki artykuł, ale tego krócej się nie da opisać:(

Jeżeli macie jakiekolwiek pytania, to piszcie śmiało, postaram się na nie wszystkie odpowiedzieć :)

Cały kod opisany w tym poście można pobrać poniżej.

Uwaga (2008-06-27 00:27:35)

Jak słusznie Grzesiek z forum CG zauważył (link) mój kod zakłada, że kożystacie z WSS/MOSS w angielskiej wersji językowej. Jeżeli jest inaczej, to proszę zamieńcie nazwy kolum "Assigned To" itp na odpowiednie nazwy z danego języka. Inaczej kod nie będzie wam działał.

11 KOMENTARZE

  1. @ Patryk

    Szczerze nie szukalem nigdy dokladnej odpowiedzi i nigdy sie nadym nie zastanawialem. czasami poprostu przyjmuje to co ktos mi powiedzial. Az sprawdze i dam znac – wrazie czego poprawie artykul.

  2. @ Patryk

    Ok, wiem z czego wyniklo zamieszanie. Ja nigdy nie zmienialem. template MS dostarczony tez ma wersje 12, i w netcie ciagle sie widzi przyklady z 12. Niezle, osoba uczy sie cale zycie. Juz poprawiam artykul :)

  3. @ Gutek
    Wielkie dzieki za odpowiedz. Mozesz mi polecic jakas ksiazke do WSS? – od czego wogole Ty zaczynales przygode z SP i jak dlugo juz w tym siedzisz?

  4. @ Patryk

    Jezeli chodzi o to od kiedy, to od pamietnego lutego 2007 kiedy rozpoczal sie juz zapomniany projekt IT Core. I MOSS i WSS zajmuje sie az do teraz – nie oceniem czy to dobrze, czy zle ;) ale czasami ludzie prosze mnie bym tak nie klnal ;)

    Osobiscie przeczytalem jedna ksiazke:

    Workflow in the 2007 Microsoft Office System

    dotyczy ona tworzenia Workflows w SharePoint i szczerze ja polecam.

    Mialem tez stycznosc z ksiazka:

    Microsoft SharePoint: Building Office 2007 Solutions in C# 2005 (Expert’s Voice in Sharepoint)

    Jednak ja jej calej nie przeczytalem, moze w polowie i potem zarzucilem. Latwiej bylo mi czytac blogi i szukac info w netcie niz konczyc ta ksiazke.

    Naprawde polecam blogi w netcie:

    Ja przewaznie kozystam z google.com i wyszukuje odpowiednich informacji jak czegos nie wiem. Ale przewaznie jest tak, ze jak juz na cos natrafie co sprawia problem, to sprawia to wszystkim i w 70% nikt nie wie jak to rozwiazac i szuka workaroundow.

  5. Cześć – Kuba chciałbym odpowiedzieć dlaczego jest 00 w ID content type. JEst to zrobione w taki sposób, aby 00 było rozdzielnikiem dla typu oraz GUIDa – ot i cała tajemnica. Jeśli przyglądniemy się dokładnie strukturze i pochodzeniu poszczególnych typów (zaczynająć od 0x01 – jako Item) to można to wywnioskować. Identyfikator _zawsze_ czytany jest od lewej do prawej i kiedy trafimy na 00 to oznacza że mozemy okreslić typ a potem mamy “00” i dalej czytamy już konkretny identyfikator. Nie będzie to zmieniame ;-)

  6. @ Artur

    Super :) dzieki, kolejna tajemnica rozwiazana :) hehe, juz chyba dzisiaj o tym wspomnialem ale czlokwiek uczy sie caly czas ;)

    Pozwolisz ze to wytlumaczenie dodam do postu :)

    –UPDATE

    Dodane :)

  7. Cześć!

    Czy mógłbyś dodać parę słów komentarza jak dodać w definicji własnego Content Type jak dodać własną kolumnę standardowego typu. Na przykład pole Data rzeczywistego zrealizowania typu oczywiście Data.

    Pozdrawiam
    Grzessiekk
    ps. dla równowagi wrzucę ten post na Code Guru ;)

  8. @Marcin

    Mialem mozliwosc przejrzenia kilku stron ksiazki. Zgadzam sie, jest dobra, zreszta autor ksiazki jest zajebistym SharePoin’towcem. ale nie polecam jej polskiej wersji – szczerze, czemu takie ksiazki sa tlumaczone na polski z “wymyslnym” nazewnictwem?

    @Grzesiek

    ;) Odpowiedz na CG, dla zainteresowanych: http://www.codeguru.pl/forum-posts-13354.aspx

    tutaj na wszelki wypadek tresc (na CG ciezko to znalezc):

    Hejka,

    dosc prosto… no prawie ;)

    FieldRefs zamieniasz na:

    <

    FieldRefs>

    <

    FieldRef

    ID={1575799B-3952-4fc2-8BF9-F6EE99E6EBDF}

    Name=_MojaData />

    </

    FieldRefs>

    Dodajesz kolejny plik XML:

    <

    Elements xmlns=http://schemas.microsoft.com/sharepoint/>

    <

    Field ID={1575799B-3952-4fc2-8BF9-F6EE99E6EBDF}

    Name=_MojaData

    DisplayName=Moja Data

    Description=Przechowuje moja date

    Group=Moja grupa dla Custom Columns

    Format=DateOnly

    Type=DateTime

    Required=False>

    <

    Default></Default>

    </

    Field>

    </

    Elements>

    taki XML zapisujemy i nastepnie dodajemy go do features.xml tam gdzie dodajemy xml od content type

    Wazne by ID bylo takie samo oraz by bylo unikatowe.

    Gutek

Comments are closed.