DynamicData e ColorPicker FieldTemplates

by Andrea 16 September 2009 03:17

Con i Dynamic Data la velocità di realizzare l'applicazione aumenta notevolmente (ovvio che dipende sempre dal tipo di applicazione che si deve realizzare) e con la creazione di FieldTemplates di ha la possibilità di migliorare l'iterazione tra applicazione e utente.

Una delle necessità che ho avuto è stata quella di dover far inserire il valore in esadecimale di un colore (es: #FFFFFF), e consapevole del fatto che un utente non potesse conoscere i valori a memoria, mi sono adoperato per realizzare un opportuno FieldTemplate.
L'ultima versione degli AJAX Control Toolkit mi è venuta in aiuto grazie al controllo ColorPicker che è stato recentemente incluso, ed ecco qui il risultato ottenuto:

ColorFieldTemplate

Il codice del FieldTemplate è il seguente:

   1: public partial class Color_EditField : FieldTemplateUserControl
   2: {
   3:     protected override void ExtractValues(IOrderedDictionary dictionary)
   4:     {
   5:         dictionary[Column.Name] = ConvertEditedValue(txtColor.Text);
   6:     }
   7:  
   8:     public override Control DataControl
   9:     {
  10:         get { return txtColor; }
  11:     }
  12: }
   1: <%@ Control Language="C#" CodeBehind="Color_Edit.ascx.cs" Inherits="DynamicData.FieldTemplates.Color_EditField" AutoEventWireup="True" %>
   2:  
   3: <asp:ImageButton 
   4:     runat="Server" 
   5:     ID="btnOpenColorPicker" 
   6:     style="float:left;margin:0 3px" 
   7:     ValidationGroup="none" 
   8:     ImageUrl="~/images/cp_button.png" 
   9:     AlternateText="Click to show color picker" />
  10: <asp:Panel 
  11:     runat="server"
  12:     ID="pnlColor" 
  13:     style="width:18px;height:18px;border:1px solid #000;margin:0 3px;float:left" />
  14: <atk:ColorPickerExtender 
  15:     runat="server"
  16:     ID="colorPicker"     
  17:     TargetControlID="txtColor" 
  18:     PopupButtonID="btnOpenColorPicker" 
  19:     SampleControlID="pnlColor" 
  20:     PopupPosition="Absolute" />
  21: <asp:TextBox ID="txtColor" 
  22:     runat="server" 
  23:     Text='<%# FieldValueEditString %>' 
  24:     style="visibility:hidden;" />

Nella mia applicazione non avevo la necessita di visualizzare il codice del colore (che compare nella TextBox), ma nel caso a qualcuno interessasse, sarà sufficiente togliere lo stile "visibility:hidden;" dalla TextBox txtColor.

Tags: ,

ASP.NET AJAX | ASP .NET | .NET

ASP.NET Ajax Control Toolkit e DynamicPopulateExtenderControlBase

by Andrea 14 September 2009 06:51

Stavo introducendo il controllo HoverMenuExtender all'interno di uno UserControl e nell'intellisense mi compaiono alcune proprietà che mi risultano "anomale" per il controllo che stavo per utilizzare. Anomale nel senso che non mi aspettavo proprio di trovare tali proprietà in questo controllo.
HoverMenuExtender 
Le proprietà in questione sono quelle che hanno il suffisso Dynamic: DynamicContextKey, DynamicControlID, DynamicServiceMethod e DynamicServicePath.

Visto che (dal nome) potevano fare al caso mio, guardo la documentazione online, e scopro che non esiste documentazione a riguardo. Allora, come spesso accade, scarico i sorgenti degli ajax control toolkit e do un'occhiata al codice per capire dove fossere utilizzate e a cosa servissero. Ed è qui che sono rimasto sorpreso.

I controlli HoverMenuExtender, DropDownExtender, ModalPopupExtender e PopupControlExtender derivano dalla classe base DynamicPopulateExtenderControlBase, che contiene per l'appunto queste proprietà:

  • DynamicServicePath: url del web service che conterrà il metodo da chiamare. (lasciare vuoto se si intende chiamare un page method)
  • DynamicServiceMethod: metodo del web service da chiamare.
  • DynamicContextKey: permette di definire un parametro opzionale per parametrizzare il metodo chiamato. (parametro opzionale)
  • DynamicControlID: id del controllo che verrà utilizzato come container per iniettare il codice HTML restituito dal metodo.

Utilizzando queste proprietà è possibile utilizzare un metodo (DynamicServiceMethod) di un web service (DynamicServicePath) per farsi ritornare una porzione di condice HTML, che verrà poi iniettato in un preciso controllo (DynamicControlID).

Per provare se il tutto funziona correttamente, la via più semplice è quella di provare il tutto.
Creo un metodo in un web service che restituisca una porzione di codice HTML:

   1: [WebMethod]
   2: [ScriptMethod]
   3: public string GetHoverMenuContent(string contextKey)
   4: {
   5:     return String.Format("<span style='{0}'>Hello World!</span>", contextKey);
   6: }

e nella pagina vado a inserire il controllo, con le proprietà correttamente valorizzate:

   1: <ajax:HoverMenuExtender 
   2:     ID="hoverMenuExtender"
   3:     runat="server"
   4:     TargetControlID="linkButton" 
   5:     PopupControlID="Panel1" 
   6:     PopupPosition="Right" 
   7:     DynamicControlID="Panel2"
   8:     DynamicContextKey='font-weight:bold' 
   9:     DynamicServiceMethod="GetHoverMenuContent" 
  10:     DynamicServicePath="~/ajax.asmx" />
  11:  
  12: <asp:Panel ID="Panel1" runat="server" style="display:none;">
  13:   <asp:Label ID="Panel2" runat="server" />
  14: </asp:Panel> 

Il risultato che ho ottenuto è stato esattamente quello voluto, e quindi che al passaggio del mouse sopra al linkButton (o al controllo definito nella proprietà TargetControlID), è stato chiamato il metodo del web service, passando nel parametro contextKey il valore specificato nella prorietà DynamicContextKey (in questo caso il valore è fisso a font-weight:bold), e una volta ritornato il codice HTML, questo è stato inserito come innerHTML del controllo Panel2, e il Panel1 reso visibile.

In poche parole, tramite queste proprietà si ha la possibilità di popolare i controlli con maggiore dinamicità, e delegando la creazione di parte del contenuto HTML ad un metodo esterno. Questo in molti casi risulta veramente utile, permettondo con poche righe di codice di ottenere il comportamento/effetto voluto, e dimostrando per l'ennesima volta la flessibilità dei controlli contenuti negli AJAX Control Toolkit.

Tags: ,

ASP.NET AJAX | ASP .NET | .NET

Visualizzare e nascondere un PopupControlExtender da una funzione server side

by Andrea 20 July 2009 08:55

Qualcuno ha posto la domanda, se fosse possibile visualizzare o nascondere un popup creato con il PopupControlExtender direttamente da una funzione server side.

A differenza del ModalPopupExtender, PopupControlExtender il  non dispone di queste funzionalità server side, ma con poche righe di codice si può aggirare la problematica.

Per fare questo dobbiamo valorizzare la proprietà BehaviorID dell'extender:

   1: <ajax:PopupControlExtender 
   2:   ID="popup"
   3:   runat="server" 
   4:   BehaviorID="popupExt" ... />

utilizzando i metodi client showPopup e hidePopup, possiamo registrare uno script che si occupi di far visualizzare o nascondere il popup. Lo script utilizzerà la funzione $find per cercare l'extender all'interno del DOM della pagina, e successivamente verrano chiamate le funzioni showPopup oppure hidePopup esposte dallo script dell'extender.

Grazie al metodo RegisterStartupScript esposto dallo ScriptManager possiamo registrare lo script che immadiatamente verrà eseguito alla fine del postback.

   1: // visualizzare il popup
   2: ScriptManager.RegisterStartupScript(this, this.GetType(), "showPopup", "$find('popupExt').showPopup();", true);
   3:  
   4: // nascondere il popup
   5: ScriptManager.RegisterStartupScript(this, this.GetType(), "hidePopup", "$find('popupExt').hidePopup();", true);

 

Tags: ,

.NET | ASP .NET | ASP.NET AJAX

MultiHandleSliderExtender in un Templated Control

by Andrea 05 March 2009 05:18

Se provate a utilizzare un MultiHandleSliderExtender all'interno di una GridView, o di un Repeater o di un altro Templated Control, vi capiterà con una bella eccezione javascript (null is null or not an object) in quanto non l'extender non riesce a trovare i controlli impostati come MultiHandleSliderTarget.
Dando un'occhiata al file javascript di questo extender si può notare che il controllo esegue la funzione $get (recupera un elemento all'interno della pagina) usando come parametro l'id inserito, ma che nel caso di inserimento in un Templated Control, questo sarà differente dall'effettivo id utilizzato nella pagina (ClientID), sollevando quindi l'eccezione.

Per risolvere questo è sufficiente gestire l'evento RowDataBound (nel caso della GridView) e sostituire in ogni MultiHandleSliderTarget l'id dei controlli con i rispetti ClientID.

Ecco il codice necessario:

   1: protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
   2: {
   3:     if (e.Row.RowType == DataControlRowType.DataRow)
   4:     {
   5:         MultiHandleSliderExtender slider = e.Row.FindControl("multiHandleSliderExtenderTwo") as MultiHandleSliderExtender;
   6:         foreach (MultiHandleSliderTarget target in slider.MultiHandleSliderTargets)
   7:             target.ControlID = e.Row.FindControl(target.ControlID).ClientID; 
   8:     }
   9: }

Tags: , , , ,

.NET | ASP .NET | ASP.NET AJAX

AutoComplete Extender - alcuni workaround

by Andrea 04 April 2008 14:04

BoxRicercaStò utilizzando il controllo AutoComplete Extender, contenuto negli Ajax Control Toolkit, e mi sono trovato ad affrontare diversi problemi dovuti a bug del controllo ed altri dovuti a problemi con IE6.
Voglio però sottolineare che grazie alla flessibilità di questi controlli, sono riuscito facilmente a trovare alcuni workaround senza dover scrivere montagne di codice.

Nella mia applicazione mi trovo ad avere un controllo TextBox a cui è collegato l'AutoComplete Extender (per agevolare l'inserimento del testo), e posizionati subito sotto sono presenti alcune DropDownList.

Iniziamo dal primo problema:
con IE6, all'apertura del pannello dell'AutoComplete Extender, le DropDownList rimangono in primo piano, "bucando" il pannello.
La soluzione che ho trovato è stata quella di intervenire nelle animations, inserendo alcuni ActionScript che nascondono le DropDownList quando il pannello si apre, e le rivisualizzano non appena il pannello si stà chiudendo. In questo modo, l'AutoComplete Extender sarà visualizzato senza problemi grafici.

Altro problema:
alla chiusura del pannello non riuscivo più a modificare il valore delle DropDownList perchè il pannello viene nascosto impostando lo stile visibility, che lo fa quindi mantere in primo piano, bloccando l'accesso ai controlli posti sotto.
La soluzione più veloce è stata quella di intervenire anche qui nelle ActionScript, recuperandomi l'oggetto del pannello (che ha l'ID composto da BehaviorID__completionListElem) e settandogli la proprietà display a none. Facendo così, il pannello non risulta più essere in primo piano, e si ha l'accesso ai controlli in precedenza bloccati.

Ecco qui il codice per risolvere questi due problemi:

<ajaxToolkit:AutoCompleteExtender 
    runat="server" 
    BehaviorID="AutoCompleteEx" 
    ID="autoComplete1"
    TargetControlID="CittaCod" 
    ServiceMethod="GetCityList" 
    ServicePath="~/Services.asmx"
    MinimumPrefixLength="2" 
    CompletionInterval="1000" 
    FirstRowSelected="true" 
    EnableCaching="true"
    CompletionSetCount="20" 
    CompletionListCssClass="autocomplete_completionListElement"
    CompletionListItemCssClass="autocomplete_listItem" 
    CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem">
    <Animations>
    <OnShow>
        <Sequence>
            <OpacityAction Opacity="0" />
            <HideAction Visible="true" />
            <ScriptAction Script="
                var behavior = $find('AutoCompleteEx');
                if (!behavior._height) {
                    var target = behavior.get_completionList();
                    behavior._height = target.offsetHeight - 2;
                    target.style.height = '0px';
                }" />
            <Parallel Duration=".4">
                <FadeIn />
                <Length PropertyKey="height" 
                        StartValue="0" 
                        EndValueScript="$find('AutoCompleteEx')._height" />
            </Parallel>                                
            <ScriptAction Script="                 
                var ddlPrezzoMin = $get(ddlPrezzoMinID);
                var ddlPrezzoMax = $get(ddlPrezzoMaxID);
                var ddlMqMin = $get(ddlMqMinID);
                var ddlMqMax = $get(ddlMqMaxID);
                
                ddlPrezzoMin.style.visibility = 'hidden';
                ddlPrezzoMax.style.visibility = 'hidden';
                ddlMqMin.style.visibility = 'hidden';
                ddlMqMax.style.visibility = 'hidden'; 
                " />
        </Sequence>
    </OnShow>
    <OnHide>
        <Sequence>
            <ScriptAction Script="    
                var ddlPrezzoMin = $get(ddlPrezzoMinID);
                var ddlPrezzoMax = $get(ddlPrezzoMaxID);
                var ddlMqMin = $get(ddlMqMinID);
                var ddlMqMax = $get(ddlMqMaxID);
                
                ddlPrezzoMin.style.visibility = 'visible';
                ddlPrezzoMax.style.visibility = 'visible';
                ddlMqMin.style.visibility = 'visible';
                ddlMqMax.style.visibility = 'visible';
                
                var autoCompleteElement = $get('AutoCompleteEx_completionListElem');
                autoCompleteElement.style.display = 'none';                                    
                " />
            <Parallel Duration=".4">
                <FadeOut />
                <Length 
                    PropertyKey="height" 
                    StartValueScript="$find('AutoCompleteEx')._height" 
                    EndValue="0" />
            </Parallel>
        </Sequence>
    </OnHide>
    </Animations>
</ajaxToolkit:AutoCompleteExtender>

 

Tags: , , , ,

ASP.NET AJAX

AJAX Control Toolkit Tabs, nascondere un TabPanel

by Andrea 06 July 2007 11:07

Da un post fatto nei newsgroup sono venuto a conoscenza di uno strano comportamento che affligge i TabPanel del controllo Tabs degli AJAX Control Toolkit e ho trovato un semplice workaround.
CropperCapture[5]

Infatti, se dovete nascondere un tab, viene spontaneo usare la proprietà Visible del TabPanel da nascondere ( e direi che la cosa, a mio avviso, sarebbe una cosa ovvia) ma non è così.
Impostando a false la proprietà Visible del primo TabPanel (per esempio), il tab viene correttamente nascosto, ma rimane visibile il testo contenuto nel HeaderText.

TabPippo.Visible = false;
CropperCapture[6]

Per risolvere questo inconveniente, al posto di utilizzare la proprietà Visible usate la proprietà Enabled, che farà nascondere completamente il tab in questione.

TabPippo.Enabled = false;
CropperCapture[7]

Il perchè di questi comportamenti non me lo spiego... Quello che mi sarei aspettato invece è che la proprietà Visible, se impostata a False, nascondesse completamente il tab, mentre l'Enabled a True che mi disabilitasse il click in modo da non poter abilitare quel TabPanel (e il tab dovrebbe rimanere visibile), ma forse sarebbero stati dei comportamenti troppo normali.

...ma l'importante è conoscerli ed eventualmente trovare dei workaround come questo (in tempi brevi).... ;)

Tags: , , ,

ASP.NET AJAX

Creare un Control Extender, da dove cominciare

by Andrea 19 June 2007 23:06

AspNetAjax Se avete intenzione di cimentarvi a creare un Control Extender sappiate che la cosa è più semplice di quello che credete.

Per cominciare vi consiglio alcuni link:
Il primo è un tutorial che trovate nel sito di ASP .NET AJAX e vi guiderà passo passo: Creating a new extender

Un'altra risorsa molto utile è il webcast tenuto da :
ASP.NET 2.0 AJAX: Extending ASP.NET AJAX

Ed infine il link al progetto AJAX Control Toolkit. All'interno del progetto scaricato è disponibile anche il pacchetto di installzione per aggiungere il template per creare un Control Extender (il file si chiama AjaxControlExtender.vsi) e permetterà di creare in automatico i file necesssari allo sviluppo di un Extender (file *Behavior.js, *Designer.cs ed *Extender.cs): AJAX Control Toolkit

Tags: , , , ,

ASP.NET AJAX

AJAX Control Toolkit - ConfirmButtonExtender in una colonna di cancellazione

by Andrea 21 March 2007 13:03

Queste sono le cose che mi piacciono, quando con poche righe di codice si risolve immediatamente un problema. Infatti con una riga di markup è possibile aggiungere ad un button una messagebox di conferma, che io utilizzo (ad esempio) quando devo eseguire delle cancellazioni, e tutto grazie al ConfirmButtonExtender. (così non serve neanche scrivere javascript) In questo esempio, ho usato il ConfirmButtonExtender in una colonna di cancellazione creamdomi un colonna con un TemplateField.

<asp:TemplateField > 
   <ItemTemplate> 
        <asp:LinkButton 
            CommandName="delete" 
            runat="server" 
            ID="deleteRecord" 
            Text="delete" /> 
        <ajaxControlToolkit:ConfirmButtonExtender 
            ID="bDeleteExtender" 
            runat="server"
            TargetControlID="deleteRecord" 
            ConfirmText="Sicuro di voler cancellare?" /> 
   </ItemTemplate> 
</asp:TemplateField>
 Bello, semplice e funziona

Tags: , ,

ASP.NET AJAX