Syndication : Atom 1.0  RSS 2.0
Blogs des développeurs   »   Blog de lutecefalco

Article complet: [ASP.NET] Créer une ComboBox avec l'aide de l'AJAX Control Toolkit

23/11/2008

Permalink 23:22:09, Catégories: Récapitulatif .NET, ASP.NET, AJAX, 1151 mots   French (FR) , lutecefalco

[.NET] [ASP.NET] Créer une ComboBox avec l'aide de l'AJAX Control Toolkit

J'ai récemment eu besoin de remplacer une liste déroulante par une ComboBox dans l'une de mes applis web.
Pour rappel, une ComboBox est une liste déroulante qui offre également la possibilité de saisir le texte de son choix (une liste déroulante ne permet que de sélectionner l'un de ses items).

Ma liste déroulante proposait une série de nombres compris entre 1 et 1000 avec un pas qui augmentait régulièrement (pas de 1 entre 0 et 100, pas de 10 entre 100 et 500 et pas de 25 entre 500 et 1000). Il fallait offrir à l'utilisateur la possibilité de saisir une valeur non existante dans la liste déroulante (108 par exemple).

Après quelques recherches sur internet, je n'avais trouvé que des composants payants ou qui ne fonctionnaient pas vraiment. En regardant du côté de l'AJAX Control Toolkit, je suis tombé sur le DropDownExtender (démo). Je me suis dit que ça pouvait faire l'affaire et je suis parti dans cette direction.

[Suite:]

Le principe du DropDownExtender est d'afficher un contrôle lors du clic le contrôle qu'étend le DropDownExtender.
Pour réaliser une ComboBox, on va utiliser une TextBox que l'on va étendre avec le DropDownExtender et on va faire afficher un Panel. Ce panel contiendra les différents items initialement contenus dans la liste déroulante. Afin de remplir la TextBox avec la valeur de l'item sélectionné dans le Panel, chaque item se présentera sous la forme d'un lien et on appellera une fonction javascript sur le onclick pour remplir la TextBox.

Définition de la TextBox, du DropDownExtender et du Panel:
<!-- La TextBox --> 
<asp:TextBox ID="tbSpread" runat="server" Width="143px"></asp:TextBox> 
<!-- Le DropDownExtender --> 
<act:DropDownExtender  
  ID="ddeSpread"  
  runat="server"  
  TargetControlID="tbSpread" 
  DropDownControlID="pnlSpread" 
  HighlightBackColor="white"> 
</act:DropDownExtender> 
<!-- Le Panel --> 
<asp:Panel  
  ID="pnlSpread"  
  runat="server"  
  Height="200px"  
  ScrollBars="Vertical"  
  CssClass="ContextMenuPanel"  
  style="display: none; visibility: hidden;"> 
  <asp:Literal ID="ltSpread" runat="server" EnableViewState="false"> 
  </asp:Literal> 
</asp:Panel>

Concernant la TextBox, rien à dire.
Concernant le DropDowExtender:
- TargetControlID indique quel contrôle étendre, c'est-à-dire quel est le contrôle sur lequel un clic entrainera l'affichage d'un autre contrôle.
- DropDownControlID correspond à l'ID du contrôle qui sera affiché
Concernant le panel, il contient un Literal qui contiendra les liens correspondants aux items à afficher.

Remplissage du panel (code behind):
   private void FillPanel()
   {
        var sb = new StringBuilder();

        // Pas = 1 entre 0 à 100. 
        for (var i = 0; i < 101; i++)
        {
            sb.AppendFormat(GenerateLink(i));
        }

        // Pas = 10 entre 100 et 500. 
        for (var i = 110; i < 501; i += 10)
        {
            sb.AppendFormat(GenerateLink(i));
        }

        // Pas = 25 entre 500 et 1000.
        for (var i = 525; i < 1001; i += 25)
        {
            sb.AppendFormat(GenerateLink(i));
        }

        ltSpread.Text = sb.ToString();
    }

    private string GenerateLink(int i)
    {
        var link = @"<a href=""javascript:OnItemSelected({0});"" class=""ContextMenuItem"">{0}</a>";

        return string.Format(link, i);
    }

On génère directement le code html correspondant aux items et on l'injecte dans le literal.
On remarque que le click sur un item appelle la fonction javascript OnItemSelected:

function OnItemSelected(value) 

    $get('<%= tbSpread.ClientID %>').value = value;
}


Cette fonction permet de remplir la TextBox avec la valeur de l'item sélectionné.

A ce niveau là, on devrait avoir une ComboBox fonctionnelle.
Voyons ce que cela donne en affichant la page:



On constate 3 problèmes:
(1) le Panel n'a pas la même longueur que la TextBox
(2) le Panel n'est pas aligné avec la TextBox
(3) le Panel apparaît en-dessous des listes déroulantes existantes

Pour le problème (1), on va utiliser un bout de code javascript qui va récupérer la longueur de la TextBox et l'appliquer au Panel:
function pageLoad()
{
       // On adapte la taille du panel à la taille de la textbox
       $get('<%= pnlSpread.ClientID %>').style.width = $get('<%= tbSpread.ClientID %>').clientWidth; 
}

La fonction pageLoad est une fonction proposée par ASP.NET AJAX et qui est automatiquement appelée à chaque chargement de la page.

Maintenant, on obtient:


Prochaine étape: aligner le Panel avec la TextBox (problème (2).
On va encore utiliser un bout de code javascript:

function pageLoad()
{
       // On adapte la taille du panel à la taille de la textbox
       $get('<%= pnlSpread.ClientID %>').style.width = $get('<%= tbSpread.ClientID %>').clientWidth; 

       // On aligne le côté gauche du panel avec le côté gauche de la textbox
       var chngPosition = $find('<%= ddeSpread.ClientID %>')._dropPopupPopupBehavior;
       chngPosition.set_positioningMode(2);
}

On obtient alors:



Le dernier problème à régler est dû à un bug bien connu de IE (une explication en français ici) . En effet, ce dernier ne gère pas correctement le z-index avec certains éléments HTML et du coup les listes déroulantes s'affichent au-dessus de notre Panel ici.

Une solution souvent évoquée est d'utiliser une IFRAME. Ne trouvant pas ça très "propre", je me suis orienté vers une solution javascript. L'idée est de masquer les listes déroulantes lors de l'affichage du Panel et de les réafficher lors du masquage de ce dernier.

Afficher/masquer un élément HTML en javascript se fait très simplement via la fonction suivante:

       function ShowHideControl(control, toShow)
        {
            if(control == null)
            return;

            if(toShow)
                control.style.visibility = 'visible';
            else
                control.style.visibility = 'hidden';
        }

La seule difficulté ici est de détecter l'affichage/masquage du Panel. Pour cela, il suffit de trouver le nom des événements levés par le DropDownExtender et s'y abonner. Dans un précédent billet, j'ai donné une astuce pour obtenir facilement ces événements. Les 2 événements qui nous intéressent ici sont donc "showing" et "hiding". Il ne nous reste plus qu'à s'y abonner et afficher/masquer les listes déroulantes. Le code javascript est le suivant:

        var bhvDde = $find('<%= ddeSpread.ClientID %>');
        bhvDde.add_showing(ShowPanelSpread);
        bhvDde.add_hiding(HidePanelSpread);

        function ShowPanelSpread()
        {
            ShowHideControl($get('<%= ddlPaymentFrequency.ClientID %>'), false);
            ShowHideControl($get('<%= ddlBasis.ClientID %>'), false);
            ShowHideControl($get('<%= ddlRoll.ClientID %>'), false);
            ShowHideControl($get('<%= ddlAdjustment.ClientID %>'), false);
            ShowHideControl($get('<%= ddlFixingFrequency.ClientID %>'), false);
            ShowHideControl($get('<%= ddlFixing.ClientID %>'), false);
        }

        function HidePanelSpread()
        {
            ShowHideControl($get('<%= ddlPaymentFrequency.ClientID %>'), true);
            ShowHideControl($get('<%= ddlBasis.ClientID %>'), true);
            ShowHideControl($get('<%= ddlRoll.ClientID %>'), true);
            ShowHideControl($get('<%= ddlAdjustment.ClientID %>'), true);
            ShowHideControl($get('<%= ddlFixingFrequency.ClientID %>'), true);
            ShowHideControl($get('<%= ddlFixing.ClientID %>'), true);
        }

Le résultat en image:




Have Fun!!!

Social Bookmarking:

                                     

Commentaires, Pingbacks:

Connectez-vous pour vous abonner à cet article:

Flux de commentaires pour cet article : Atom 1.0  RSS 2.0

Cet article n'a pas de Commentaires/Pingbacks pour le moment...

Vous devez être identifié pour poster un commentaire.

Liste des blogs

Blog de lutecefalco

Catégories


Rechercher

<  Février 2012  >
Lun Mar Mer Jeu Ven Sam Dim
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29        

Syndiquez ce blog XML

Articles :

Commentaires :

 
 
 
 
Partenaires

Hébergement Web