 |
Super-Logiciels pour vous |
 |
 |
ALYASSIR Gestion simple et performante :
- Facturation
- BLs
- Devis
- Commandes
- Reglements
- Clients et fournisseurs | | | |
Al Fondoki Logiciel de la gestion
hôteliere:
Réservations, main courante, poits de vente, dépôts, occupation des chambres, ... | | | |
Al Modabbir Beton Une version de Al Modabbir destinée aux entreprises dont l'activité est la production et vente du beton ... | | | |
Al Hassib Comptabilité générale, Liasse comptable marocaine ... | | | |
| Plus |
|
Avenue des F.A.R. Rsidence Niama N6 - Ttouan (Maroc)
Tl :(+212) 8 90 60 52 25
Fax :(+212) 5 39 97 25 15
Mobile :(+212) 6 61 10 74 37
Email :mce@meta-computer.com
|
|
|
|
Acceuil php, js(92) DOT
NET
|
| DOT
NET |
2009-04-30 |
|
Cet article vous présente comment faire
communiquer les différents éléments d'une page ASP.NET. On y verra comment faire communiquer une ContentPage avec sa
MasterPage, ainsi que comment faire communiquer un UserControl avec sa page mère.
A travers cet article, vous
allez voir comment faire communiquer une ContentPage avec sa MasterPage. Puis vous verrez comment faire communiquer un
UserControl avec sa page mère.
Le site web utilisé dans l'article est développé en C# /
ASP.NET avec Visual Studio 2008, et se nomme MasterPageContentPageUserControl.
La structure de la MasterPage, nommée
DvpMasterPage, est la suivante:
Le menu haut contiendra les liens permettant de
naviguer entre les différentes pages du site.
Le menu bas contiendra un bouton et une liste déroulante.
Le
pied de page contiendra un label.
Le code source est disponible à la fin de cet article.
I. Communication entre une MasterPage et une ContentPage
I-A. Communication de
la ContentPage vers la MasterPage
Comme évoqué plus haut, le pied de page de la MasterPage contient un label nommé
lblFooter, dont le texte par défaut est "Pied de page par défaut":
Le but ici est de pouvoir modifier le texte du label à partir de la
ContentPage.
On va imaginer le fonctionnement suivant:
- Une textbox et un bouton dans la ContentPage. Un
clic sur le bouton entraîne une mise à jour du texte du pied de page avec le texte saisi dans la textbox.
Code aspx:
Modifier le texte du footer:
I-A-1. La
méthode "pas propre"
La 1ère idée qui vient à l'esprit est d'utiliser la méthode FindControl de la classe
MasterPage, de caster l'objet Control récupéré en Label puis d'assigner une valeur à sa propriété Text.
Cela
donnerait:
protected void btnSubmit_Click(object sender, EventArgs e)
{
// On récupère le
label du pied de page
var footer = (Label)this.Master.FindControl("lblFooter");
footer.Text =
tbFooter.Text;
}
Cela fonctionne mais ce n'est pas vraiment idéal. Si
vous vous trompez dans le nom du label passé à la fonction FindControl, ou si quelques temps plus tard vous modifiez le nom
du label dans la MasterPage, vous aurez droit à une belle erreur lors de l'exécution du site web, alors que tout compile
correctement.
I-A-2. La méthode "propre"
L'idée ici est de définir,
au niveau de la MasterPage, une propriété qui mettra à jour le texte du label du pied de page.
Dans notre cas, une
propriété SetOnly suffit. Ce qui donne:
public string FooterText
{
set
{
lblFooter.Text = value;
}
}
L'étape suivante est
d'accéder à cette propriété depuis la ContentPage.
Ce qui donnerait:
protected void btnSubmit_Click
(object sender, EventArgs e)
{
this.Master.FooterText = tbFooter.Text;
}
Le problème est que ce code ne compile pas. D'ailleurs l'IntelliSense ne propose pas la propriété
FooterText.
La raison est simple: this.Master retourne un objet de type MasterPage,
et non un objet de type DvpMasterPage.
Une solution serait de caster cet
objet en DvpMasterPage. Ce qui donnerait:
protected void btnSubmit_Click(object sender, EventArgs e)
{
((DvpMasterPage) this.Master).FooterText = tbFooter.Text;
}
Cela
fonctionne et, maintenant, l'IntelliSense nous propose la propriété FooterText.
Il existe cependant une solution
plus élégante: la directive MasterType
Cette directive permet de fortement typer notre MasterPage. Au niveau du code
aspx de notre page, cela donne:
<%@ MasterType VirtualPath="~/DvpMasterPage.Master" %>
A partir de maintenant, la propriété Master de la ContentPage est fortement typée comme vous pouvez le voir:
Et la propriété FooterText est directement accessible. Cela donne finalement:
protected void btnSubmit_Click(object sender, EventArgs e)
{
this.Master.FooterText =
tbFooter.Text;
}
Pour info, le fait d'insérer la directive MasterType
surcharge la propriété Master dans le fichier designer.cs de la ContentPage, d'où le typage fort:
///
/// Master property.
///
///
/// Auto-generated
property.
///
public new DVP.MasterPageContentPageUserControl.DvpMasterPage Master {
get {
return ((DVP.MasterPageContentPageUserControl.DvpMasterPage)(base.Master));
}
}
I-B. Communication de la MasterPage vers la
ContentPage
Le but ici est de récupérer dans la ContentPage, un clic sur le bouton ou une
sélection dans la liste déroulante de la MasterPage.
Le principe est le
suivant:
Du côté de la MasterPage: déclarer des événements et les lever lors du clic sur le bouton ou lors de la
sélection d'un élément dans la liste déroulante
Du côté de la ContentPage: s'abonner aux événements de la
MasterPage
I-B-1. Côté MasterPage
On va déclarer 2 événements: un pour le clic sur le
bouton et un pour la sélection d'un élément dans la liste déroulante.
Cela donne:
public event
EventHandler ColorChanged;
public event EventHandler BoutonClicked;
Il reste
maintenant à lever ces événements au moment adéquat:
protected void btnMenu_Click(object sender, EventArgs e)
{
if (BoutonClicked != null)
BoutonClicked(sender, e);
}
protected void ddlColors_SelectedIndexChanged(object sender, EventArgs e)
{
if (ColorChanged !=
null)
ColorChanged(sender, e);
}
On va également avoir
besoin d'une propriété qui permet de récupérer l'élément sélectionné dans la liste déroulante:
public string
SelectedColor
{
get
{
return ddlColors.SelectedValue;
}
}
I-B-2. Côté ContentPage
Il faut commencer par
créer les gestionnaires d'événements ("Event Handler"). Un gestionnaire d'événement est la méthode qui va
s'exécuter en réponse à un événément.
private void Master_BoutonClicked(object sender, EventArgs e)
{
label.Text = string.Format("Vous avez cliqué sur le bouton de la MasterPage à {0}",
DateTime.Now.ToLongTimeString());
}
private void Master_ColorChanged(object sender, EventArgs e)
{
label.Text = "Vous avez sélectionné la couleur " + this.Master.SelectedColor;
}
Il faut ensuite s'abonner à ces événements lors du chargement de la page. C'est là
qu'interviennent les gestionnaires d'événéments définis précédemment:
protected void Page_Load(object sender,
EventArgs e)
{
this.Master.ColorChanged += Master_ColorChanged;
this.Master.BoutonClicked
+= Master_BoutonClicked;
}
On peut voir que l'IntelliSense propose les
événements définis dans la MasterPage
Dorénavant, la ContentPage est automatiquement
"avertie" de toute action sur le bouton ou la liste déroulante contenus dans la MasterPage.
II. Communication entre une Page et un UserControl
On va imaginer le scénario suivant:
Un
UserControl qui contient un contrôle Calendar
Une page aspx qui contient ce UserControl
A partir de la
page, on souhaite pouvoir spécifier le mois à afficher dans le Calendar
On souhaite récupérer au niveau de la page
la date sélectionnée par l'utilisateur dans le Calendar
II-A. Le UserControl
Côté
design, le UserControl comporte uniquement un contrôle Calendar:
<%@ Control Language="C#"
AutoEventWireup="true" CodeBehind="UcCalendar.ascx.cs" Inherits="DVP.MasterPageContentPageUserControl.UcCalendar"
%>
Il faut créer une
propriété qui sera utilisée pour spécifier le mois à afficher. Lorsque cette propriété sera settée, on affichera également le
Calendar qui est invisible par défaut:
public Constants.Months Month
{
set
{
Calendar1.VisibleDate = new DateTime(DateTime.Now.Year, (int)value, 1);
Calendar1.Visible =
true;
}
}
Le type Months est enum définie dans une classe
static:
public static class Constants
{
public enum Months
{
Janvier = 1,
Fevrier = 2,
Mars = 3,
Avril = 4,
Mai =
5,
Juin = 6,
Juillet = 7,
Aout = 8,
Septembre = 9,
Octobre = 10,
Novembre = 11,
Decembre = 12
}
}
Il faut également créer une propriété qui retournera la date sélectionnée dans le
Calendar:
public DateTime SelectedDate
{
get
{
return
Calendar1.SelectedDate;
}
}
La dernière étape consiste à mettre
en place le mécanisme qui a pour but d'informer la page qui contient le UserControl lorsque l'utilisateur sélectionne
une date dans le Calendar.
Une solution serait d'utiliser la méthode FindControl afin de
récupérer le Label puis d'assigner une valeur à sa propriété Text. Cela donnerait:
protected void
Calendar1_SelectionChanged(object sender, EventArgs e)
{
((Label)this.Parent.FindControl
("lblSelectedDate")).Text = string.Format("La date sélectionnée est {0}", Calendar1.SelectedDate.ToLongDateString
());
}
Encore une fois, cette solution est peu élégante. D'une part, on
n'est pas à l'abri d'une faute de frappe sur le nom du Label ou d'un renommage de ce dernier ultérieurement.
D'autre part, cela lie fortement le UserControl à la page, ce qui va à l'encontre du but d'un UserControl. En effet,
un UserControl a pour but d'être réutilisé à différents endroits. Que se passera-t-il si vous utilisez ce UserControl dans
une page qui ne contient pas de label intitulé lblSelectedDate? Vous aurez droit à une belle exception à l'exécution.
La bonne méthode est de créer un événement que l'on lévera lors de la sélection d'une date
dans le Calendar et qui sera intercepté par la page.
public event EventHandler SelectedDateChanged;
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
if (SelectedDateChanged
!= null)
SelectedDateChanged(sender, e);
}
II-B. La Page
Dans notre exemple, la page qui contient le UserControl est très simple. Outre le UserControl,
on y trouve également:
- une liste déroulante contenant la liste des mois
- un Label qui affichera la date
sélectionnée dans le Calendar du UserControl.
La liste déroulante a sa propriété AutoPostBack à
true. Ainsi, chaque sélection d'un élément entrainera automatiquement une mise à jour du Calendar.
ID="ddlMonths"
runat="server"
AutoPostBack="true"
onselectedindexchanged="ddlMonths_SelectedIndexChanged">
La liste déroulante est databindée au Page_Load à partir
des valeurs de l'enumération Months précédemment définie.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
ddlMonths.DataSource = Enum.GetNames(typeof
(Constants.Months));
ddlMonths.DataBind();
}
}
Lors de la sélection d'un élément dans la liste déroulante, et afin de mettre à jour le Calendar, il suffit
d'attribuer une valeur à sa propriété Month. Ce qui donne:
protected void ddlMonths_SelectedIndexChanged(object
sender, EventArgs e)
{
var selectedMonth = (Constants.Months)Enum.Parse(typeof(Constants.Months),
ddlMonths.SelectedValue);
UcCalendar1.Month = selectedMonth;
}
La dernière étape est de récupérer la date sélectionnée dans le Calendar et de l'afficher dans un Label. Pour cela,
il suffit de s'abonner à l'événement levé par le UserControl lors de la sélection d'une date.
Avant de
s'abonner à l'événement, il faut créer le gestionnaire d'événement, cette méthode qui sera appelée en réponse à un
événement. Ce gestionnaire aura la simple tâche d'afficher la date sélectionnée dans le Calendar. Pour cela, il suffit
d'utiliser la propriété du UserControl définie dans ce but. Cela donne:
protected void
UcCalendar1_SelectedDateChanged(object sender, EventArgs e)
{
lblSelectedDate.Text = string.Format
("La date sélectionnée est {0}", UcCalendar1.SelectedDate.ToLongDateString());
}
Il y a 2 façons de s'abonner à cet événement: de façon déclarative ou de façon programmatique.
De façon programmatique dans le Page_Load de la page:
protected void Page_Load(object
sender, EventArgs e)
{
UcCalendar1.SelectedDateChanged += new EventHandler
(UcCalendar1_SelectedDateChanged);
}
Ou alors de façon déclarative dans le
code aspx:
Notez qu'il faut
ajouter le nom de l'événement avec le préfixe "On" lors de la déclaration de façon déclarative.
Conclusion
Cet article vous a montré comment faire communiquer une MasterPage avec une ContentPage,
ainsi qu'un UserControl avec une Page.
Liens
Code source de l'exemple
Remerciements
Je remercie l'équipe Dotnet pour leurs relectures
attentives du document. |
| Commentaires des visiteurs : |
|
|
|
|
|