Tutorial: Crear un tipo de campo personalizado

Última modificación: viernes, 25 de junio de 2010

Hace referencia a: SharePoint Foundation 2010

En este artículo
Configurar el proyecto
Crear la clase de regla de validación
Crear la clase de campos personalizados
Creación del control de representación de campo
Creación de la plantilla de representación de campo
Crear la definición de tipo de campo
Creación de la hoja de estilo XSLT
Crear y probar el tipo de campo personalizado
Diferencias entre la representación de campos para dispositivos móviles y la representación de campos para equipos

En este tema se ofrece una guía paso a paso para crear un tipo de campo personalizado. Creará un campo destinado a contener un número de libro estándar internacional (ISBN) de 10 dígitos.

Para obtener información general acerca de los pasos implicados en la creación de un tipo de campo personalizado y la definición de su representación, vea Procedimiento para crear un tipo de campo personalizado.

Requisitos previos

Microsoft Visual Studio 2010

Configurar el proyecto

Para configurar el proyecto de campos personalizado

  1. En Visual Studio, cree un Proyecto de SharePoint vacío. Conviértalo en una solución de conjunto o granja de servidores, en lugar de una solución de espacio aislado, y denomínelo ISBN_Field_Type.

  2. Haga clic con el botón secundario en el nombre del proyecto en el Explorador de soluciones y seleccione Propiedades.

  3. En la ficha Aplicación del cuadro de diálogo Propiedades, escriba Contoso.SharePoint.ISBN_Field_Type como el Nombre del ensamblado y Contoso.SharePoint como el Espacio de nombres predeterminado. Deje la Versión de .NET Framework de destino establecida en .NET Framework 3.5.

  4. Si el cuadro Plataformas de solución en el Menú estándar de Visual Studio no indica "Cualquier CPU" o "x64", abra la ficha Compilación y establezca el Destino de la plataforma en "Cualquier CPU" o "x64". Para obtener más información sobre cómo elegir, vea Procedimiento para establecer el marco de destino y CPU correctos.

  5. Haga clic en el botón Guardar todos los archivos de la barra de herramientas.

  6. Haga clic con el botón secundario en el nombre del proyecto en el Explorador de soluciones y seleccione Agregar | Nuevo elemento.

  7. En el cuadro de diálogo Agregar nuevo elemento, seleccione Visual C# | Código (o Visual Basic | Código) en el árbol Plantillas instaladas.

  8. Seleccione Clase en el cuadro Plantillas y escriba ISBN.Field.cs (o ISBN.Field.vb) en el cuadro Nombre. Haga clic en Agregar.

  9. Repita el paso anterior para crear una segunda clase, pero escriba ISBN.FieldControl.cs (o ISBN.FieldControl.vb) en el cuadro Nombre. Haga clic en Agregar.

  10. Agregue una tercera clase del mismo modo y escriba ISBN10ValidationRule.cs (o ISBN10ValidationRule.vb) en el cuadro Nombre. Haga clic en Agregar.

  11. En el Explorador de soluciones, haga clic con el botón secundario en el nombre del proyecto, seleccione Agregar y, a continuación, elija Carpeta asignada de SharePoint.

  12. Use el control de árbol que se abre para asignar la carpeta a TEMPLATE\ControlTemplates y haga clic en Aceptar.

  13. Haga clic con el botón secundario en la nueva carpeta ControlTemplates (no en el nombre del proyecto) en el Explorador de soluciones y seleccione Agregar | Nuevo elemento.

  14. En el cuadro de diálogo Agregar nuevo elemento, seleccione SharePoint | 2010 en el árbol Plantillas instaladas.

  15. Seleccione un Control de usuario de SharePoint en el cuadro Plantillas y asigne al archivo ascx el nombre ISBNFieldControl.ascx. Haga clic en Agregar. Visual Studio agregará automáticamente el archivo al manifiesto de la solución de SharePoint y lo establece para que se implemente en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\ControlTemplates. En este momento también agrega el ensamblado al manifiesto y lo establece para que se implemente en la memoria caché global de ensamblados (GAC).

    SugerenciaSugerencia

    Para agregar el Control de usuario, no haga clic con el botón secundario en el nombre del proyecto en el Explorador de soluciones. Cuando se agrega un Control de usuario de ese modo, Visual Studio lo coloca en una subcarpeta de TEMPLATE\ControlTemplates y, si no se mueve, Visual Studio lo implementa en una subcarpeta correspondiente de %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\ControlTemplates. Las plantillas de representación en las subcarpetas no se cargarán.

  16. Elimine los archivos ISBNFieldControl.ascx.cs y ISBNFieldControl.ascx.designer.cs (o los archivos ISBNFieldControl.ascx.vb y ISBNFieldControl.ascx.designer.vb) creados automáticamente en el archivo ISBNFieldControl.ascx. No son necesarios para este proyecto. El contenido predeterminado de ISBNFieldControl.ascx hace referencia al archivo ISBNFieldControl.ascx.cs (o ISBNFieldControl.ascx.vb) recién eliminado y, si crea el proyecto en este momento, el compilador le mostrará una advertencia sobre el archivo faltante. Pase por alto esta advertencia (el contenido predeterminado se cambiará en un paso posterior de este tema).

  17. En el Explorador de soluciones, haga clic con el botón secundario en el nombre del proyecto, seleccione Agregar y, a continuación, elija Carpeta asignada de SharePoint.

  18. Use el control de árbol que se abre para asignar la carpeta a TEMPLATE\XML y haga clic en Aceptar.

  19. Haga clic con el botón secundario en la nueva carpeta XML (no en el nombre del proyecto) en el Explorador de soluciones y seleccione Agregar | Nuevo elemento.

  20. En el cuadro de diálogo Agregar nuevo elemento, seleccione Visual C# | Datos (o Visual Basic | Datos) y, a continuación, Archivo XML en la ventana Plantillas.

  21. En el cuadro Nombre, escriba fldtypes_ISBNField.xml y haga clic en Agregar.

  22. En el Explorador de soluciones, haga clic con el botón secundario en el nombre del proyecto, seleccione Agregar y, a continuación, Carpeta asignada de SharePoint.

  23. Use el control de árbol que se abre para asignar la carpeta a TEMPLATE\LAYOUTS\XSL y haga clic en Aceptar.

  24. Haga clic con el botón secundario en la nueva carpeta XSL (no en el nombre del proyecto) en el Explorador de soluciones y seleccione Agregar | Nuevo elemento.

  25. En el cuadro de diálogo Agregar nuevo elemento, seleccione Visual C# | Datos (o Visual Basic | Datos) y, a continuación, Archivo XSLT en la ventana Plantillas.

  26. En el cuadro Nombre, escriba fldtypes_ISBNField.xsl y haga clic en Agregar. Tenga en cuenta que es muy similar al nombre del archivo anterior que ha creado. Los dos archivos tienen propósitos diferentes y se implementan en carpetas diferentes. Diferéncielos al trabajar en este tema.

  27. Haga clic con el botón secundario en el nodo Referencias en el Explorador de soluciones, haga clic en Agregar referencia y seleccione PresentationFramework.dll en la ficha .NET del cuadro de diálogo Agregar referencia. Haga clic en Aceptar. (Este ensamblado contiene la definición de la clase ValidationRule que se creará en el siguiente procedimiento).

Crear la clase de regla de validación

Para crear una clase de reglas de validación

  1. Abra el archivo ISBN10ValidationRule.cs (o ISBN10ValidationRule.vb) y agregue las siguientes instrucciones.

    using System.Text.RegularExpressions;
    using System.Windows.Controls;
    using System.Globalization;
    
    Imports System.Text.RegularExpressions
    Imports System.Windows.Controls
    Imports System.Globalization
    
  2. Cambie el espacio de nombres de modo que cumpla con las instrucciones descritas en el tema sobre las instrucciones de nomenclatura de espacios de nombres. En este tutorial, use Contoso.System.Windows.Controls.

  3. Reemplace la declaración de clase por el código siguiente.

    public class ISBN10ValidationRule : ValidationRule
    {
        private const Int32 ISBNMODULO = 11;
    
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            String iSBN = (String)value;
            String errorMessage = "";
    
            Regex rxISBN = new Regex(@"^(?'GroupID'\d{1,5})-(?'PubPrefix'\d{1,7})-(?'TitleID'\d{1,6})-(?'CheckDigit'[0-9X]{1})$");
    
            if (!rxISBN.IsMatch(iSBN))
            {
                errorMessage = "An ISBN must have this structure:\n1-5 digit Group ID, hyphen, \n1-7 digit Publisher Prefix, hyphen, \n1-6 digit Title ID, hyphen, \n1 Check Digit (which can be \"X\" to indicate \"10\").\n";
            }
    
            if (errorMessage == "") // Matched the RegEx, so check for group length errors.
            {
                Match mISBN = rxISBN.Match(iSBN);
                GroupCollection groupsInString = mISBN.Groups;
    
                String groupID = groupsInString["GroupID"].Value;
                String pubPrefix = groupsInString["PubPrefix"].Value;
    
                if ((groupID.Length + pubPrefix.Length) >= 9)
                {
                    errorMessage = "The Group ID and Publisher Prefix can total no more than 8 digits.\n";
                }
    
                String titleID = groupsInString["TitleID"].Value;
    
                if (((groupID.Length + pubPrefix.Length) + titleID.Length) != 9)
                {
                    errorMessage = errorMessage + "The Group ID, Publisher Prefix, and \nTitle ID must total exactly 9 digits.\n";
                }
    
                if (errorMessage == "") //No group length errors, so verify the check digit algorithm.
                {
                    Int32 checkDigitValue;
                    String checkDigit = groupsInString["CheckDigit"].Value;
    
                    // To ensure check digit is one digit, "10" is represented by "X".
                    if (checkDigit == "X")
                    {
                        checkDigitValue = 10;
                    }
                    else
                    {
                        checkDigitValue = Convert.ToInt32(checkDigit);
                    }
    
                    String iSBN1st3Groups = groupID + pubPrefix + titleID; //Concatenate without the hyphens.
    
                    // Sum the weighted digits.
                    Int32 weightedSum = (10 * Convert.ToInt32(iSBN1st3Groups.Substring(0, 1))) +
                                         (9 * Convert.ToInt32(iSBN1st3Groups.Substring(1, 1))) +
                                         (8 * Convert.ToInt32(iSBN1st3Groups.Substring(2, 1))) +
                                         (7 * Convert.ToInt32(iSBN1st3Groups.Substring(3, 1))) +
                                         (6 * Convert.ToInt32(iSBN1st3Groups.Substring(4, 1))) +
                                         (5 * Convert.ToInt32(iSBN1st3Groups.Substring(5, 1))) +
                                         (4 * Convert.ToInt32(iSBN1st3Groups.Substring(6, 1))) +
                                         (3 * Convert.ToInt32(iSBN1st3Groups.Substring(7, 1))) +
                                         (2 * Convert.ToInt32(iSBN1st3Groups.Substring(8, 1))) +
                                          checkDigitValue;
    
                    Int32 remainder = weightedSum % ISBNMODULO;  // ISBN is invalid if weighted sum modulo 11 is not 0.
    
                    if (remainder != 0)
                    {
                        errorMessage = "Number fails Check Digit verification.";
                    }
    
                    if (errorMessage == "") // Passed check digit verification. 
                    {
                        return new ValidationResult(true, "This is a valid ISBN.");
                    }// end check digit verification passed
    
                    else // the check digit verification failed
                    {
                        return new ValidationResult(false, errorMessage);
                    }
    
                }// end no group length errors
    
                else // There was some error in a group length
                {
                    return new ValidationResult(false, errorMessage);
                }
    
            }// end RegEx match succeeded
    
            else // There was a RegEx match failure
            {
                  return new ValidationResult(false, errorMessage);
            }
    
        }// end Validate method 
    
    }// end ISBN10ValidationRule class
    
    Public Class ISBN10ValidationRule
        Inherits ValidationRule
        Private Const ISBNMODULO As Int32 = 11
    
        Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As CultureInfo) As ValidationResult
            Dim iSBN As String = CType(value, String)
            Dim errorMessage As String = ""
    
            Dim rxISBN As New Regex("^(?'GroupID'\d{1,5})-(?'PubPrefix'\d{1,7})-(?'TitleID'\d{1,6})-(?'CheckDigit'[0-9X]{1})$")
    
            If Not rxISBN.IsMatch(iSBN) Then
                errorMessage = "An ISBN must have this structure:" & vbLf & "1-5 digit Group ID, hyphen, " & vbLf & "1-7 digit Publisher Prefix, hyphen, " & vbLf & "1-6 digit Title ID, hyphen, " & vbLf & "1 Check Digit (which can be ""X"" to indicate ""10"")." & vbLf
            End If
    
            If errorMessage = "" Then ' Matched the RegEx, so check for group length errors.
                Dim mISBN As Match = rxISBN.Match(iSBN)
                Dim groupsInString As GroupCollection = mISBN.Groups
    
                Dim groupID As String = groupsInString("GroupID").Value
                Dim pubPrefix As String = groupsInString("PubPrefix").Value
    
                If (groupID.Length + pubPrefix.Length) >= 9 Then
                    errorMessage = "The Group ID and Publisher Prefix can total no more than 8 digits." & vbLf
                End If
    
                Dim titleID As String = groupsInString("TitleID").Value
    
                If ((groupID.Length + pubPrefix.Length) + titleID.Length) <> 9 Then
                    errorMessage = errorMessage & "The Group ID, Publisher Prefix, and " & vbLf & "Title ID must total exactly 9 digits." & vbLf
                End If
    
                If errorMessage = "" Then 'No group length errors, so verify the check digit algorithm.
                    Dim checkDigitValue As Int32
                    Dim checkDigit As String = groupsInString("CheckDigit").Value
    
                    ' To ensure check digit is one digit, "10" is represented by "X".
                    If checkDigit = "X" Then
                        checkDigitValue = 10
                    Else
                        checkDigitValue = Convert.ToInt32(checkDigit)
                    End If
    
                    Dim iSBN1st3Groups As String = groupID & pubPrefix & titleID 'Concatenate without the hyphens.
    
                    ' Sum the weighted digits.
                    Dim weightedSum As Int32 = (10 * Convert.ToInt32(iSBN1st3Groups.Substring(0, 1))) + (9 * Convert.ToInt32(iSBN1st3Groups.Substring(1, 1))) + (8 * Convert.ToInt32(iSBN1st3Groups.Substring(2, 1))) + (7 * Convert.ToInt32(iSBN1st3Groups.Substring(3, 1))) + (6 * Convert.ToInt32(iSBN1st3Groups.Substring(4, 1))) + (5 * Convert.ToInt32(iSBN1st3Groups.Substring(5, 1))) + (4 * Convert.ToInt32(iSBN1st3Groups.Substring(6, 1))) + (3 * Convert.ToInt32(iSBN1st3Groups.Substring(7, 1))) + (2 * Convert.ToInt32(iSBN1st3Groups.Substring(8, 1))) + checkDigitValue
    
                    Dim remainder As Int32 = weightedSum Mod ISBNMODULO ' ISBN is invalid if weighted sum modulo 11 is not 0.
    
                    If remainder <> 0 Then
                        errorMessage = "Number fails Check Digit verification."
                    End If
    
                    If errorMessage = "" Then ' Passed check digit verification.
                        Return New ValidationResult(True, "This is a valid ISBN.") ' end check digit verification passed
    
                    Else ' the check digit verification failed
                        Return New ValidationResult(False, errorMessage)
                    End If
                    ' end no group length errors
    
                Else ' There was some error in a group length
                    Return New ValidationResult(False, errorMessage)
                End If
                ' end RegEx match succeeded
    
            Else ' There was a RegEx match failure
                Return New ValidationResult(False, errorMessage)
            End If
    
        End Function ' end Validate method
    
    End Class ' end ISBN10ValidationRule class
    

    La clase de reglas de validación que acaba de crear contiene toda la lógica de validación detallada. Si desea obtener más información acerca de las clases de reglas de validación, consulte System.Text.RegularExpressions y ValidationRule.

Crear la clase de campos personalizados

Para crear una clase de campos personalizados

  1. Abra el archivo ISBN.Field.cs (o ISBN.Field.vb).

  2. Agregue las siguientes instrucciones.

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.SharePoint.Security;
    
    using System.Windows.Controls;
    using System.Globalization;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    
    Imports Microsoft.SharePoint
    Imports Microsoft.SharePoint.WebControls
    Imports Microsoft.SharePoint.Security
    
    Imports System.Windows.Controls
    Imports System.Globalization
    Imports System.Runtime.InteropServices
    Imports System.Security.Permissions
    
  3. Agregue las siguientes instrucciones. Permitirán que la implementación de clase haga referencia a otras clases que se crearán en pasos posteriores. Hasta que haya creado dichas clases, es posible que vea advertencias del compilador acerca de estas instrucciones.

    using Contoso.SharePoint.WebControls;
    using Contoso.System.Windows.Controls;
    
    Imports Contoso.SharePoint.WebControls
    Imports Contoso.System.Windows.Controls
    
  4. Asegúrese de que el espacio de nombres sea Contoso.SharePoint.

  5. Asegúrese de que la clase se denomina ISBNField y cambie su declaración para especificar que hereda de SPFieldText.

    public class ISBNField : SPFieldText
    {
    }
    
    Public Class ISBNField
        Inherits SPFieldText
    
    End Class
    
  6. Agregue los siguientes constructores necesarios para la clase.

    public ISBNField(SPFieldCollection fields, string fieldName)
            : base(fields, fieldName)
    {
    }
    
    public ISBNField(SPFieldCollection fields, string typeName, string displayName)
            : base(fields, typeName, displayName)
    {
    }
    
    Public Sub New(fields as SPFieldCollection, fieldname as String)
            MyBase.New(fields, fieldName)
    End Sub
    
    Public Sub New(fields as SPFieldCollection, typeName as String, displayName as String)
            MyBase.New(fields, typeName, displayName)
    End Sub
    
  7. Agregue la siguiente invalidación de FieldRenderingControl a la clase. ISBNFieldControl es una clase que se creará en un paso posterior.

    public override BaseFieldControl FieldRenderingControl
    {
         [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
        get
        {
            BaseFieldControl fieldControl = new ISBNFieldControl();
            fieldControl.FieldName = this.InternalName;
    
            return fieldControl;
        }
    }
    
    Public Overrides ReadOnly Property FieldRenderingControl() As BaseFieldControl
        Get
            Dim fieldControl As BaseFieldControl = New ISBNFieldControl()
            fieldControl.FieldName = Me.InternalName
            Return fieldControl
        End Get
    End Property
    
  8. Agregue la siguiente invalidación del método GetValidatedString a la clase ISBNField:

    public override string GetValidatedString(object value)
    {
        if ((this.Required == true)
           &&
           ((value == null)
            ||
           ((String)value == "")))
        {
            throw new SPFieldValidationException(this.Title 
                + " must have a value.");
        }
        else
        {
            ISBN10ValidationRule rule = new ISBN10ValidationRule();
            ValidationResult result = rule.Validate(value, CultureInfo.InvariantCulture);
    
            if (!result.IsValid)
            {
                throw new SPFieldValidationException((String)result.ErrorContent);
            }
            else
            {
                return base.GetValidatedString(value);
            }
        }
    }// end GetValidatedString
    
    Public Overrides Function GetValidatedString(ByVal value As Object) As String
        If (Me.Required = True) AndAlso ((value Is Nothing) OrElse (CType(value, String) = "")) Then
            Throw New SPFieldValidationException(Me.Title & " must have a value.")
        Else
            Dim rule As New ISBN10ValidationRule()
            Dim result As ValidationResult = rule.Validate(value, cultureInfo.InvariantCulture)
    
            If Not result.IsValid Then
                Throw New SPFieldValidationException(CType(result.ErrorContent, String))
            Else
                Return MyBase.GetValidatedString(value)
            End If
        End If
    End Function ' end GetValidatedString
    

    Esta invalidación es un ejemplo de patrón común para las invalidaciones de GetValidatedString:

    • Las invalidaciones del método GetValidatedString comprueban si el campo es necesario y, en caso afirmativo, el método invalidado produce una excepción SPFieldValidationException cuando el valor es null o una String vacía. Esta excepción es captada por las páginas Nuevo elemento y Editar elemento cuando el usuario intenta guardar el elemento de lista que se está creando o editando. En este caso, la página permanece abierta y la propiedad Message() de la excepción muestra un mensaje de error bajo el campo vacío.

    • Las invalidaciones de GetValidatedString lanzan una excepción SPFieldValidationException cuando el valor no es válido y aparece un mensaje de error bajo el campo no válido.

    • Las invalidaciones de GetValidatedString llaman al GetValidatedString base en caso de que el valor pase la validación personalizada.

  9. Guarde y cierre el archivo.

Creación del control de representación de campo

Para crear el control de representación de campo

  1. Abra el archivo ISBN.FieldControl.cs (o ISBN.FieldControl.vb).

  2. Agregue las siguientes instrucciones.

    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    using System.Runtime.InteropServices;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    
    Imports System.Web
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    
    Imports System.Runtime.InteropServices
    Imports Microsoft.SharePoint
    Imports Microsoft.SharePoint.WebControls
    
  3. Cambie el espacio de nombres por Contoso.SharePoint.WebControls.

  4. Asegúrese de que la clase se denomina ISBNFieldControl y cambie su declaración para especificar que hereda de TextField.

    public class ISBNFieldControl : TextField
    {
    }
    
    Public Class ISBNFieldControl 
        Inherits TextField
    
    End Class
    
  5. Agregue un campo protegido para un control web Label de ASP.NET que llevará el prefijo "ISBN" antes de cada número ISBN cuando se represente en modo Nuevo o Editar. No es necesario agregar un campo protegido TextBox para poner el propio número ISBN, ya que el ISBNFieldControl personalizado hereda ese campo de TextField.

    protected Label ISBNPrefix;
    
    Protected Label ISBNPrefix
    
  6. Agregue otro campo protegido de un control web Label de ASP.NET que representará el valor actual del campo en el modo de presentación.

    protected Label ISBNValueForDisplay;
    
    Protected Label ISBNValueForDisplay
    
  7. A continuación, agregue la siguiente invalidación de la propiedad DefaultTemplateName. La String que asignará a esta propiedad es el identificador de un objeto RenderingTemplate que se agregará, en un paso posterior, al archivo .ascx creado anteriormente. (Cuando finalice el proyecto, este archivo se implementará en la carpeta %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\CONTROLTEMPLATES). Si no se invalida ControlTemplate, Template o TemplateName, se llamará a RenderingTemplate del siguiente modo: ControlTemplate devolverá Template que, a su vez, devolverá la propiedad Template de cualquier RenderingTemplate nombrada por TemplateName. Por último, el descriptor de acceso get de TemplateName devolverá DefaultTemplateName. En un caso más complejo donde, por ejemplo, los modo Nuevo y Editar se encuentren en plantillas distintas, necesitará invalidar una o varias de las siguientes propiedades, seguramente junto con AlternateTemplateName o DefaultAlternateTemplateName.

    protected override string DefaultTemplateName
    {
        get
        {
            if (this.ControlMode == SPControlMode.Display)
            {
                return this.DisplayTemplateName;
            }
            else
            {
                return "ISBNFieldControl";
            }         
        }
    }
    
    Protected Overrides ReadOnly Property DefaultTemplateName() As String
        Get
            If Me.ControlMode = SPControlMode.Display Then
                Return Me.DisplayTemplateName
            Else
                Return "ISBNFieldControl"
        End Get
    End Property
    
  8. Agregue la siguiente invalidación de DisplayTemplateName. La String que asigna a esta propiedad es el identificador de un objeto RenderingTemplate que se agregará en un paso posterior al archivo ascx creado anteriormente. Este objeto representa el valor del campo en el modo de presentación.

    public override string DisplayTemplateName
    {
        get
        {
            return "ISBNFieldControlForDisplay";
        }
        set
        {
            base.DisplayTemplateName = value;
        }
    }
    
    Public Overrides Property DisplayTemplateName() As String
        Get
                 Return "ISBNFieldControlForDisplay"
        End Get
        Set
                 MyBase.DisplayTemplateName = Value
        End Set
    End Property
    
  9. Agregue la siguiente invalidación del método CreateChildControls. La invalidación no realiza ningúna función si el ISBNField subyacente es null. (Puede que sea null si se crea ISBNFieldControl independientemente del descriptor de acceso set para la propiedad FieldRenderingControl de ISBNField (vea la invalidación de FieldRenderingControl en ISBN.Field.cs o ISBN.Field.vb).

    protected override void CreateChildControls()
    {
        if (this.Field != null)
        {
    
    
        }// end if there is a non-null underlying ISBNField 
    
      // Do nothing if the ISBNField is null.
    }
    
    Protected Overrides Sub CreateChildControls()
        If Me.Field IsNot Nothing Then
    
        End If ' end if there is a non-null underlying ISBNField
    
        ' Do nothing if the ISBNField is null or control mode is Display.
    End Sub
    
  10. Agregue la siguiente llamada al método base como la primera línea de la instrucción condicional. Este tipo de llamada suele ser necesario para asegurarse de que se crean los controles secundarios heredados en caso de que estén total o parcialmente representados por el CreateChildControls base en lugar de por una plantilla. Por ejemplo, la plantilla "TextField" de DefaultTemplates.ascx (ubicada en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\ControlTemplates) representa el control secundario TextBox, pero el método CreateChildControls ajusta el tamaño máximo de TextBox para que coincida con el tamaño máximo del campo SPFieldText contiguo. El CreateChildControls base también puede crear controles BaseValidator dinámicos. Sin embargo, lo normal es no tener acceso al código fuente del método base, por lo que es necesario experimentar para determinar si hace falta llamarlo y, en caso afirmativo, saber en qué lugar de la invalidación debe llamarlo.

    // Make sure inherited child controls are completely rendered.
    base.CreateChildControls();
    
    ' Make sure inherited child controls are completely rendered.
    MyBase.CreateChildControls()
    
  11. Agregue las líneas siguientes para asociar los controles secundarios en la plantilla de representación con los campos de control secundarios declarados en su control de campo personalizado (o heredados por su control primario). Este paso debe realizarse ahora, aunque la plantilla de representación no se creará hasta más adelante, ya que la llamada a los CreateChildControls base asociará los controles secundarios heredados con la plantilla de representación usada por la clase de campo personalizado principal, no con la plantilla de representación personalizada, por lo que la asociación base tiene que reemplazarse por una nueva.

    // Associate child controls in the .ascx file with the 
    // fields allocated by this control.
    this.ISBNPrefix = (Label)TemplateContainer.FindControl("ISBNPrefix");
    this.textBox = (TextBox)TemplateContainer.FindControl("TextField");
    this.ISBNValueForDisplay = (Label)TemplateContainer.FindControl("ISBNValueForDisplay");
    
    ' Associate child controls in the .ascx file with the 
    ' fields allocated by this control.
    Me.ISBNPrefix = CType(TemplateContainer.FindControl("ISBNPrefix"), Label)
    Me.textBox = CType(TemplateContainer.FindControl("TextField"), TextBox)
    Me.ISBNValueForDisplay = CType(TemplateContainer.FindControl("ISBNValueForDisplay"), Label)
    
  12. Agregue la siguiente estructura debajo del código de asociación de control. El campo usa una plantilla de representación distinta (que se creará en un paso posterior de este tema) en el modo de presentación de la que usa en los modos de edición y nuevo; por lo tanto, se inicializan controles secundarios diferentes según el modo.

    if (this.ControlMode != SPControlMode.Display)
    {
    
    }
    else // control mode is Display 
    {                 
    
    }// end control mode is Display
    
    If Not Me.ControlMode = SPControlMode.Display Then
    
    Else ' control mode is display
    
    End If ' end control mode is Display
    
  13. Agregue la siguiente estructura condicional interna dentro de la cláusula "if" (o "If") de la estructura condicional realizada en el paso anterior. El código no debe realizar ninguna acción en una devolución (postback) porque si se reinicializa en una devolución (postback), podrían cancelarse los cambios que ha realizado un usuario en los valores de los controles secundarios.

    if (!this.Page.IsPostBack)
    {
    
    }// end if this is not a postback 
    
    //Do not reinitialize on a postback.
    
    If Not Me.Page.IsPostBack Then
    
    End If ' end if this is not a postback
    
    'Do not reinitialize on a postback.
    
  14. Dentro de la estructura condicional agregada en el último paso, agregue la siguiente condicional interno para iniciar el control secundario TextBox con un valor ISBN predeterminado cuando el modo de control es Nuevo.

    if (this.ControlMode == SPControlMode.New)
    {
        textBox.Text = "0-000-00000-0";
    
    } // end assign default value in New mode
    
    If Me.ControlMode = SPControlMode.New Then
       textBox.Text = "0-000-00000-0"
    
    End If ' end assign default value in New mode
    
  15. En el bloque else (o Else) que se ejecuta cuando el modo de control es de presentación, agregue el siguiente código para inicializar el campo en su valor actual de la base de datos de contenido.

    // Assign current value from database to the label control
    ISBNValueForDisplay.Text = (String)this.ItemFieldValue;
    
    ' Assign current value from database to the label control
    ISBNValueForDisplay.Text = CType(Me.ItemFieldValue, String)
    
  16. En el modo Editar no hace falta hacer nada porque el método OnLoad iniciará ISBNFieldControl.Value con el valor de ItemFieldValue que tiene el valor actual del campo en la base de datos de contenido. En este momento, la invalidación de CreateChildControls debería tener el siguiente aspecto.

    protected override void CreateChildControls()
    {
        if (this.Field != null)
        {
            // Make sure inherited child controls are completely rendered.
            base.CreateChildControls();
    
            // Associate child controls in the .ascx file with the 
            // fields allocated by this control.
            this.ISBNPrefix = (Label)TemplateContainer.FindControl("ISBNPrefix");
            this.textBox = (TextBox)TemplateContainer.FindControl("TextField");
            this.ISBNValueForDisplay = (Label)TemplateContainer.FindControl("ISBNValueForDisplay");
    
            if (this.ControlMode != SPControlMode.Display)
            {
                if (!this.Page.IsPostBack)
                {
                    if (this.ControlMode == SPControlMode.New)
                    {
                        textBox.Text = "0-000-00000-0";
    
                    } // end assign default value in New mode
    
                 }// end if this is not a postback 
    
              // Do not reinitialize on a postback.
    
            }// end if control mode is not Display
            else // control mode is Display 
            {                 
                // Assign current value from database to the label control
                ISBNValueForDisplay.Text = (String)this.ItemFieldValue;
    
            }// end control mode is Display
    
        }// end if there is a non-null underlying ISBNField 
    
        // Do nothing if the ISBNField is null.
    }
    
    Protected Overrides Sub CreateChildControls()
        If Me.Field IsNot Then
            ' Make sure inherited child controls are completely rendered.
            MyBase.CreateChildControls()
    
            ' Associate child controls in the .ascx file with the 
            ' fields allocated by this control.
            Me.ISBNPrefix = CType(TemplateContainer.FindControl("ISBNPrefix"), Label)
            Me.textBox = CType(TemplateContainer.FindControl("TextField"), TextBox)
            Me.ISBNValueForDisplay = CType(TemplateContainer.FindControl("ISBNValueForDisplay"), Label)
    
            If Not Me.ControlMode = SPControlMode.Display Then
    
                 If Not Me.Page.IsPostBack Then
                     If Me.ControlMode = SPControlMode.New Then
                         textBox.Text = "0-000-00000-0"
    
                     End If ' end assign default value in New mode
    
                 End If ' end if this is not a postback
    
                 'Do not reinitialize on a postback.
    
            Else ' control mode is display
                ' Assign current value from database to the label control
                ISBNValueForDisplay.Text = CType(Me.ItemFieldValue, String)
    
            End If ' end control mode is Display
    
        End If ' end if there is a non-null underlying ISBNField
    
        ' Do nothing if the ISBNField is null or control mode is Display.
    End Sub
    
  17. Agregue la siguiente invalidación de la propiedad Value, que es el valor del campo en la interfaz de usuario. Si el usuario final ha modificado el valor y aún no lo ha guardado, la propiedad Value no será necesariamente el valor real del objeto ISBNField subyacente (derivado de SPFieldText) ni el valor del campo en la base de datos de contenido. Tenga en cuenta que tanto el descriptor de acceso get como el descriptor de acceso set comienzan llamando a EnsureChildControls (que, a su vez, llamará a CreateChildControls si es necesario). Es obligatorio llamar a EnsureChildControls, a menos que (1) se llame primero a la propiedad base y (2) se sepa que los descriptores de acceso set y get de la propiedad base llaman a EnsureChildControls. Si sustituyera el control secundario TextBox subyacente heredado de TextField por un tipo de control totalmente distinto, como un cuadro de lista desplegable, los descriptores de acceso set y get de la invalidación de la propiedad Value tendrían que establecer este control directamente, en lugar de llamar a una propiedad base. Para asegurarse de que el control carga inicialmente el valor en el objeto ISBNField subyacente, el método OnLoad() configura ISBNFieldControl.Value con el valor de ItemFieldValue, que es el valor del objeto ISBNField subyacente.

    public override object Value
    {
        get
        {
            EnsureChildControls();
            return base.Value;
        }
        set
        {
             EnsureChildControls();
             base.Value = (String)value;
             // The value of the ISBNPrefix field is hardcoded in the
             // template, so it is not set here.
        }
    }
    
    Public Overrides Property Value() As Object
        Get
            EnsureChildControls()
            Return MyBase.Value
        End Get
        Set(ByVal value As Object)
            EnsureChildControls()
            MyBase.Value = CType(value, String)
            ' The value of the ISBNPrefix field is hardcoded in the
            ' template, so it is not set here.
        End Set
    End Property
    

Creación de la plantilla de representación de campo

Para crear la plantilla de representación

  1. Abra el archivo ISBNFieldControl.ascx.

  2. Las directivas siguientes ya se encuentran en el archivo.

    <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
    <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
    <%@ Import Namespace="Microsoft.SharePoint" %> 
    <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    
  3. Debajo de este marcado hay una directiva <%@ Control que hace referencia a los archivos eliminados en un paso anterior y contiene atributos adicionales que no se usan en este proyecto. Reemplácela por la siguiente directiva simplificada.

    <%@ Control Language="C#" %>
    
  4. Debajo de las directivas, agregue el siguiente marcado.

    <SharePoint:RenderingTemplate ID="ISBNFieldControl" runat="server">
      <Template>
        <asp:Label ID="ISBNPrefix" Text="ISBN" runat="server" />
        &nbsp;
        <asp:TextBox ID="TextField" runat="server"  />
      </Template>
    </SharePoint:RenderingTemplate>
    

    Tenga en cuenta los hechos siguientes acerca de este marcado:

    • El ID de la RenderingTemplate debe ser idéntico a la cadena usada en la invalidación de la propiedad DefaultTemplateName.

    • El atributo Text del control Label se define aquí en la plantilla porque no se modifica nunca.

    • Entre los dos controles se incluye un elemento HTML "&nbsp;".

    • La definición de TextBox es idéntica a la de "TextField" RenderingTemplate, que está definida en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\CONTROLTEMPLATES\DefaultTemplates.ascx. Sin embargo, la definición debe repetirse aquí porque la invalidación de DefaultTemplateName apunta a esta plantilla personalizada, en lugar de la plantilla de "TextField". Se usa el mismo ID en la plantilla personalizada porque el método CreateChildControls base (vea el apartado anterior) podría hacer referencia al control por este ID.

  5. Agregue la siguiente RenderingTemplate adicional justo debajo de la primera.

    <SharePoint:RenderingTemplate ID="ISBNFieldControlForDisplay" runat="server">
      <Template>
        <asp:Label ID="ISBNValueForDisplay" runat="server" />
      </Template>
    </SharePoint:RenderingTemplate>
    

    El método CreateChildControls designará esta RenderingTemplate como la plantilla predeterminada en el modo de presentación.

Crear la definición de tipo de campo

Para crear la definición de tipo de campo

  1. En Visual Studio, cree el proyecto. El proyecto no está completo, pero se debe crear en este momento para generar un GUID y un token de clave pública para el ensamblado.

  2. Abra el archivo fldtypes_ISBNField.xml y reemplace su contenido por el siguiente marcado.

    <?xml version="1.0" encoding="utf-8" ?>
    <FieldTypes>
      <FieldType>
        <Field Name="TypeName">ISBN</Field>
        <Field Name="ParentType">Text</Field>
        <Field Name="TypeDisplayName">ISBN</Field>
        <Field Name="TypeShortDescription">ISBN for a book</Field>
        <Field Name="UserCreatable">TRUE</Field>
        <Field Name="ShowOnListCreate">TRUE</Field>
        <Field Name="ShowOnSurveyCreate">TRUE</Field>
        <Field Name="ShowOnDocumentLibraryCreate">TRUE</Field>
        <Field Name="ShowOnColumnTemplateCreate">TRUE</Field>
        <Field Name="FieldTypeClass">Contoso.SharePoint.ISBNField, $SharePoint.Project.AssemblyFullName$</Field>
      </FieldType>
    </FieldTypes>
    

    En este archivo se define el tipo de campo personalizado para SharePoint Foundation. Para obtener información detallada sobre el objetivo y el significado de sus elementos, vea Procedimiento para crear una definición de tipo de campo personalizado, Descripción del archivo FldTypes.xml, Elemento FieldTypes (Tipos de campo), Elemento FieldType (Tipos de campo) y Elemento Field (Tipos de campo). Tenga en cuenta que el elemento <Field Name="FieldTypeClass"> debe estar entero en una línea.

  3. El valor del elemento <Field Name="FieldTypeClass"> es el nombre completo de la clase de campo personalizada seguido por una coma y, a continuación, por un token de Visual Studio 2010 ($SharePoint.Project.AssemblyFullName$). Al compilar el proyecto, se crea una copia de este archivo en la que el token se reemplaza por el nombre de cuatro partes completo del ensamblado. Esta es la copia que se implementa al seleccionar Implementar solución en el menú Generar de Visual Studio en Visual Studio 2010. Si no usa Visual Studio 2010, deberá compilar el proyecto en este momento, aunque no esté terminado, a fin de generar un token de clave pública. Posteriormente, puede usar la herramienta descrita en Procedimiento para crear una herramienta para obtener el nombre completo de un ensamblado para obtener el nombre de cuatro partes completo y pegarlo manualmente en lugar del token.

Creación de la hoja de estilo XSLT

Para crear la hoja de estilo XSLT

  • Abra el archivo fldtypes_ISBNField.xsl y reemplace toda la información que se encuentre debajo de la etiqueta <?xml version="1.0" encoding="utf-8"?> por el siguiente marcado.

    <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema"
                    xmlns:d="https://schemas.microsoft.com/sharepoint/dsp"
                    version="1.0"
                    exclude-result-prefixes="xsl msxsl ddwrt"
                    xmlns:ddwrt="https://schemas.microsoft.com/WebParts/v2/DataView/runtime"
                    xmlns:asp="https://schemas.microsoft.com/ASPNET/20"
                    xmlns:__designer="https://schemas.microsoft.com/WebParts/v2/DataView/designer" 
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                    xmlns:SharePoint="Microsoft.SharePoint.WebControls"
                    xmlns:ddwrt2="urn:frontpage:internal">
    
      <xsl:template match="FieldRef[@Name = 'ISBN']" mode="Text_body">
    
        <xsl:param name="thisNode" select="." /> 
    
        <span style="background-color:lightgreen;font-weight:bold">
    
          <xsl:value-of select="$thisNode/@*[name()=current()/@Name]" />
    
        </span>
    
      </xsl:template >
    
    </xsl:stylesheet>
    

    La hoja de estilo XSLT representa el campo en vistas de lista. Las celdas de la columna ISBN de las vistas de lista tienen un fondo verde claro con el valor de ISBN en negrita.

    El encabezado de columna en el modo de vista de lista se representa por medio de otra hoja de estilo XSLT suministrada en el archivo integrado fldtypes.xsl en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATES\LAYOUTS\XSL.

Crear y probar el tipo de campo personalizado

Para crear y probar el tipo de campo personalizado

  1. Seleccione Implementar en el menú Generar. Automáticamente se recompilará el ensamblado, se implementará el ensamblado en la GAC, se implementará el archivo ascx en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\ControlTemplates, se implementará el archivo fldtypes*.xml en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\XML, se implementará el archivo fldtypes*.xsl en %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL y se reciclará la aplicación web.

    Nota

    Si el entorno de desarrollo es una granja de varios servidores, el paso de implementación no se llevará a cabo automáticamente. Implemente la solución, isbn_field_type.wsp, desde la página Administración de soluciones de la aplicación de Administración central o con un cmdlet de Consola de administración de SharePoint.

  2. Abra un sitio web en su aplicación web de SharePoint y cree una lista denominada Libros.

  3. Agregue una nueva columna a la lista. En la página Crear columna, ponga como nombre de la columna "ISBN".

  4. Haga clic en el botón de radio de ISBN para un libro.

  5. Haga clic en el botón de radio para que el campo sea obligatorio.

  6. Deje sin marcar la casilla de verificación Agregar a vista predeterminada.

  7. Haga clic en Aceptar.

  8. Agregar un elemento a la lista.

  9. En la página Nuevo elemento, compruebe que el campo esté establecido inicialmente en el valor predeterminado "0-000-00000-0" y que, además del título del campo "ISBN", el valor propiamente dicho esté inmediatamente precedido por "ISBN" como se define en la plantilla de representación de los modos nuevo y de edición.

  10. Escriba los valores de ISBN no válidos para ver qué tipo de errores se obtiene cuando intenta guardar el elemento.

  11. Vea qué sucede si se deja el campo completamente en blanco.

  12. Por último, escriba 0-262-61108-2 u otro valor que sea válido y haga clic en Guardar. (Si obtiene errores para un ISBN válido, asegúrese de que no haya ningún espacio en blanco al final del valor).

  13. Confirme que el valor de la vista de lista esté en negrita con un fondo verde claro.

  14. Haga clic en el título del elemento para abrir la página de presentación. Confirme que el campo se representa con su valor actual de la base de datos de contenido. Tenga en cuenta que aunque el título del campo "ISBN" está presente, el valor propiamente dicho no está inmediatamente precedido por "ISBN" como en los modos de edición y nuevo porque este prefijo no formaba parte de la plantilla de representación del modo de presentación.

  15. Haga clic en Editar elemento para editar el campo. Confirme que el campo esté establecido inicialmente en su valor actual, no en el valor predeterminado, y que además del título del campo "ISBN", el valor propiamente dicho también esté inmediatamente precedido por "ISBN" como se define en la plantilla de representación de los modos nuevo y de edición.

  16. Cambie el valor del campo a valores no válidos y y confirme que los errores de validación aparecen en modo de edición igual que en el modo nuevo.

Diferencias entre la representación de campos para dispositivos móviles y la representación de campos para equipos

En SharePoint Foundation, la representación de campos con controles de representación de campos personalizados para dispositivos móviles es similar a la representación de campos con controles de representación de campos personalizados para equipos. No obstante, tenga en cuenta las diferencias siguientes:

  • Las páginas móviles son un conjunto de páginas totalmente distinto de las páginas principales de un sitio SharePoint Foundation (diseñados para exploradores de equipos) y hacen referencia a un conjunto distinto de elementos de RenderingTemplate.

  • Los objetos RenderingTemplate móviles se declaran en MobileDefaultTemplates.ascx y GbwMobileDefaultTemplates.ascx, no en DefaultTemplates.ascx.

  • Los controles móviles de representación de campos tienen su propio nombre de espacio Microsoft.SharePoint.MobileControls que se derivan de clases en el nombre de espacio ASP.NET System.Web.UI.MobileControls (y no en el de System.Web.UI.WebControls ).

  • La jerarquía de herencia para controles de representación de campos móviles es algo diferente de la de los controles de representación de campos habituales. Por ejemplo, las funciones de TemplateBasedControl y FormComponent en la representación de campos habituales se combinan en la clase SPMobileComponent.

  • Los controles de representación de campos personalizados que cree para contextos móviles se basan más en el método CreateChildControls del control para representar un campo y, en consecuencia, menos en la plantilla de representación, de lo que sucede con los controles de representación de campos personalizados que se crean para exploradores de equipos). Es más, cuando se desarrollan controles de representación móviles personalizados, no se suele invalidar el método CreateChildControls. En su lugar, los controles móviles de representación personalizada normalmente invalidarán uno o varios de los cuatro métodos llamados por el método CreateChildControls :

Vea también

Referencia

Elemento FieldTypes (Tipos de campo)

Elemento FieldType (Tipos de campo)

Elemento Field (Tipos de campo)

Namespace Naming Guidelines

Elemento RenderPattern (Tipos de campo)

AlternateTemplateName

BaseValidator

ControlTemplate

CreateChildControls

DefaultAlternateTemplateName

DefaultTemplateName

EnsureChildControls

FieldRenderingControl

GetValidatedString

ItemFieldValue

Label

OnLoad()

RegularExpressions

RenderingTemplate

SPControlMode

SPFieldText

SPFieldValidationException

Template

TemplateName

TextBox

TextField

ValidationRule

Value

Conceptos

Procedimiento para crear una clase de campos personalizados

Procedimiento para crear una definición de tipo de campo personalizado

Implementación de tipos de campo personalizados

Validación de datos de campos personalizados

Procedimiento para crear un control de representación de campos

Procedimiento para crear plantillas de representación de campos

Procedimiento para crear un tipo de campo personalizado

Introducción a las soluciones