Freigeben über


Erstellen eines benutzerdefinierten Webpart-Editors in SharePoint 2010

Zusammenfassung:  Informationen zum Microsoft SharePoint 2010-Webpartsystem und Erstellen eines benutzerdefinierten Webpart-Editors in SharePoint 2010. Sie können mithilfe von benutzerdefinierten EditorParts den Benutzern Funktionalität bieten, die über ASP.NET-Benutzersteuerelemente bereitgestellt werden kann.

Letzte Änderung: Montag, 9. März 2015

Gilt für: Business Connectivity Services | Open XML | SharePoint Designer 2010 | SharePoint Foundation 2010 | SharePoint Online | SharePoint Server 2010 | Visual Studio

Inhalt dieses Artikels
Einführung in benutzerdefinierte EditorParts in SharePoint 2010
Typen für das EditorPart-System in SharePoint 2010
Beispielszenario: Erstellen eines benutzerdefinierten EditorParts in SharePoint 2010
Erstellen der benutzerdefinierten Webpartlösung in Visual Studio 2010
Bereitstellen der SharePoint-Webpart-Editor-Lösung
Schlussbemerkung
Weitere Ressourcen

Bereitgestellt von:  Ravi Chinni, Microsoft Corporation | Vijay Bikka, Microsoft Corporation

Inhalt

  • Einführung in benutzerdefinierte EditorParts in SharePoint 2010

  • Typen für das EditorPart-System in SharePoint 2010

  • Beispielszenario: Erstellen eines benutzerdefinierten EditorParts in SharePoint 2010

  • Erstellen der benutzerdefinierten Webpartlösung in Visual Studio 2010

  • Bereitstellen der SharePoint-Webpart-Editor-Lösung

  • Schlussbemerkung

  • Weitere Ressourcen

Klicken Sie, um Code abzurufen. Code herunterladen: Erstellen eines benutzerdefinierten Webpart-Editors in SharePoint 2010

Einführung in benutzerdefinierte EditorParts in SharePoint 2010

Das Microsoft SharePoint 2010-Webpartsystem ermöglicht Benutzern die Konfiguration eines Webparts mithilfe von Webparteigenschaften. Für jede Webparteigenschaft gibt es eine Standardbenutzeroberfläche, auf die über den Toolbereich Bearbeiten des Webparts zugegriffen werden kann. Eine Eigenschaft vom Typ String wird beispielsweise als Textfeld gerendert, während die Eigenschaft Enum als Dropdownlistenfeld gerendert wird.

Dieses standardmäßige Rendering durch das System lässt nicht viele Anpassungen zu, da der Benutzer keinen Handler für die Steuerelemente erhält, die gerendert werden. Das System weist die folgenden Einschränkungen auf:

  • Kontrolle über die Benutzeroberfläche: Numerische und Zeichenfolgentypen werden als Textfelder, der Typ enumeration als Dropdownlistenfeld und der Typ Boolean als Kontrollkästchen gerendert. Sie können beispielsweise nicht den Typ enumeration als Optionsschaltflächen anstatt als Dropdownlistenfeld anzeigen.

  • Ereignisse: Von den Steuerelementen ausgelöste Ereignisse können nicht bearbeitet werden. Sie können beispielsweise nicht eine Dropdownliste basierend auf der Aktivierung eines Kontrollkästchens aktivieren oder deaktivieren.

  • Gültigkeitsprüfung: Wenn die Gültigkeit der Benutzereingabe geprüft werden muss, bietet das System keine einfache Möglichkeit, ein Microsoft ASP.NET-Steuerelement für die Gültigkeitsprüfung dem generierten Eingabesteuerelement zuzuordnen. Sie können beispielsweise die Gültigkeit der Zeichenfolgeneingabe für eine gültige E-Mail-Adresse nicht mithilfe eines ASP.NET RegEx-Steuerelements für die Gültigkeitsprüfung bestätigen.

Sie können diese Einschränkungen mithilfe benutzerdefinierter EditorParts außer Kraft setzen. Mithilfe dieser Parts können Sie Benutzern Funktionalität bieten, die über ASP.NET-Benutzersteuerelemente bereitgestellt werden kann. Ein Webpart kann benutzerdefinierte EditorParts implementieren, die geladen werden können, wenn das Webpart im Bearbeitungsmodus ist, eine benutzerdefinierte Benutzeroberfläche zur Verfügung stellen, Ereignisse verarbeiten und die Gültigkeit von Eingaben prüfen. Einem Webpart können mehrere benutzerdefinierte EditorParts zugeordnet werden.

Dieser Artikel, in dem das SharePoint 2010-Webpartsystem detailliert beschrieben wird, bietet ein Codebeispiel zum Veranschaulichen der Erstellung eines benutzerdefinierten Webpart-Editors in SharePoint 2010. Zunächst soll das System untersucht werden, das benutzerdefinierte EditorParts ermöglicht.

Typen für das EditorPart-System in SharePoint 2010

Zwei Typen bilden die Grundlage für das Entwickeln benutzerdefinierter EditorParts: die IWebEditable-Schnittstelle und die EditorPart-Klasse.

IWebEditable-Schnittstelle

Über die IWebEditable-Schnittstelle können Sie benutzerdefinierte Bearbeitungssteuerelemente angeben, die einem WebPart-Steuerelement zugeordnet sind. Die WebPart-Basisklasse implementiert diese Schnittstelle bereits, abgeleitete Klassen müssen die Basisimplementierung überschreiben. Tabelle 1 enthält die Elemente, die überschrieben werden müssen.

Tabelle 1. IWebEditable-Elemente

Element

Beschreibung

object WebBrowsableObject { get; }

Die Eigenschaft, über die das EditorPart-Steuerelement einen Verweis auf das zu bearbeitende Webpart erhält.

EditorPartCollection CreateEditorParts();

Diese Methode gibt die Auflistung von EditorPart-Steuerelementen zurück, die dem Webpart zugeordnet sind.

EditorPart-Klasse

Die EditorPart-Klasse dient als Basis einer abgeleiteten Klasse, die im Toolbereich Bearbeiten eines Webparts eine benutzerdefinierte Benutzeroberfläche bereitstellt. Die abgeleitete Klasse muss die in Tabelle 2 aufgeführten Elemente überschreiben.

Tabelle 2. EditorPart-Elemente

Element

Beschreibung

public abstract bool ApplyChanges();

Mithilfe dieser Methode werden die Änderungen, die am EditorPart-Steuerelement erfolgt sind, auf das Webpart angewendet.

public abstract void SyncChanges();

Das Webpart speichert die vom Benutzer bereitgestellten Werte. Diese Methode ruft die Werte aus dem Webpart ab, wenn diese vom EditorPart gelesen werden.

Beispielszenario: Erstellen eines benutzerdefinierten EditorParts in SharePoint 2010

In diesem Abschnitt wird anhand eines Beispielszenarios beschrieben, wie ein benutzerdefiniertes Webpart erstellt wird, das ein benutzerdefiniertes EditorPart enthält.

Das Szenario umfasst das Erstellen eines Webparts, das dem Benutzer eine Gruppe von Registerkarten anzeigt. Jede Registerkarte enthält einen Titel und etwas Inhalt, die beide vom Benutzer eingegeben werden. Bei Klicken auf den Titel wird der entsprechende Inhalt angezeigt. Das Webpart ermöglicht dem Benutzer das Hinzufügen, Bearbeiten und Löschen von Registerkarten mithilfe eines EditorParts.

Abbildung 1 zeigt das Webpart im Bearbeitungsmodus.

Abbildung 1. Registerkarten-Editor-Webpart im Bearbeitungsmodus

Registerkarten-Editor-Webpart im Bearbeitungsmodus

Softwareanforderungen für das benutzerdefinierte EditorPart im SharePoint 2010-Szenario

Für dieses Szenario muss folgende Software auf dem Computer installiert sein:

  • Microsoft SharePoint Server 2010

  • Microsoft Visual Studio 2010

Erstellen der benutzerdefinierten Webpartlösung in Visual Studio 2010

Führen Sie diese Schritte aus, um die Lösung in Visual Studio 2010 zu erstellen.

So erstellen Sie die Webpartlösung in Visual Studio 2010

  1. Klicken Sie in Visual Studio 2010 auf Neues Projekt, erweitern Sie den Knoten SharePoint, klicken Sie auf 2010 und dann auf Leeres SharePoint-Projekt. Nennen Sie das Projekt EditorPartTab, und klicken Sie dann auf OK.

  2. Fügen Sie dem Projekt zwei Klassen mit den Namen TabData und TabConfigurationEditorPart hinzu.

  3. Fügen Sie dem Projekt ein visuelles Webpart mit dem Namen TabEditorWebPart hinzu. Dadurch werden dem Projekt die Klasse TabEditorWebPart und das Benutzersteuerelement TabEditorWebPartUserControl hinzugefügt.

  4. Benennen Sie TabEditorWebUserControl in TabConfigurationEditorPartUserControl um.

    HinweisHinweis

    Vergewissern Sie sich, dass der Klassenname des Benutzersteuerelements in TabConfigurationEditorPartUserControl.ascx.cs ebenfalls umbenannt wird und nicht nur der Dateiname.

  5. Ändern Sie den Wert des Inherits-Attributs der Control-Anweisung in der Codedatei TabConfigurationEditorPartUserControl.ascx entsprechend dem neuen Klassennamen.

  6. Speichern Sie alle Dateien, und stellen Sie sicher, dass der Klassenname in der Codedatei TabConfigurationEditorPartUserControl.ascx.designer.cs so lautet: TabConfigurationEditorPartUserControl.

Die folgenden Komponenten haben Sie dem Projekt hinzugefügt:

  • TabData-Klasse: Entitätsklasse, die eine Registerkarte darstellt.

  • TabEditorWebPart-Klasse: Benutzerdefinierte Webpartklasse zum Anzeigen der Registerkarten.

  • TabConfigurationEditorPart-Klasse: EditorPart-Klasse zum Verfügbarmachen der Funktionalität zum Erstellen, Bearbeiten und Löschen von Registerkarten.

  • TabConfigurationEditorPartUserControl-Klasse: Ein Benutzersteuerelement zum Hosten der Schnittstelle, die von der TabConfigurationEditorPart-Klasse geladen wird.

In den folgenden Abschnitten werden der Code und die Funktionalität dieser Komponenten detailliert beschrieben:

TabData-Klasse

Die TabData-Klasse ist eine Entitätsklasse mit den beiden Eigenschaften Title undContent. Title ist der Name der Registerkarte, Content ihr Inhalt, der bei Klicken auf die Registerkarte angezeigt wird.

Die Klasse ist mit dem Serializable-Attribut markiert, da eine Auflistung von Objekten dieser Klasse in der TabEditorWebPart-Klasse als Eigenschaft deklariert ist, um die Liste der Registerkarten dauerhaft zu speichern.

Der folgende Code enthält die TabData-Klasse, die zwei Eigenschaften für den Titel und Inhalt definiert.

namespace MSDN.SharePoint.Samples
{
    using System;

    [Serializable]
    public class TabData
    {
        public string Title { get; set; }
        public string Content { get; set; }
    }
}

TabEditorWebPart-Klasse

Das Webpart zeigt eine Auflistung von Registerkarten an. Die TabEditorWebPart-Klasse sollte bereits Informationen von der WebPart-Klasse erben. Das Webpart deklariert eine private Variable vom Typ _tabList als Auflistung von TabData-Objekten. Diese Auflistung ist in die TabList-Eigenschaft eingebunden. Die Eigenschaft gibt eine leere Auflistung zurück, wenn _tabList Null ist. Die Eigenschaft ist auch mit Personalizable markiert, um Benutzern die Anpassung der Registerkarten zu ermöglichen.

Das Webpart deklariert auch die private Variable _divTabContent vom Typ HtmlGenericControl, um den Inhalt der ausgewählten Registerkarte anzuzeigen (siehe das folgende Codebeispiel).

namespace MSDN.SharePoint.Samples
{
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;

    [ToolboxItemAttribute(false)]
    public class TabEditorWebPart : System.Web.UI.WebControls.WebParts.WebPart
    {
        // A div to display the content of the tab.
        private HtmlGenericControl _divTabContent;

        // Collection of tabs.
        private List<TabData> _tabList;

        // Property to hold the collection of tabs.
        // Set the Personalizable attribute to true, 
        // to allow for personalization of tabs by users.
        [Personalizable(true)]
        public List<TabData> TabList { 
            get
            {
                if (this._tabList == null)
                {
                    // Return an empty collection if null.
                    this._tabList = new List<TabData>();
                }

                return this._tabList;
            }  
            
            set
            {
                this._tabList = value;
            } 
        }       
    }
}

So implementieren Sie die IWebEditable-Schnittstelle

  1. Wie bereits erwähnt, muss das Webpart die Elemente der IWebEditable-Schnittstelle überschreiben. Die WebBrowsableObject-Eigenschaft wird überschrieben, um einen Verweis auf die TabEditorWebPart-Instanz zurückzugeben (siehe das folgende Beispiel).

    public override object WebBrowsableObject
    {
      // Return a reference to the Web Part instance.
      get { return this; }
    }
    
  2. Die CreateEditorParts-Methode wird überschrieben, um eine Auflistung von TabConfigurationEditorPart-Objekten zurückzugeben. In diesem Fall enthält die Auflistung nur ein Objekt.

    HinweisHinweis

    Die ID jedes EditorParts auf der Seite muss eindeutig sein. Setzen Sie also vor die ID des EditorPart-Elements die ID des Webparts.

    public override EditorPartCollection CreateEditorParts()
    {
      TabConfigurationEditorPart editorPart = new TabConfigurationEditorPart();
    
      // The ID of the editor part should be unique. So prefix it with the ID of the Web Part.
      editorPart.ID = this.ID + "_TabConfigurationEditorPart";
    
      // Create a collection of editor parts and add them to the EditorPart collection.
      List<EditorPart> editors = new List<EditorPart> { editorPart };
      return new EditorPartCollection(editors);
    }
    

So erstellen Sie die Steuerelemente und Ereignishandler

  1. Die CreateChildControls-Methode rendert die TabList-Eigenschaft als ASP.NET-Menüsteuerelement. Wenn die Anzahl der Registerkarten größer als 0 ist, werden Titel und Inhalt der ersten Registerkarte angezeigt. Wenn die Anzahl der Registerkarte gleich 0 ist, wird eine Meldung angezeigt, die den Benutzer auffordert, im Bearbeitungsmodus Registerkarten hinzuzufügen. Diese Methode registriert auch einen Ereignishandler zum Verarbeiten des Klicks auf eine Registerkarte (siehe dieses Codebeispiel).

    protected override void CreateChildControls()
    {
      this._divTabContent = new HtmlGenericControl("div");
      this._divTabContent.ID = "divTabContent";
    
      // Render the tabs if the count is more than zero.
      if (this.TabList.Count > 0)
      {
        Menu tabMenu = new Menu();
    
        tabMenu.Orientation = Orientation.Horizontal;
        tabMenu.MenuItemClick += new MenuEventHandler(TabMenu_MenuItemClick);
        foreach (TabData tab in this.TabList)
        {
          tabMenu.Items.Add(new MenuItem(tab.Title));
        }
    
        this.Controls.Add(tabMenu);
    
        // Set the text in div to the content of the first tab.
        this._divTabContent.InnerHtml = this.TabList[0].Content;
      }
      else
      {
        // If no tabs exist, set the div text to
        // tell the user to edit the Web Part and add tabs.
        this._divTabContent.InnerHtml = "Edit this Web Part to add Tabs.";
      }
    
      this.Controls.Add(_divTabContent);
    }
    
  2. Der TabMenu_MenuItemClick-Ereignishandler verarbeitet den Klick auf den Titel einer Registerkarte, um den entsprechenden Inhalt anzuzeigen (siehe den folgenden Code).

    private void TabMenu_MenuItemClick(object sender, MenuEventArgs e)
    {
      // Display the content related to the tab that was clicked.
      string tabTitle = e.Item.Text;
    
      // Find the tab based on the title clicked, 
      // and set the div to the corresponding content.
      this._divTabContent.InnerHtml = this.TabList.Find(t => t.Title.Equals(tabTitle)).Content;
    }
    

Die SaveChanges-Methode ist so konzipiert, dass der Aufruf aus der EditorPart-Klasse erfolgt. Diese Methode ruft die SetPersonalizationDirty-Methode der WebPart-Klasse auf, die ein Kennzeichen festlegt, das dem Webpart angibt, dass die Webparteigenschaften außerhalb der Klasse geändert wurden. Wird dieses Kennzeichen nicht festgelegt, bleiben die Änderungen an den Webparteigenschaften außerhalb der Klasse wirkungslos.

public void SaveChanges()
{
  // This method sets a flag indicating that the personalization data has changed.
  // This enables the changes to the Web Part properties from outside the Web Part class.
  this.SetPersonalizationDirty();
}

TabConfigurationEditorPart-Klasse

Die TabConfigurationEditorPart-Klasse stellt die Funktionalität zum Erstellen, Bearbeiten und Löschen der Registerkarten bereit. Die TabConfigurationEditorPart-Klasse muss von der EditorPart-Klasse vererbt worden sein.

Alle benötigten Steuerelemente zum Ermöglichen dieser Funktionalität können in der EditorPart-Klasse selbst als untergeordnete Steuerelemente deklariert werden. Die TabConfigurationEditorPartUserControl-Klasse wurde erstellt, und alle benötigten untergeordneten Steuerelemente wurden in ihr deklariert. Das Benutzersteuerelement wird vom EditorPart geladen.

Die Klasse deklariert Verweisvariablen auf das Webpart und Benutzersteuerelement sowie die TabList-Auflistung der TabData-Klasse. Die TabList-Auflistung fungiert als Mittler zum Synchronisieren der Änderungen zwischen dem Benutzersteuerelement und dem Webpart. Der folgende Code veranschaulicht die TabConfigurationEditorPart-Klasse, die Funktionalität zum Erstellen, Bearbeiten und Löschen der Registerkarten bereitstellt.

namespace MSDN.SharePoint.Samples
{
    using System;
    using System.Collections.Generic;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint.WebPartPages;

    public class TabConfigurationEditorPart : EditorPart
    {
        // The deployment path of the user control.
        const string TabControlConfigurationPath = @"~/_CONTROLTEMPLATES/EditorPartTab/TabEditorWebPart/TabConfigurationEditorPartUserControl.ascx";

        // The user control object ID.
        const string UserControlID = "OperationsUserControl";

        // Declare a reference to the user control.
        TabConfigurationEditorPartUserControl configuratorControl;

        // Declare a reference to the Tab Editor Web Part.
        private TabEditorWebPart tabEditorWebPart;

        public TabConfigurationEditorPart()
        {
            this.Title = "Tab Configuration";
        }

        public List<TabData> TabList { get; set; }        
    }
}

So erstellen Sie die Steuerelemente und Ereignishandler

  1. Die EditorPart-Klasse überschreibt die CreateChildControls-Methode der Basisklasse, um das Benutzersteuerelement zu laden und der Auflistung untergeordneter Steuerelemente der EditorPart-Klasse hinzuzufügen. Die Methode registriert auch einen Ereignishandler zum Verarbeiten des Ereignisses, wenn im Toolbereich auf die Schaltfläche Abbrechen geklickt wird. Das Benutzersteuerelement enthält bestimmte Gültigkeitsprüfungen, die nicht erwünscht sind, wenn im Toolbereich auf die Schaltfläche Abbrechen geklickt wird. Die CreateChildControls-Methode deaktiviert deshalb Gültigkeitsprüfungen für die Schaltfläche Abbrechen.

    protected override void CreateChildControls()
    {
      // Get a reference to the Edit Tool pane.
      ToolPane pane = this.Zone as ToolPane;
      if (pane != null)
      {
        // Disable the validation on Cancel button of ToolPane.
        pane.Cancel.CausesValidation = false;
        pane.Cancel.Click += new EventHandler(Cancel_Click);
      }
    
      // Load the user control and add it to the controls collection of the editor part.
      this.configuratorControl =
      this.Page.LoadControl(TabConfigurationEditorPart.TabControlConfigurationPath) as TabConfigurationEditorPartUserControl;
      this.configuratorControl.ID = TabConfigurationEditorPart.UserControlID;
      this.Controls.Add(configuratorControl);
    }
    
  2. Die Cancel_Click-Methode aktiviert die Funktionalität zum Rückgängigmachen der Änderungen, die an der TabList-Eigenschaft bei der Bearbeitung des Webparts erfolgt sind. Dazu wird die TabList-Eigenschaft des Webparts auf die der OriginalTabList-Eigenschaft des Benutzersteuerelements festgelegt.

    void Cancel_Click(object sender, EventArgs e)
    {
      // On cancel, roll back all the changes by restoring the original list.
      if (this.configuratorControl.OriginalTabList != null)
      {
        this.TabList = this.configuratorControl.OriginalTabList;
        this.ApplyChanges();
      }
    }
    

So überschreiben Sie EditorPart-Elemente

  1. Die ApplyChanges-Methode wird von Microsoft .NET Framework aufgerufen, wenn im Toolbereich auf die Schaltfläche OK geklickt wird. Hier müssen Sie Code schreiben, der das Webpart basierend auf den im EditorPart erfolgten Änderungen aktualisiert.

    In der TabConfigurationEditorPart-Klasse legt die überschriebene ApplyChanges-Methode die TabList-Eigenschaft für das Webpart auf diejenige im EditorPart fest.

    HinweisHinweis

    Die Methode ruft die SaveChanges-Methode des Webbrowsers auf, um das Webpart über die Änderung an der Webparteigenschaft TabList zu benachrichtigen.

    public override bool ApplyChanges()
    {
      this.tabEditorWebPart = this.WebPartToEdit as TabEditorWebPart;
    
      // Set the Web Part's TabList.
      this.tabEditorWebPart.TabList = this.TabList;
    
      // Call the Web Part's personalization dirty.
      this.tabEditorWebPart.SaveChanges();
      return true;
    }
    
  2. Die SyncChanges-Methode muss die Logik zum Lesen der Werte der Webparteigenschaften aus dem Webpart enthalten. Die EditorPart-Klasse nutzt diese Werte zum Laden des Status seiner untergeordneten Steuerelemente, wenn das Webpart in den Bearbeitungsmodus wechselt.

    In der TabConfigurationEditorPart-Klasse liest die überschriebene SyncChanges-Methode die TabList-Eigenschaft für das Webpart und weist sie der TabList-Eigenschaft für das EditorPart zu.

    public override void SyncChanges()
    {
      // Sync with the new property changes here.
      EnsureChildControls();
    
      this.tabEditorWebPart = this.WebPartToEdit as TabEditorWebPart;
    
      // Read the TabList from the Web Part.
      this.TabList = this.tabEditorWebPart.TabList;
    }
    

TabConfigurationEditorPartUserControl-Klasse

Das Benutzersteuerelement stellt die Schnittstelle bereit, um Benutzern das Hinzufügen neuer sowie das Bearbeiten und Löschen vorhandener Registerkarten zu erlauben. Es erzwingt ferner verschiedene Gültigkeitsprüfungen für die Registerkarten. Der Titel der Registerkarte muss angegeben werden, da zwei Registerkarten nicht denselben Titel haben dürfen.

Das Benutzersteuerelement zeigt außerdem Änderungen an der TabList-Eigenschaft sofort im Webpart an, indem die aktualisierte TabList-Eigenschaft an das Webpart übergeben wird. Wenn im Toolbereich Bearbeiten auf die Schaltfläche Abbrechen geklickt wird, werden diese Änderungen rückgängig gemacht. Nachfolgend werden das Markup und der Code hinter dem Benutzersteuerelement erläutert.

Die ASCX-Datei, die das Markup enthält, dient zum Deklarieren der Benutzeroberfläche und Steuerelemente für die Gültigkeitsprüfung für das Benutzersteuerelement und weist zwei Steuerelemente für Bereiche auf:

  • Der Bereich panelConfiguredTabs enthält eine Dropdownliste mit den Titeln der vorhandenen Registerkarten sowie drei Schaltflächen zum Hinzufügen, Bearbeiten und Löschen einer Registerkarte. Jede Schaltfläche enthält die entsprechenden Ereignishandler.

  • Der Bereich panelTabItemist standardmäßig ausblendet und wird eingeblendet, wenn der Benutzer versucht, eine Registerkarte hinzuzufügen oder zu bearbeiten. Dieser Bereich enthält Textfelder für den Titel und Inhalt der Registerkarte. Drei Schaltflächen sind deklariert: Speichern, Speichern nach Bearbeitung und Abbrechen. Die Schaltfläche Speichern wird angezeigt, wenn der Benutzer auf die Schaltfläche Neue Registerkarte hinzufügen klickt. Der dazugehörige Ereignishandler speichert die neue Registerkarte. Die Schaltfläche Speichern nach Bearbeitung wird angezeigt, wenn auf die Schaltfläche Bearbeiten geklickt wird. Die Schaltfläche Abbrechen wird nur sichtbar, wenn der Benutzer versucht, eine Registerkarte hinzuzufügen oder zu bearbeiten. Das Benutzersteuerelement deklariert außerdem zwei Steuerelemente für die Gültigkeitsprüfung: eine erforderliche Feldprüfung für das Textfeld Titel und eine benutzerdefinierte Prüfung, ob ein Titel mit demselben Namen bereits vorhanden ist.

Das Benutzersteuerelement deklariert außerdem ein ausgeblendetes Feld mit dem Namen hiddenFieldDetectRequest, das weiter unten in diesem Artikel unter So verarbeiten Sie das Seitenladeereignis erläutert wird. Das folgende Codebeispiel veranschaulicht das Erstellen der beiden Bereiche, Schaltflächen und Steuerelemente für die Gültigkeitsprüfung.

<%@ 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="TabConfigurationEditorPartUserControl.ascx.cs"
  Inherits="MSDN.SharePoint.Samples.TabConfigurationEditorPartUserControl, 
            MSDN.SharePoint.Samples, 
            Version=1.0.0.0, 
            Culture=Neutral, 
            PublicKeyToken=3aae0e8a62e006af" %>
<asp:HiddenField runat="server" ID="hiddenFieldDetectRequest" Value="0" />
<div style="width: 250px">
  <table cellpadding="5px" cellspacing="5px">
    <tr>
      <td>
        <fieldset title="Configured Tabs">
          <legend>Configured Tabs</legend>
          <asp:Panel ID="panelConfiguredTabs" runat="server">
            <table cellpadding="5px" cellspacing="5px">
              <tr style="padding-top: 5px; padding-bottom: 5px">
                <td>
                  <asp:Label 
                    runat="server" 
                    ID="labelConfiguredTabs" 
                    Text="Tab list:"></asp:Label>
                </td>
                <td colspan="2" align="right">
                  <asp:DropDownList 
                    ID="dropDownConfiguredTabs" 
                    runat="server" 
                    EnableViewState="true"
                    AutoPostBack="true" 
                    OnTextChanged="dropDownConfiguredTabs_OnTextChanged">
                    <asp:ListItem Text="Select one" Value="Select one"></asp:ListItem>
                  </asp:DropDownList>
                </td>
              </tr>
              <tr style="padding-top: 5px">
                <td align="center">
                  <asp:Button 
                    runat="server" 
                    ID="buttonAddNewTab" 
                    Text="Add New" 
                    OnClick="ButtonAddNewTab_OnClick"
                    CausesValidation="false" />
                </td>
                <td align="center">
                  <asp:Button 
                    runat="server" 
                    ID="buttonEditTab" 
                    Text="Edit" 
                    OnClick="ButtonEditTab_OnClick"
                    CausesValidation="false" />
                </td>
                <td align="center">
                  <asp:Button 
                    runat="server" 
                    ID="buttonDeleteTab" 
                    Text="Delete" 
                    OnClick="ButtonDeleteTab_OnClick"
                    CausesValidation="false" />
                </td>
              </tr>
            </table>

          </asp:Panel>
        </fieldset>
      </td>
    </tr>
    <tr>
      <td>
        <asp:Panel ID="panelTabItem" runat="server" Visible="false">
          <fieldset title="Tab Data" runat="server" id="fieldSetTitle">
            <legend runat="server" id="legendTitle">Tab Data</legend>
            <table>
              <tr>
                <td>
                  <asp:Label ID="labelName" Text="Title:" runat="server"></asp:Label>
                </td>
                <td>
                  <asp:TextBox ID="textBoxTitle" runat="server" MaxLength="20"></asp:TextBox>
                  <asp:Label runat="server" ForeColor="Red" Text="*" />
                </td>
              </tr>
              <tr>
                <td>
                  &nbsp;
                </td>
                <td>
                  <asp:RequiredFieldValidator 
                    runat="server" 
                    ControlToValidate="textBoxTitle" 
                    ErrorMessage="Title is required."
                    ID="requiredFieldValidatorTextBoxTitle" 
                    EnableClientScript="true"></asp:RequiredFieldValidator>
                  <br />
                  <asp:CustomValidator 
                    runat="server" 
                    ControlToValidate="textBoxTitle" 
                    ErrorMessage="Tab with same Title already exists."
                    ID="customValidatorTextBoxTitle"></asp:CustomValidator>
                </td>
              </tr>
              <tr>
                <td>
                  <asp:Label 
                    ID="labelURL" 
                    Text="Content:" 
                    runat="server"></asp:Label>
                </td>
                <td>
                  <asp:TextBox 
                    ID="htmlBody" 
                    runat="server" 
                    TextMode="MultiLine" 
                    Rows="6" 
                    MaxLength="100"></asp:TextBox>
                </td>
              </tr>
              <tr>
                <td colspan="2" align="right">
                  <asp:Button 
                    runat="server" 
                    ID="buttonSave" 
                    Text="Save" 
                    OnClick="ButtonSave_Click"
                    CausesValidation="true" 
                    Visible="false" />
                  <asp:Button 
                    runat="server" 
                    ID="buttonCancel" 
                    Text="Cancel" 
                    OnClick="ButtonCancel_Click"
                    CausesValidation="false" />&nbsp;&nbsp;
                  <asp:Button 
                    runat="server" 
                    ID="buttonSaveOnEdit" 
                    Text="Save" 
                    OnClick="ButtonSaveOnEdit_Click"
                    CausesValidation="true" 
                    Visible="false" />
                </td>
              </tr>
            </table>

          </fieldset>
        </asp:Panel>
      </td>
    </tr>
  </table>

</div>

Die Datei .ascx.cs mit der Code-Behind-Datei enthält die Logik zum Speichern und Rückgängigmachen der an der Registerkartenliste erfolgten Änderungen. Die TabConfigurationEditorPartUserControl-Klasse in der Code-Behind-Datei deklariert Verweise auf die TabConfigurationEditorPart-Auflistung der TabData-Klassen.

Im folgenden Codebeispiel, das die von der Codedatei .ascx.cs verwendeten Namespaces enthält, werden mehrere Objekte für die TabConfigurationEditorPartUserControl-Klasse erstellt.

namespace MSDN.SharePoint.Samples
{
  using System;
  using System.Collections.Generic;
  using System.Linq;

  public partial class TabConfigurationEditorPartUserControl : System.Web.UI.UserControl
  {
    private TabConfigurationEditorPart parentEditorPart;
        
    public List<TabData> TabList;

    const string TabStorageViewStateId = "TabStorageViewState";   
  }
}

In den folgenden Abschnitten werden andere Methoden und Eigenschaften beschrieben, die die Klasse benötigt.

So verarbeiten Sie das Seitenladeereignis

  1. Die Page_Load-Methode ruft die aktuelle Gruppe von Registerkarten aus dem Webpartspeicher ab, indem die SyncChanges-Methode der EditorPart-Klasse aufgerufen wird.

    Nach Abrufen der Liste der Registerkarten müssen Sie die Registerkartentitel an das Steuerelement der Dropdownliste binden. Dies muss beim ersten Laden des Steuerelements erfolgen. Üblicherweise muss dazu die IsPostBack-Eigenschaft des Page-Steuerelements ausgewählt werden. Ist IsPostBack auf false festgelegt, wird die Seite erstmals geladen, und die anfängliche Datenbindung erfolgt gemäß dieser Bedingung. Doch die EditorPart-Steuerelemente werden erstmalig geladen, wenn der Benutzer auf das Menü Webparts ändern klickt oder die Seite in den Bearbeitungsmodus versetzt. Diese beiden Aktionen sind Postbacks, und die IsPostBack-Eigenschaft wäre auf true festgelegt. Auch alle nachfolgenden Aktionen für das EditorPart wären Postbacks, und die Eigenschaft bliebe true. Deshalb können Sie die Eigenschaft nicht für Logik verwenden, die beim ersten Laden des Steuerelements ausgeführt wird.

  2. Verwenden Sie als Umgehungslösung die hiddenFieldDetectRequest-Variable. Beim ersten Laden des Benutzersteuerelements hat es den Standardwert 0, und die Datenbindung erfolgt gemäß dieser Bedingung. Ferner wird der Wert auf 1 festgelegt, um die wiederholte Ausführung desselben Codes bei nachfolgenden Postbacks zu vermeiden. Der Code zum Speichern der Liste der Registerkarten im Ansichtsstatus wird gemäß derselben Bedingung ausgeführt, um die Abbruchfunktionalität zu aktivieren. Wenn der Benutzer im Toolbereich auf die Schaltfläche Abbrechen klickt, werden die Änderungen des Benutzers an den Registerkarten rückgängig gemacht. Die Registerkartenliste für das Webpart wird in diejenige zurückgesetzt, die im Ansichtsstatus gespeichert war, was im folgenden Codebeispiel gezeigt wird.

    protected void Page_Load(object sender, EventArgs e)
    {
      this.parentEditorPart = this.Parent as TabConfigurationEditorPart;
    
      // Call Sync Changes on the editor part, to read the tab list from the Web Part.
      this.parentEditorPart.SyncChanges();
      this.TabList = this.parentEditorPart.TabList;
    
      // Check whether this is the first Page_Load of the control.
      if (this.hiddenFieldDetectRequest.Value == "0")
      {
        this.hiddenFieldDetectRequest.Value = "1";
    
        // Save the original tab list to the control's ViewState.
        this.SaveOriginalTabListToViewState();
    
        // Bind the tab list to the drop-down.
        this.PopulateConfiguredTabsDropDown();
      }
    }
    
  3. Die SaveOriginalTabListToViewState-Methode speichert die Registerkartenliste im Ansichtsstatus des Benutzersteuerelements (siehe den folgenden Code).

    private void SaveOriginalTabListToViewState()
    {
      // Save the tab list that was already retrieved 
      // from the Web Part storage to the view state.
      if (this.TabList != null)
      {
        this.ViewState[TabStorageViewStateId] = this.TabList;
      }
    }
    
  4. Die PopulateConfiguredTabsDropDown-Methode führt die Datenbindung für die Dropdownliste aus. Die Bindung erfolgt, entweder wenn das Steuerelement erstmals geladen wird oder auf die Schaltflächen Speichern oder Speichern nach Bearbeitung geklickt wird. Bei jeder erfolgten Bindung wird das ausgewählte Element in der Dropdownliste auf den Standardwert Ein Element auswählen festgelegt. Die Methode deaktiviert also die Schaltflächen Bearbeiten und Löschen und blendet den Bereich Registerkartenelement aus.

    private void PopulateConfiguredTabsDropDown()
    {
      this.dropDownConfiguredTabs.Items.Clear();
      this.dropDownConfiguredTabs.Items.Add("Select one");
    
      // Add the Tab titles to the tab list drop-down.
      if (this.TabList != null)
      {
        for (int index = 0; index < TabList.Count; index++)
        {
          this.dropDownConfiguredTabs.Items.Add(TabList[index].Title.ToString());
        }
      }
    
      // Hide the Edit and Delete buttons, and tab panel.
      this.buttonDeleteTab.Enabled = false;
      this.buttonEditTab.Enabled = false;
      this.panelTabItem.Visible = false;
    }
    
  5. Die OriginalTabList-Eigenschaft gibt die im Ansichtsstatus gespeicherte Liste der Registerkarten zurück.

    public List<TabData> OriginalTabList
    {
      get
      {
        // Retrieve the original tab list from the ViewState.
        List<TabData> retValue = null;
        retValue = this.ViewState[TabStorageViewStateId] as List<TabData>;
        return retValue;
      }
    }
    

So verarbeiten Sie das Änderungsereignis in der Dropdownliste der Registerkartenliste

  • Dieser Ereignishandler verarbeitet die Änderung der Dropdownliste der Registerkartenliste und legt den Status der Schaltflächen Bearbeiten und Löschen im Bereich Registerkartenelement gemäß dem in der Dropdownliste ausgewählten Wert fest. Wenn der ausgewählte Wert Ein Element auswählen ist, werden die Schaltflächen deaktiviert und der Bereich ausgeblendet (siehe das folgende Codebeispiel).

    protected void dropDownConfiguredTabs_OnTextChanged(object sender, EventArgs e)
    {
      this.panelTabItem.Visible = false;
    
      // Enable the Edit and Delete buttons if any tab is selected in the drop-down list.
      if(dropDownConfiguredTabs.SelectedIndex == 0)
      {
        this.buttonDeleteTab.Enabled = false;
        this.buttonEditTab.Enabled = false;
      }
      else
      {
        this.buttonDeleteTab.Enabled = true;
        this.buttonEditTab.Enabled = true;
      }
    }
    

So verarbeiten Sie die Klickereignisse für die Schaltflächen "Hinzufügen", "Bearbeiten" und "Löschen"

  1. Der Ereignishandler für den Klick auf die Schaltfläche Neu hinzufügen zeigt den Bereich Registerkartenelement und die Schaltfläche Speichern an, leert die Textfeld Titel und Inhalt und blendet die Schaltfläche Speichern nach Bearbeitung aus (siehe das folgende Codebeispiel).

    protected void ButtonAddNewTab_OnClick(object sender, EventArgs e)
    {
      // Show the panel and clear title and content.
      this.panelTabItem.Visible = true;
      this.textBoxTitle.Text = string.Empty;
      this.htmlBody.Text = string.Empty;
      this.buttonSave.Visible = true;
      this.buttonSaveOnEdit.Visible = false;
    }
    
  2. Der Ereignishandler für den Klick auf die Schaltfläche Bearbeiten zeigt das Feld Registerkartenelement und die Schaltfläche Speichern nach Bearbeitung an, legt die Wert der Textfelder Titel und Inhalt auf die Werte der ausgewählten Registerkarte fest und blendet die Schaltfläche Speichern aus.

    protected void ButtonEditTab_OnClick(object sender, EventArgs e)
    {
      // Hide the Save button and Show the SaveOnEdit button.
      this.buttonSave.Visible = false;
      this.buttonSaveOnEdit.Visible = true;
    
      // Show the tab panel.
      this.panelTabItem.Visible = true;
    
      // Find the tab selected to Edit, and set the Title and Content text box values.
      TabData selectedLink = this.TabList.First(tab => tab.Title == this.dropDownConfiguredTabs.SelectedItem.Text);
      this.textBoxTitle.Text = selectedLink.Title;
      this.htmlBody.Text = selectedLink.Content;
    }
    
  3. Der Ereignishandler für die Schaltfläche Löschen entfernt die ausgewählte Registerkarte aus der Registerkartenliste, führt eine erneute Bindung für die Dropdownliste der Registerkartenliste durch und ruft die ApplyChanges-Methode auf, damit die Änderungen vom Webpart übernommen werden.

    protected void ButtonDeleteTab_OnClick(object sender, EventArgs e)
    {
      // Remove the title from the drop-down list.
      this.TabList.RemoveAll(tab => tab.Title == this.dropDownConfiguredTabs.SelectedItem.Text);
    
      // Re-bind the drop-down list.
      this.PopulateConfiguredTabsDropDown();
    
      // Apply the changes to the Web Part.
      this.ApplyChanges();
    }
    

So verarbeiten Sie die Klickereignisse für die Schaltflächen "Speichern", "Speichern nach Bearbeitung" und "Löschen"

  1. Im folgenden Code prüft der Ereignishandler für die Schaltfläche Speichern, ob bereits eine Registerkarte mit demselben Titel vorhanden ist. Ist dies der Fall, tritt bei der Gültigkeitsprüfung ein Fehler auf. Ist dies nicht der Fall, wird eine neue Registerkarte erstellt und der Registerkartenliste hinzugefügt. Der Code führt eine erneute Bindung für die Dropdownliste durch und ruft die ApplyChanges-Methode auf, damit die Änderungen vom Webpart übernommen werden.

    protected void ButtonSave_Click(object sender, EventArgs e)
    {
      // Check whether a tab with same title already exists.
      IEnumerable<TabData> matches = this.TabList.Where(tab => (tab.Title == this.textBoxTitle.Text));
    
      if (matches.Count() > 0)
      {
        // Fail the validation if a tab with the same title already exists.
        this.customValidatorTextBoxTitle.IsValid = false;
      }
      else
      {
        // If no tab exists with the same title, save and apply the changes.
        this.SaveTab();
        this.PopulateConfiguredTabsDropDown();
        this.ApplyChanges();
      }
    }
    
  2. Der Ereignishandler für die Schaltfläche Speichern nach Bearbeitung prüft zunächst, ob der bearbeitete Titel der ausgewählten Registerkarte bereits in der Dropdownliste vorhanden ist. Falls ja, tritt bei der Gültigkeitsprüfung ein Fehler auf. Falls der Titel nicht bearbeitet wurde, wird die ausgewählte Registerkarte aus der Registerkartenliste entfernt, eine neue Registerkarte mit dem Titel und Inhalt erstellt und der Registerkartenliste hinzugefügt. Ferner wird für die Dropdownliste der Tabellenliste eine erneute Bindung durchgeführt und die ApplyChanges-Methode aufgerufen, damit die Änderungen vom Webpart übernommen werden.

    protected void ButtonSaveOnEdit_Click(object sender, EventArgs e)
    {
    
      // If the selected item's text in the tab list drop-down is not equal
      // to the value in the Title text box, the title has been modified. 
      // Check whether the modified title already exists.
      if((this.dropDownConfiguredTabs.SelectedItem.Text != this.textBoxTitle.Text) &&
       (this.TabList.Where(tab => tab.Title == this.textBoxTitle.Text).Count() > 0 ))
      {
    
        // If the edited title of the existing tab matches an already existing one, fail the validation.
        this.customValidatorTextBoxTitle.IsValid = false;
      }
      else
      {
    
        // If the title wasn't edited, remove the existing tab.
        // This line doesn’t do anything if a tab with the edited title doesn't already exist.
        this.TabList.RemoveAll(link => link.Title == this.dropDownConfiguredTabs.SelectedItem.Text);
    
        // Create a new tab with the edited title and content, and add it to the collection.
        this.SaveTab();
    
        // Rebind the drop-down list.
        this.PopulateConfiguredTabsDropDown();
    
        // Call Apply Changes to display the changes on the Web Part.
        this.ApplyChanges();
      }
    }
    
  3. Der Ereignishandler der Schaltfläche Abbrechen blendet lediglich den Bereich Registerkartenelement aus.

    protected void ButtonCancel_Click(object sender, EventArgs e)
    {
      // Hide the tab panel.
      this.panelTabItem.Visible = false;
    }    
    
  4. Die Hilfsmethode SaveTab erstellt eine neue Registerkarte anhand des aktuell eingegebenen Titels und Inhalts und fügt diese der Registerkartenliste hinzu.

    private void SaveTab()
    {
      // Create a new tab, and save it to the tab list collection.
      TabData tab = new TabData();
      tab.Title = this.textBoxTitle.Text;
      tab.Content = this.htmlBody.Text;
      this.TabList.Add(tab);
    }
    
  5. Die ApplyChanges-Methode ruft die ApplyChanges-Methode des EditorParts auf, das die Änderungen auf das Webpart anwendet.

    private void ApplyChanges()
    {
      // Call the ApplyChanges method of the parent editor part class.
      this.parentEditorPart.ApplyChanges();
    }
    

Bereitstellen der SharePoint-Webpart-Editor-Lösung

Klicken Sie zum Bereitstellen der Lösung in Visual Studio im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und klicken Sie dann auf Bereitstellen.Das Lösungspaket wird der SharePoint-Farm von Visual Studio bereitgestellt.

Erstellen Sie eine Webparts-Seite, und fügen Sie das Webpart der Seite hinzu.

Schlussbemerkung

In diesem Artikel wurden das SharePoint 2010-Webpartsystem und das Erstellen eines benutzerdefinierten Webpart-Editors behandelt. Entwickler sind nicht auf die Standardoberfläche beschränkt, die vom Webpartsystem für die Webparteigenschaften gerendert wird. Sie können zur Erfüllung nahezu beliebiger Projektanforderungen die Oberfläche anpassen.

Weitere Ressourcen

Weitere Informationen finden Sie in den folgenden Ressourcen: