Crear un editor de elementos web personalizados en SharePoint 2010

SharePoint 2010

Resumen:  obtenga más información sobre el Microsoft SharePoint 2010 marco de trabajo de elementos web y sobre cómo crear un editor de elementos web personalizado en SharePoint 2010. Puede usar los elementos de editor personalizados para ofrecer a los usuarios una funcionallidad que se puede conseguir mediante los ASP.NET controles de usuario.

El marco de trabajo de elementos web Microsoft SharePoint 2010 permite a los usuarios configurar un elemento web mediante propiedades de elemento web. Se proporciona una interfaz de usuario (IU) predeterminada para cada propiedad de elemento web que se expone al usuario en el panel Herramienta de edición del elemento web. Por ejemplo, una propiedad del tipo String se representa como un cuadro de texto y un Enum se representa como un cuadro de lista desplegable.

Esta representación predeterminada que realiza el marco de trabajo no permite un grado elevado de personalización porque el usuario no puede controlar los controles que se representan. Por ejemplo, tiene las siguientes limitaciones:

  • Control mediante la IU: Los tipos numéricos y de cadena se representan como cuadros de texto, los tipos enumeration se representan como un cuadro de lista desplegable y los tipos Boolean se representan como casillas. Así pus, no puede mostrar un tipo enumeration como botones de radio en lugar de un cuadro de lista desplegable.

  • Eventos: los eventos que generan los controles no se pueden controlar; por ejemplo, no puede habilitar o deshabilitar una lista desplegable basada en la selección de una casilla.

  • Validación: si la entrada del usuario se debe validar, el marco de trabajo no proporciona una manera de conectar un control de validación Microsoft ASP.NET al control de entrada que se genera. Por ejemplo, no puede validar una entrada de cadena para una dirección de correo electrónico válida mediante un control de validación RegEx ASP.NET.

Puede superar estas limitaciones si usa elementos de editor personalizados. Con los elementos de editor personalizados, puede ofrecer a los usuarios la funcionalidad que se puede conseguir mediante los controles de usuario ASP.NET. Un elemento web puede implementar elementos de editor personalizados que se pueden cargar cuando el elemento web está en modo de edición, exponer una IU personalizada, controlar eventos y validar entradas. Un elemento web puede tener más de un elemento de editor personalizado asociado.

En este artículo se describe el marco de trabajo de elementos web SharePoint 2010 en detalle y proporciona un código de ejemplo para mostrar cómo se crea un editor de elementos web personalizados en SharePoint 2010. En primer lugar, examine el marco de trabajo que habilita los elementos de editor personalizados.

Existen dos tipos básicos para desarrollar los elementos de editor personalizados: la interfaz IWebEditable y la clase EditorPart.

Interfaz IWebEditable

Puede usar la interfaz IWebEditable para especificar controles de edición personalizada asociados a un control WebPart. La clase de base WebPart ya lo implementa y las clases derivadas deben reemplazar la implementación de la base. En la tabla 1 se indican los miembros que se deben reemplazar.

Tabla 1. Miembros IWebEditable

Miembro

Descripción

object WebBrowsableObject { get; }

La propiedad mediante la cual el control EditorPart obtiene una referencia al elemento web que se está editando.

EditorPartCollection CreateEditorParts();

Este método devuelve la colección de controles EditorPart asociados al elemento web.

Clase EditorPart

La clase EditorPart sirve como base para una clase derivada que proporciona una IU personalizada en el panel Herramienta de edición de un elemento web. La clase derivada debe reemplazar a los miembros indicados en la tabla 2.

Tabla 2. Miembros EditorPart

Miembro

Descripción

public abstract bool ApplyChanges();

Este método aplica los cambios que se realizan en el control EditorPart sobre el elemento web.

public abstract void SyncChanges();

El elemento web almacena los valores proporcionados por el usuario. Este método recupera los valores del elemento web cuando están listos en lo que respecta al editor.

En esta sección se usa un escenario de ejemplo para describir cómo crear un elemento web personalizado que contenga un elemento de editor personalizado.

El escenario supone la creación de un elemento web que muestra un conjunto de fichas al usuario. Cada ficha contiene un título y contenido, ambos especificados por el usuario. Al hacer clic en el título se muestra el contenido correspondiente. El elemento web permite al usuario agregar, editar y eliminar fichas usando un elemento de editor.

En la figura 1 se muestra el elemento web en el modo de edición.

Figura 1. Elemento web de editor de fichas en modo de edición

Pestaña Elemento web Editor en modo de edición

Requisitos de software para el elemento de editor personalizado en un escenario de SharePoint 2010

Para este escenario, debe tener el siguiente software instalado en el equipo:

  • Microsoft SharePoint Server 2010

  • Microsoft Visual Studio 2010

Siga estos pasos para crear la solución en Visual Studio 2010.

Para crear una solución de elementos web en Visual Studio

  1. En Visual Studio 2010, haga clic en Nuevo proyecto, expanda el nodo SharePoint, haga clic en 2010 y, a continuación, haga clic en Proyecto de SharePoint vacío. Asigne al proyecto el nombre EditorPartTab y, a continuación, haga clic en Aceptar.

  2. Agregue al proyecto dos clases con los nombres TabData y TabConfigurationEditorPart.

  3. Agregue al proyecto un elemento web visual con el nombre TabEditorWebPart. De este modo se agrega al proyecto una clase con el nombre TabEditorWebPart y un control de usuario con el nombre TabEditorWebPartUserControl.

  4. Cambie el nombre TabEditorWebUserControl por el de TabConfigurationEditorPartUserControl.

    Nota Nota

    Asegúrese de que también se cambie el nombre de clase del control de usuario de TabConfigurationEditorPartUserControl.ascx.cs, y no solo el nombre del archivo.

  5. Cambie el valor del atributo Inherits de la directiva Control del archivo de código TabConfigurationEditorPartUserControl.ascx, según el nuevo nombre de clase.

  6. Guarde todos los archivos, asegúrese de que el nombre de clase del archivo de código TabConfigurationEditorPartUserControl.ascx.designer.cs sea TabConfigurationEditorPartUserControl.

Los siguientes son los componentes que ha agregado al proyecto:

  • Clase TabData: clase de entidad que representa una ficha.

  • Clase TabEditorWebPart: clase de elemento web personalizado para visualizar las fichas.

  • Clase TabConfigurationEditorPart: clase de elemento de editor para exponer la funcionalidad para crear, editar y eliminar fichas.

  • Clase TabConfigurationEditorPartUserControl: un control de usuario para hospedar la interfaz. Se carga mediante la clase TabConfigurationEditorPart.

En las siguientes secciones se describe detalladamente el código y la funcionalidad de cada uno de estos componentes.

Clase TabData

La clase TabData es una clase de entidad que contiene dos propiedades: la propiedad Title y la propiedad Content. Title es el nombre de la ficha y Content es el contenido que se muestra al hacer clic en la ficha.

La clase se marca con el atributo Serializable porque se declara una colección de objetos de esta clase en la clase TabEditorWebPart como propiedad, para almacenar la lista de fichas.

El siguiente código muestra la clase TabData, que define dos propiedades para el título y el contenido.

namespace MSDN.SharePoint.Samples
{
    using System;

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


Clase TabEditorWebPart

El elemento web muestra una colección de fichas. La clase TabEditorWebPart ya debe estar heredando de la clase WebPart. Ek elemento web declara una variable privada _tabList como una colección de objetos TabData. Esta colección se ajusta mediante la propiedad TabList. La propiedad devuelve una colección vacía si _tabList es nulo. La propiedad también se marca como Personalizable para permitir que los usuarios personalicen las fichas.

El elemento web también declara una variable privada _divTabContent del tipo HtmlGenericControl para mostrar el contenido de la ficha seleccionada, tal como se muestra en el siguiente ejemplo de código.

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;
            } 
        }       
    }
}


Para implementar la interfaz IWebEditable

  1. Tal como se explicaba anteriormente, el elemento web debe invalidar los miembros de la interfaz IWebEditable. La propiedad WebBrowsableObject se invalida para devolver una referencia a la instancia TabEditorWebPart, tal como se muestra en el siguiente ejemplo.

    public override object WebBrowsableObject
    {
      // Return a reference to the Web Part instance.
      get { return this; }
    }
    
    
    
  2. El método CreateEditorParts se invalida para devolver una colección de objetos TabConfigurationEditorPart. En este caso, la colección contiene solo un objeto.

    NotaNota

    El Id. de cada elemento de editor de la página debe ser único, de modo que debe anteponer al Id. del EditorPart el Id. del elemento web.

    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);
    }
    
    
    

Para crear los controles y controladores de eventos

  1. El método CreateChildControls representa TabList como un control de menú ASP.NET. Si el número de fichas es superior a cero, se muestra el título y el contenido de la primera ficha. Si el número de fichas no es superior a cero, aparece un mensaje que indica al usuario que vaya al modo de edición y agregue filas. El método también registra un controlador de eventos para controlar el clic en una ficha, tal como se muestra en este ejemplo de código.

    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. El controlador de eventos TabMenu_MenuItemClick controla el clic del título de una ficha para mostrar el contenido correspondiente, tal como se muestra el el siguiente código.

    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;
    }
    
    
    

El método SaveChanges está pensado para que se llame desde la clase EditorPart. Este método llama al método SetPersonalizationDirty de la clase WebPart, que establece una marca que indica al elemento web que las propiedades del elemento web se han cambiado desde fuera de la clase. Si no se establece, los cambios realizados a las propiedades del elemento web desde fuera de la clase no tendrán efecto.

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();
}

Clase TabConfigurationEditorPart

La clase TabConfigurationEditorPart proporciona la funcionalidad para agregar, crear y editar las fichas. El TabConfigurationEditorPart debe heredarse de la clase EditorPart.

Todos los controles necesarios para habilitar esta funcionalidad se pueden declarar como controles secundarios en la propia clase EditorPart. Se ha creado el TabConfigurationEditorPartUserControl y se han declarado en él todos los controles secundarios necesarios. El control de usuarios lo carga el elemento de editor.

La clase declara variables de referencia al elemento web y el control de usuarios, y declara una colección de TabList de la clase TabData. La colección de TabList actúa como intermediaria para sincronizar los cambios entre el control de usuarios y el elemento web. El siguiente código demuestra la clase TabConfigurationEditorPart, que proporciona la funcionalidad para agregar, crear y editar las fichas.

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; }        
    }
}

Para crear los contorles y los controladores de eventos

  1. El EditorPart invalida el método CreateChildControls de la clase base para cargar el control de usuarios y agregarlo a la colección de controles secundarios del EditorPart. El método también registra un controlador de eventos para controlar el evento cuando se haga clic en el botón Cancelar del panel de herramientas. El control de usuarios contiene ciertas validaciones y estas validaciones no son deseadas cuando se hace clic en el botón Cancelar del panel de herramientas. De este modo, el método CreateChildControls deshabilita las validaciones para el botón Cancelar.

    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. El método Cancel_Click habilita la funcionalidad para deshacer los cambios que se han realizado en el TabList mientras se edita el elemento web. Esto se hace estableciendo la propiedad TabList del elemento web en la de OriginalTabList desde el control de usuarios.

    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();
      }
    }
    
    

Para invalidar los miembros de EditorPart

  1. El método ApplyChanges recibe la llamada del Microsoft .NET Framework al hacer clic en el botón Aceptar del panel de herramientas. En ese momento debe escribir cualquier código que actualice el elemento web de acuerdo con los cambios que se realicen en el elemento de editor.

    En la clase TabConfigurationEditorPart, el método invalidado ApplyChanges establece la propiedad TabList del elemento web en la del elemento de editor.

    NotaNota

    El método llama al método SaveChanges del elemento web para notificar al elemento web el cambio a la propiedad del elemento web TabList.

    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. El método SyncChanges debe contener la lógica para leer los valores de las propiedades del elemento web desde el elemento web. La clase EditorPart usa estos valores para cargar el estado de sus controles secundarios cuando el elemento web entra en modo de edición.

    En la clase TabConfigurationEditorPart, el método invalidado SyncChanges lee la propiedad TabList del elemento web y la asigna a la TabList en el elemento de editor.

    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;
    }
    
    

Clase TabConfigurationEditorPartUserControl

El control de usuarios proporciona la interfaz para permitir que los usuarios agreguen fichas nuevas y editen y eliminen fichas existentes. También aplica determinadas validaciones en las fichas. El título de la ficha es necesario y dos fichas no pueden tener el mismo título.

El control de usuarios también muestra cualquier cambio que se realice en la TabList inmediatamente en el elemento web, pasando la TabList actualizada al elemento web. Al hacer clic en el botón Cancelar del panel Herramienta de edición, estos cambios se deshacen. A continuación se explica el marcado y el código que subyacen tras el control de usuarios.

El archivo .ascx que contiene el marcado declara la IU y los controles de vallidación para el control de usuarios. Tiene dos controles de panel:

  • El panel panelConfiguredTabs contiene una lista desplegable que muestra los títulos de las fichas existentes. También contiene tres botones, un botón cada uno para agregar, editar y eliminar una ficha. Cada botón contiene los controladores de eventos respectivos.

  • De manera predeterminada, el panel panelTabItem está oculto y se vuelve visible cuando el usuario intenta agregar o editar una ficha. Contiene cuadros de texto para el título y el contenido de la ficha. Se declaran tres botones: Guardar, Guardar al editar y Cancelar. El botón Guardar está visible cuando el usuario hace clic en el botón Agregar nueva ficha y el controlador de eventos correspondiente guarda la nueva ficha. El botón Guardar al editar está visible al hacer clic en el botón Editar. Asimismo, el botón Cancelar solo está disponible cuando el usuario intenta agregar o editar una ficha. Además, el control de usuarios declara dos controles de validación: un validador de campo necesario en el cuadro de texto Título y un validador predeterminado para comprobar si ya existe un título con el mismo nombre.

El control de usuarios también declara un campo oculto con el nombre hiddenFieldDetectRequest, lo cual se explica en Para controlar el evento de carga de páginas, más adelante en este artículo. El siguiente ejemplo de código muestra cómo crear dos paneles, botones y controles de validación.

<%@ 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>


El archivo .ascx.cs que contiene el código subyacente contiene la lógica para guardar y deshacer los cambios que se realicen en la lista de fichas. La clase TabConfigurationEditorPartUserControl del archivo del código subyacente declara referencias a la colección TabConfigurationEditorPart de las clases TabData.

El siguiente exémplo de código muestra los espacios de nombres que usa el archivo de código.ascx.cs y crea varios objetos para la clase TabConfigurationEditorPartUserControl.

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";   
  }
}

En las siguientes secciones se describen otros métodos y propiedades que necesita la clase.

Para controlar el evento de carga de páginas

  1. El método Page_Load recupera el conjunto actual de fichas desde el almacenamiento de elementos web llamando al método SyncChanges de la clase EditorPart.

    Tras recuperar la lista de fichas, debe enlazar los títulos de fichas con el control de listas desplegables. Esto se debe hacer la primera vez que se cargue el control. Tradicionalmente, esto se hace seleccionando la propiedad IsPostBack del control de páginas. Si la propiedad IsPostBack es falsa, la página se carga por primera vez y el enlace de datos inicial se realiza en esa condición. Pero los controles de elementos de editor se cargan por primera vez cuando el usuario hace clic en el menú Modificar elemento web del elemento web o lleva la página al modo de edición. Estas dos acciones son postbacks, y la propiedad IsPostBack sería true. Todas las acciones posteriores por parte del editor serían postbacks, y la propiedad seguiría siendo true. Por lo tanto, no puede usar esta propiedad para que se ejecute ningúna lógica en la primera carga del control.

  2. Para solucionar esto, use la variable hiddenFieldDetectRequest. La primera vez que se carga el control de usuarios, tiene un valor predeterminado de 0 y el enlace de datos se realiza en esta condición. Además, el valor se establece en 1 para evitar la ejecución repetida del mismo código en postbacks posteriores. El código para guardar la lista de fichas en el estado de vista se ejecuta en la misma condición, para habilitar la funcionalidad de cancelación. Cuando el usuario hace clic en el botón Cancelar del panel de herramientas, se deshacen los cambios que ha hecho el usuario sobre las fichas: la lista de fichas del elemento web se restaura con la que estaba almacenada en el estado de vista. Esto se demuestra en el siguiente ejemplo de código.

    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. El método SaveOriginalTabListToViewState guarda la lista de fichas en el estado de vista del contorl de usuarios, tal como se muestra en el siguiente código.

    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. El método PopulateConfiguredTabsDropDown realiza el enlace de datos para la lista desplegable. El enlace se realiza la primera vez que se carga el control o al hacer clic en los botones Guardar o Guardar al editar. Cada vez que se realiza el enlace, el elemento seleccionado de la lista desplegable se establece en el valor predeterminado Seleccione uno. Así pues, el método deshabilita los botones Editar y Eliminar y oculta el panel Elemento de ficha.

    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. La propiedad OriginalTabList devuelve la lista de fichas guardadas en el estado de vista.

    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;
      }
    }
    
    

Para controlar el evento de cambio de desplegable en la lista de la ficha

  • Este controlador de eventos controla el cambio en el desplegable de la lista de le ficha. Establece el estado de los botones Editar y Eliminar en el panel Elemento de ficha según el valor de desplegable seleccionado. Los botones se deshabilitan y el panel se oculta cuando el valor seleccionado es Seleccione uno, tal como se muestra en el siguiente ejemplo de código.

    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;
      }
    }
    
    

Para controlar los eventos de clic de los botones Agregar, Editar y Eliminar

  1. El controlador de eventos para el botón Agregar nuevo muestra el panel Elemento de ficha y el botón Guardar borra los cuadros de texto Título y Contenido, y oculta el botón Guarxdar al editar, tal como se muestra en el siguiente ejemplo.

    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. El controlador de eventos para el clic del botón Editar muestra el panel de elementos de ficha, y el botón Guardar al editar establece los valores de los cuadros de texto Título y Contenido en los valores de la ficha seleccionada y oculta el botón Guardar.

    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. El controlador de eventos para el botón Eliminar quita la ficha selccionada de la lista de fichas, vuelve a enlazar el desplegable de la lista de la ficha y llama al método ApplyChanges para que se apliquen los cambios en el elemento web.

    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();
    }
    
    

Para controlar los clics de los botones Guardar, Guardar al editar y Cancelar

  1. En el siguiente código, el controlador de eventos para el clic del botón Guardar comprueba si ya existe una ficha con el mismo título. Si ya existe una ficha con ese título, la validación no se realiza correctamente. Si no existe una ficha con el mismo título, se crea una nueva ficha y se agrega a la lista de fichas. A continaución, el código vuelve a enlazar la lista desplegable y llama al método ApplyChanges para que se apliquen los cambios en el elemento web.

    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. El controlador de eventos para el botón Guardar al editar comprueba primero si ya existe el título editado de la ficha seleccionada en la lista desplegable; en caso afirmativo, la validación no se realiza correctamente. Si el título no se ha editado, quita la ficha seleccionada de la lista de fichas, crea una ficha nueva usando el título y el contenido y la agrega a la lista de fichas. Asimismo, el desplegable de la lista de la ficha se vuelve a enlazar y se llama al método ApplyChanges para que se apliquen los cambios al elemento web.

    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. El controlador de eventos del botón Cancelar solo oculta el panel Elemento de ficha.

    protected void ButtonCancel_Click(object sender, EventArgs e)
    {
      // Hide the tab panel.
      this.panelTabItem.Visible = false;
    }    
    
    
    
  4. El método de la utilidad SaveTab crea una ficha nueva a partir del título y el contenido introducidos actualmente, y los agrega a la lista de la ficha.

    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. El método ApplyChanges llama al método ApplyChanges del editor, que aplica los cambios al elemento web.

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

Para implementar la solución, en Visual Studio, haga clic con el botón secundario en el proyecto en Explorador de soluciones y, a continuación, haga clic en Implementar. Visual Studio implementa el paquete de soluciones en la granja de servidores de SharePoint.

Cree un página de elementos web y agregue el elemento web a la página.

En este artículo se ha hablado del marco de trabajo del elemento web SharePoint 2010 y de cómo crear un editor de elementos web personalizados. Los desarrolladores limitados a la interfaz predeterminada que se representa mediante el marco de trabajo del elemento web para las propiedades del elemento web. Puede personalizar la interfaz para satisfacer casi cualqueir requisito del proyecto.

Mostrar: