WebPart in un piatto di SharePoint con una spruzzata di WebUserControl

Creare WebPart con un'UI un pò carina è IMHO qualcosa di alquanto complicato.

E' interessante, in questi casi e non, utilizzare le WebUserControl.

Purtroppo ancor'oggi con le Visual Studio 2008 extensions for Windows SharePoint Services 3.0, v1.3 - Mar 2009 CTP non è stato creato un progetto che ne supporta direttamente l'utilizzo.

Ma, con un paio di accorgimenti, è possibile utilizzarle.

Vediamo come.

  1. Installiamo le extensions di cui sopra.
  2. Creiamo un progetto di tipo SharePoint -> WebPart
  3. Create/disegnate il vostro WebUserControl in un progetto di tipo ASP.NET Web Application (per questo esempio utilizzerò un ascx di nome WebUserControl1.ascx)
  4. Prendete il contenuto del file WebUserControl1.ascx.designer.cs e riversatelo all'interno del file WebUserControl1.ascx.cs
  5. Eliminate la keyword partial dalla classe
  6. Quello che otterrete è qualcosa del tipo (io ho inserito una Label e un Button):
    public class WebUserControl1 : System.Web.UI.UserControl
    {
        protected Label Label1;
    
        protected Button Button1;
    
        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    
        protected void Button1_Click(object sender, EventArgs e)
        {
            Label1.Text = DateTime.Now.ToString();
        }
    }
     
  7. Copiate il codice di cui sopra e inseritelo all'interno del namespace del file cs creato
    dal progetto SharePoint WebPart del punto 2
  8. Il risultato sarà il seguente:
    [Guid("2f61a277-7142-4d8d-a72c-4dfd83c6cedb")]
    public class WebPart1 : System.Web.UI.WebControls.WebParts.WebPart
    {
        public WebPart1()
        {
        }
    
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
    
            // TODO: add custom rendering code here.
            // Label label = new Label();
            // label.Text = "Hello World";
            // this.Controls.Add(label);
        }
    }
    
    public class WebUserControl1 : System.Web.UI.UserControl
    {
        protected Label Label1;
    
        protected Button Button1;
    
        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    
        protected void Button1_Click(object sender, EventArgs e)
        {
            Label1.Text = DateTime.Now.ToString();
        }
    }
     
  9. Adesso potreste anche cancellare il file WebUserControl1.ascx.cs
  10. Aggiungiamo l'item Root File nel nostro progetto SharePoint WebPart
  11. Sotto la directory RootFiles, create le directory Template\ControlTemplates. Questa sarà la directory SharePoint dove verrà copiato il nostro WebUserControl
  12. Copiamo il nostro file WebUserControl1.ascx dall'applicazione ASP.NET Web Application alle directory del punto precedente, in modo da ottenere RootFiles\Template\ControlTemplates\WebUserControl1.ascx e aggiungiamo il file al progetto
  13. Adesso dobbiamo modificare il nostro file WebUserControl1.ascx per far puntare i riferimenti al code-behind alla stessa dll della WebPart. In teoria quello che dovreste avere è:
    <%@ Control Language="C#" AutoEventWireup="true"
    CodeBehind="WebUserControl1.ascx.cs"
    Inherits="WebApplication1.WebUserControl1" %>
    che dovrà diventare:
    <%@ Control Language="C#" AutoEventWireup="true"
    ClassName="WebUserControl1"
    Inherits="WebPart1.WebUserControl1, WebPart1, Version=1.0.0.0,
    Culture=neutral, PublicKeyToken=<token creato dal progetto SharePoint WebPart>"
    %>
     
    in ClassName specifichiamo la classe del nostro WebUserControl copiato nel punto 7,
    mentre in Inherits specifichiamo:
    Namespace.ClassName, Nome_Assembly, Version, Culture, PublicKeyToken

    tutti questi dati lì ho presi da Administrative Tools -> Microsoft .NET Framework 2.0 Configuration
    guardando le proprietà della mia dll della WebPart deployata.

A questo punto potete inserire la WebPart in una pagina e testarla.

 

 Le WebPart vanno testate all'interno di una pagina di SharePoint non nelle WebPart Preview; nella WebPart Preview gli eventi non funzioneranno.

 

Expression Trees

Avevo postato questo link nella sezione link del blog, così facendo non gli ho dato una certa visualizzazione.

Ecco il link, l'articolo è molto interessante:

http://msdn.microsoft.com/en-us/library/bb397951.aspx

 

Tags:

Replace Constructors with Creation Methods

Continuando la serie di post sui smells, inizio ad introdurre i possibili smell e le relative possibili soluzioni.

Il primo che affronteremo riguarda una classe con 5 costruttori (anche se personalmente già 2 costruttori sono troppi):

 

public class Loan
{
    public Loan(string commitment, int riskRating, int maturity)
    public Loan(string commitment, int riskRating, int maturity, DateTime expiry)
    public Loan(string commitment, string outstanding, int riskRating, int maturity, DateTime expiry)
    public Loan(int capitalStrategy, string commitment, int riskRating, int maturity, DateTime expiry)
    public Loan(int capitalStrategy, string commitment, string outstanding, int riskRating, int maturity, DateTime expiry)
}

Ecco come si presenterà la classe una volta rifattorizzata:

public class Loan
{
    private Loan(int capitalStrategy, string commitment, string outstanding, int riskRating, int maturity, DateTime expiry)
    public static Loan createTermLoad(string commitment, int riskRating, int maturity)
    {
        return new Loan(-1, commitment, "", riskRating, maturity, DateTime.MinValue);
    }

    public static Loan createTermLoad(int capitalStrategy, string commitment,
                                      string outstanding, int riskRating, int maturity)
    {
        return new Loan(capitalStrategy, commitment, outstanding, riskRating, maturity,
                        DateTime.MinValue);
    }

    public static Loan createRevolver(string commitment, string outstanding,
                                      int riskRating, DateTime expiry)
    {
        return new Loan(-1, commitment, outstanding, riskRating, -1, DateTime.MinValue);
    }

    public static Loan createRevolver(int capitalStrategy, string commitment,
                                      string outstanding, int riskRating, int maturity)
    {
        return new Loan(capitalStrategy, commitment, outstanding, riskRating,
                        maturity, DateTime.MinValue);
    }

    public static Loan createRCTL(string commitment, string outstanding,
                                  int riskRating, int maturity, DateTime expiry)
    {
        return new Loan(-1, commitment, outstanding, riskRating, maturity, expiry);
    }

    public static Loan createRCTL(int capitalStrategy, string commitment,
                                  string outstanding, int riskRating, int maturity,
                                  DateTime expiry) 
    {
        return new Loan(capitalStrategy, commitment, outstanding, riskRating, maturity, expiry);
    }
}
Motivazione:

Perchè dovrei togliere i miei molteplici costruttori a favore di una seria di metodi statici?
I costruttori non comunicano qual'è la loro intenzione nel momento in cui istanziano la classe, così più costruttori abbiamo all'interno della nostra classe più è probabile che dovremo andare a controllare ogni singolo costruttore per capire cosa fa (cosa impensabile se neanche abbiamo i sorgenti).

Se servirà creare un costruttore con la stessa firma, ma che istanzia l'oggetto in maniera diversa, non si potrà inserire.

Se il software avrà una certa dimensione e tanti costruttori è probabile che molti di questi non verranno utilizzati e vi rimaranno lì perchè anche capire quali vengono usati e quali no è un lavoro molto complicato.

Benefici e non
+ Comunica quale tipo di istanza stiamo creando
+ Evita i limiti dei costruttori
+ E' più semplice trovare i metodi non usati
- E' un metodo non standard per istanziare gli oggetti. Così potreste trovarvi alcune classi con i costruttori classici e altre no.

 

Per questi post sto prendendo, molto, spunto da libro Refactoring To Patterns di Joshua Kerievsky.