Seguro que todos hemos usado la clase SPContext para obtener datos de la página actual, sitio, etc.
El problema nos surge cuando en nuestro wepart queremos usar el contexto de otro web/lista/item disitinto del contexto que nos tocaría.
Ejemplo, nos hemos creado un webpart que muestra una lista de elementos y queremos meter el control por defecto de moss para que salgan los menús igual que en las listas "de verdad" de moss.
Si ponemos este código, veremos que como el contexto es el de una página web (donde se ejecuta el webpart) el menú nuevo nos aparece con items que no corresponden a la lista:
Dim nmenu As New NewMenu
toolbar.Buttons.Controls.Add(nmenu)
Podemos ver como no salen los items del menú que queremos, pq el objeto NewMenu toma el contexto actual (de la página), no el de la lista a la que se refiere el webpart:
Lo que tenemos que hacer es obtener un contexto para la lista y pasar al control ese contexto en la propiedad RenderContext, para que el control lo tenga en cuenta y pinte las opciones correspondientes a la lista, el código quedaría tal que así:
Dim contextoLista As SPContext = SPContext.GetContext(System.Web.HttpContext.Current, spLista.DefaultView.ID, spLista.ID, web)
Dim nmenu As New NewMenu
nmenu.RenderContext = contextoLista
toolbar.Buttons.Controls.Add(nmenu)
Fijaos que obtenemos el contexto pasandole el id de la lista, de la vista y el web, de tal forma que para el new menu es como si estuviera en el allitems.aspx de la lista. De esta forma el resultado queda así, se puede ver que los items del menú son los correspondientes a la lista que estamos mostrando.
Esto para los controles de MOSS, pero ¿qué pasa con los nuestros? En nuestro caso estábamos tratando de añadir una opción a una lista tal y como explica Jan Tielens aquí y aquí:
Básicamente heredamos de System.Web.UI.WebControls.WebControl y creamos un MenuItemTemplate en el que hacemos "nuestras historias" para las que necesitamos saber el item Id de la carpeta de la lista en la que estamos (eso o cualquier otra cosa de la lista). Basicamente el picarnos eso hace que podamos hacer en el item del menú todo lo que queramos y que no sea solo un link a otra página, sino que pueda tener la lógica q nos venga en gana.
La extensión la ponemos en el menú Acciones, que recibe el contexto que hemos creado anteriormente como RenderContext, el código inicial es este:
Public Class ActionVisorContentTypes
Inherits System.Web.UI.WebControls.WebControl
Protected Overrides Sub CreateChildControls()
Dim list As SPList = SPContext.Current.List
....
End Sub
...
End Class
¿Cual es el problema? Cuando accedemos al SPContext.Current no pillamos el contexto que nos hemos creado y hemos pasado como RenderContext (pese a que el menú de acciones si lo coge), sino el del webpart (con lo que la propiedad list es Nothing/Null y se la pega). Así que parece que los controles no estan cogiendo siempre ese..
Bueno parece que el fallo está en heredar de System.Web.UI.WebControls.WebControl, tras pegarnos un poco con el Reflector vemos que el primer hijo de WebControl que expone la propiedad RenderContext es Microsoft.SharePoint.WebControls.TemplateBasedControl, así que heredamos de él a ver que pasa.
Entonces lo que debemos usar es en vez del SPContext.Current directamente es el RenderContext (que parece que el menú contenedor se lo pasa cuando lo pinta por lo que recibe el contexto que le hemos definido), de tal manera que el código queda así:
Public Class ActionVisorContentTypes
Inherits Microsoft.SharePoint.WebControls.TemplateBasedControl
Protected Overrides Sub CreateChildControls()
Dim list As SPList = Me.RenderContext.List
....
End Sub
...
End Class
De esta manera la extensión que nos hemos hecho funciona tanto desde la página de la vista de la lista como desde nuestro webpart.