OVH Cloud OVH Cloud

User Controls et pattern observateur

9 réponses
Avatar
Mielmonster
Bonjour,

je dispose de deux user controls qui seront situés sur la même page.
le premier est une barre de controles simple (movenext, moveprevious) qui
est appelee a controler le deuxieme qui est une liste de produits.

afin de gerer cela, j'ai decide d'utiliser un pattern observateur.
ce qui implique que le control liste s'inscrit aupres du controle commande.
quand l'utilisateur clique sur next ou previous du control commande, je
notifie le control liste et lui dit de defiler vers l'avant ou vers
l'arriere.

malheureusement, tout se fait bien mais le control liste n'est pas
rafraichi.

savez vous comment forcer ce control a se rafraichir.

d'autre part, j'imagine que la meilleure methode .Net pour gerer ce type de
comportement serait d'utiliser un delegate qui est beaucoup moins java-like
que l'observateur mais... je n'ai pas du tout compris comment marchent les
delegates de .Net.

donc si qqn se sent d'humeur pedagogue... ;-)

merci d'avance

Yannick

9 réponses

Avatar
Boris Sargos
Salut,

le delegate n'est pas une notion compliquée. Dans le cas d'un délégué
"simple", tu peux le comparer à un pointeur sur fonction en C++ : ça revient
au même.
Les délégués multicast sont plus sophistiqués. Je ne suis pas (encore !) un
maître en C#, mais je peux t'expliquer ce que j'ai compris de leur
utilisation dans le cas du déclenchement d'évènements. En fait, il s'utilise
lorsque tu cherches à "prévenir" plusieurs objets distincts d'un évènement.
Je ne sais pas vraiment si c'est ton cas..
Dis-moi lequel des deux tu souhaites que je t'explique, et c'est parti ...
En tous cas, si tu veux que tes objets soient indépendants, l'approche
Observateur me semble plus judicieuse.

A+
Avatar
Mielmonster
salut,

merci pour ta reponse.

effectivement, je souhaiterais que mes deux objets (qui sont deux web user
controls) soient independants.
mais alors peut etre as-tu la solution a mon probleme. la communication
entre les deux est bien faite (dans mon test, je mets a un jour un label),
mais le label en question n'est jamais affiche car le web user control ne se
recharge pas...

en ce qui concerne les delegates, je serais interesse par les deux mais
surtout par les delegates multicast pour les evenements.

a+

Yannick

----- Original Message -----
From: "Boris Sargos"
Newsgroups: microsoft.public.fr.dotnet.csharp
Sent: Wednesday, October 13, 2004 5:42 PM
Subject: Re: User Controls et pattern observateur


Salut,

le delegate n'est pas une notion compliquée. Dans le cas d'un délégué
"simple", tu peux le comparer à un pointeur sur fonction en C++ : ça
revient
au même.
Les délégués multicast sont plus sophistiqués. Je ne suis pas (encore !)
un
maître en C#, mais je peux t'expliquer ce que j'ai compris de leur
utilisation dans le cas du déclenchement d'évènements. En fait, il
s'utilise
lorsque tu cherches à "prévenir" plusieurs objets distincts d'un
évènement.
Je ne sais pas vraiment si c'est ton cas..
Dis-moi lequel des deux tu souhaites que je t'explique, et c'est parti ...
En tous cas, si tu veux que tes objets soient indépendants, l'approche
Observateur me semble plus judicieuse.

A+




Avatar
Pascal Mercier
Bonjour,

Les delegates sont des types qui définissent la signature d'une méthode
(ordre+type de paramètres). Lorsqu'on déclare ensuite un objet du type du
delegate on peut le transmettre à un autre objet qui sera donc capable de
l'invoquer. La seul contrainte est donc de respecter la fameuse signature de
la méthode déléguée.
En gros, s'il fallait imager le truc, ce serait de dire à un objet donné :
"he ! je te donne un pointeur sur une méthode qui est chez moi, tu peux me
rappeler quand tu veux...". Bon, ca c'est le B-A-B-A.
Voici un tutorial pour mettre en pratique :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcwlkdelegatestutorial.asp

Mais pour revenir à ton problème, la méthode la plus adaptée est
l'utilisation d'événements. Dans ton cas, le contrôle liste s'abonne au
contrôle Commande lorsque l'on clique sur des liens (ou des boutons ou des
images) qui correspondent au "MoveNext" ou "MovePrevious". Mais à la limite,
tu n'as même pas besoin de définir tes propres événements, puisque si tu
composes le contrôle Commande avec des liens (type Hyperlink par exemple),
tu "accroches" la liste aux événements Click du lien et ça se fait tout
seul.

Ceci dit, les événements se codent en utilisant les delegates. Le principe
est qu'un objet expose un événement (mot-clé event) d'un type de delegate
donné. L'event s'appelle alors comme une méthode (éventuellement, on peut y
passer des paramètres, les EventArgs). Le fait d'appeler un membre de type
event déclenche l'invocation de tous les "clients" qui se sont abonnés à cet
événement. Pour s'abonner, les "clients" utilise une syntaxe du type:
Objet1.TheEvent += new EventHandler(NomDeMethode);

Objet1 est l'objet qui détient le membre de type event qui déclenchera
l'événement
TheEvent est l'événement lui-même
+= pour dire : "je m'ajoute à la liste des abonnés à cet événement"
new EventHandler(NomDeMethode), où NomDeMethode est le nom de la méthode que
Objet1 doit invoquer lorsqu'il déclenchera son événement. Ceci à pour effet
de créer un delegate à rappeler.
Voilà, j'espère ne pas avoir été trop confus, mais ce n'est jamais super
trivial d'expliquer les événéments.

Mais si les événements t'interesse, regarde aussi le tutorial :
http://msdn.microsoft.com/library/en-us/csref/html/vcwlkEventsTutorial.asp?frame=true

Bonne lecture,
Cordialement,

Pascal Mercier
Microsoft France - MCS


"Mielmonster" a écrit dans le message de news:
416d4e41$0$7215$
salut,

merci pour ta reponse.

effectivement, je souhaiterais que mes deux objets (qui sont deux web user
controls) soient independants.
mais alors peut etre as-tu la solution a mon probleme. la communication
entre les deux est bien faite (dans mon test, je mets a un jour un label),
mais le label en question n'est jamais affiche car le web user control ne
se
recharge pas...

en ce qui concerne les delegates, je serais interesse par les deux mais
surtout par les delegates multicast pour les evenements.

a+

Yannick

----- Original Message -----
From: "Boris Sargos"
Newsgroups: microsoft.public.fr.dotnet.csharp
Sent: Wednesday, October 13, 2004 5:42 PM
Subject: Re: User Controls et pattern observateur


Salut,

le delegate n'est pas une notion compliquée. Dans le cas d'un délégué
"simple", tu peux le comparer à un pointeur sur fonction en C++ : ça
revient
au même.
Les délégués multicast sont plus sophistiqués. Je ne suis pas (encore !)
un
maître en C#, mais je peux t'expliquer ce que j'ai compris de leur
utilisation dans le cas du déclenchement d'évènements. En fait, il
s'utilise
lorsque tu cherches à "prévenir" plusieurs objets distincts d'un
évènement.
Je ne sais pas vraiment si c'est ton cas..
Dis-moi lequel des deux tu souhaites que je t'explique, et c'est parti
...
En tous cas, si tu veux que tes objets soient indépendants, l'approche
Observateur me semble plus judicieuse.

A+








Avatar
Boris Sargos
Yannick,

je ne connais pas du tout la programmation web. Je ne suis pas en mesure de
te donner une solution.
En ce qui concerne les délégués multicast, lors de l'application aux
évènements, c'est un mécanisme non trivial qui nécessite trois étapes. On va
supposer que tu as créé un contrôle dont la fonction principale est
d'effectuer un calcul :
public class MyControl : Control {
... // données membres
public double Calculate() { ... }
}

De deux choses l'une :
- ou le calcul est court, et dans ton programme client de MyControl, tu
peux écrire une chose telle que :
MyControl mycontrol = new MyControl();
int result = mycontrol.Calculate();
...
et tout marche bien,

- ou le calcul est long, et le code précédent n'est pas enviqgeable,
sous peine de bloquer le programme un long moment. Dans ce cas, dans ta
fonction Calculate, tu crées un thread pour ne pas bloquer le programme.
Mais, si tu connais un peu les threads, tu sais bien que le client de
MyControl qui a appelé Calculate() n'a aucune chance d'avoir de réponse,
puisque MyControl ne connait ce client pas a priori (suis-je clair ?).
Donc, là encore, deux solutions sont possibles :
- dans le constructeur de MyControl, tu peux prendre une
référence sur l'objet MyClient qui contient une donnée membre Result, à qui
renvoyer le résultat :

public class MyClient {
... // données membres
int m_Result;
public int Result {
set { m_Result = value; }
}
}

public class MyControl : Control {
public MyControl(MyClient client) { m_Client = client; }
... // données membres
object m_Client = null;
public void Calculate() { // La fonction devient de type
void
...
// Le calcul est terminé :
m_Client.Result = #resultat#;
}
}

MyClient myclient = new MyClient();
MyControl mycontrol = new MyControl(myclient);
mycontrol.Calculate();
// L'affectation du résultat se fera dans la classe MyClient, une
fois le thread terminé

Ca n'est pas très esthétique, et en plus, ça contraint d'utiliser un type
MyClient ou un dérivé. Une variante serait d'utiliser une interface. Ce
serait moins inélégant et moins contraignant, mais tout aussi inefficace.
En C++, on aurait utilisé un pointeur de fonction. En C#, on utilise un
delegué :

public delegate void ResultEventHandler(int result); //
délégué qui prend un int en paramètre

le code devient :


public class MyClient {
... // données membres
int m_Result;
public void OnResult(int result) { m_Result = result; }
}

public class MyControl : Control {
public MyControl(ResultEventHandler mydelegate) { m_MyDelegate mydelegate; }
... // données membres
private ResultEventHandler m_MyDelegate = null;
public void Calculate() { // La fonction devient de type
void
...
// Le calcul est terminé :
m_MyDelegate(#resultat#); // C'est aussi
simple que cela !
}
}

MyClient myclient = new MyClient();
MyControl mycontrol = new MyControl(new
ResultEventHandler(MyClient.OnResult);
mycontrol.Calculate();
// L'affectation du résultat se fera dans la classe MyClient, une
fois le thread terminé

Voilà ce que tu pourrais utiliser dans ton code. Maintenant, supposons que
plusieurs classes soient intéresées par le résultat du calcul. Tu
souhaiterais donc "avertir" plusieurs objets en même temps que le calcul
aété effectué. C'est là qu'interviennent les délégués multicast. A priori,
c'est le même principe, à une différence près que le délégué multicast va
collecter tous les clients qu'il devra avertir, et les avertira le moment
venu par le biais d'un évènement. Lors de la compilation, tu ne connais pas
encore les clients. Et ça, c'est un gros avantage.

public class MyClient {
... // données membres
int m_Result;
public void OnResult(int result) { m_Result = result; }
}

public class MyControl : Control {
public MyControl() { ... }
// Plus de constructeur avec un délégué en paramètre
... // données membres
public event ResultEventHandler MyEvent;
// m_MyEvent est de type ResultEventHandler : c'est un délégué
public void Calculate() { // La fonction devient de type
void
...
// Le calcul est terminé :
m_MyDelegate(#resultat#); // C'est aussi
simple que cela !
}
}

MyClient1 myclient1 = new MyClient1();
MyClient2 myclient2 = new MyClient2();
MyControl mycontrol = new MyControl();
mycontrol1.MyEvent += new ResultEventHandler(mycontrol1.OnResult);
mycontrol2.MyEvent += new ResultEventHandler(mycontrol2.OnResult);
mycontrol.Calculate();
// L'affectation du résultat se fera dans les classe MyClient, une
fois le thread terminé.


Voilà. J'espère que c'est déjà un peu plus clair chez toi désormais. Si tu
ne comrends pas, n'hésite pas à me recontacter.
A+
Avatar
Mielmonster
bonjour,

j'aurais, si possible, besoin de precision sur cette partie du texte.
je ne vois pas bien comment faire cela et si ca peut se faire tout seul,
pourquoi s'en priver !
je ne vois pas bien comment accrocher la liste aux evenements click car a
priori ils ne se connaissent pas (ils sont dans deux user controls
differents)

merci d'avance

Yannick


Mais à la limite, tu n'as même pas besoin de définir tes propres
événements, puisque si tu composes le contrôle Commande avec des liens
(type Hyperlink par exemple), tu "accroches" la liste aux événements Click
du lien et ça se fait tout seul.


Avatar
Pascal Mercier
Autant pour moi, la classe Hyperlink n'expose pas d'événement de type Click.
Elle pourrait cependant être utiliser pour créer des paramètres dans l'Url,
mais ce n'est pas le sujet. Vous pourriez donc utiliser des classes comme
HtmlAnchor, ImageButton, Button, etc...bref tout contrôle qui expose des
événements de type Click serveur.
Revenons à nos événements. Partons du principe que le contrôle Commande
héberge des contrôles HtmlAnchor qui sont soit créés dynamiquement par code,
soit placés manuellement dans le contrôle. Ces contrôles HtmlAnchor étant
imbriqués dans le contrôle Commande ils ne sont pas visibles directement par
un autre contrôle de la page, ni par la page elle-même. Il est donc de la
responsabilité du contrôle Commande d'exposer ces Hyperlink via des
propriétés public.
A partir de là, on ramène le contexte à quelque chose d'ordinaire pour une
page ASP.NET, à savoir que les événéments click des Hyperlink sont
accessibles à partir de la page (ou d'un autre contrôle) et que l'on peut
alors s'abonner à leurs événements.
J'évoque l'utilisation de UserControls, mais la démarche est identique pour
des classes de type WebControls.

Pour le code, cela pourrait donner qqchose comme ça.

Voici la classe UserControl de type Commande (tronquée du code autogénéré
par le framework):
public class Commande : System.Web.UI.UserControl
{
protected System.Web.UI.HtmlControls.HtmlAnchor MovePrevious;
protected System.Web.UI.HtmlControls.HtmlAnchor MoveNext;

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}

public HtmlAnchor Previous
{
get
{
return MovePrevious;
}
}

public HtmlAnchor Next
{
get
{
return MoveNext;
}
}
....// Ici le code autogénéré par le FW 1.1
}

Voici le code behind de la page (tronquée du code autogénéré par le
framework):
public class WebForm2 : System.Web.UI.Page
{
protected Commande MoveCommande; // Contrôle UserControl exposant ses
HtmlAnchor interne. Peut-être mis aussi dans la méthode InitializeComponent.

private void Page_Load(object sender, System.EventArgs e)
{
MoveCommande.Previous.ServerClick +=new
EventHandler(Previous_ServerClick);
MoveCommande.Next.ServerClick +=new EventHandler(Next_ServerClick);
}

private void Previous_ServerClick(object sender, EventArgs e)
{
// Action sur le click de Précédent
}

private void Next_ServerClick(object sender, EventArgs e)
{
// Action sur le click de Suivant
}
....// Ici le code autogénéré par le FW 1.1
}

Cordialement,
Pascal Mercier
Microsoft France - MCS

"Mielmonster" wrote in message
news:416e23d0$0$28825$
bonjour,

j'aurais, si possible, besoin de precision sur cette partie du texte.
je ne vois pas bien comment faire cela et si ca peut se faire tout seul,
pourquoi s'en priver !
je ne vois pas bien comment accrocher la liste aux evenements click car a
priori ils ne se connaissent pas (ils sont dans deux user controls
differents)

merci d'avance

Yannick


>Mais à la limite, tu n'as même pas besoin de définir tes propres
>événements, puisque si tu composes le contrôle Commande avec des liens
>(type Hyperlink par exemple), tu "accroches" la liste aux événements


Click
>du lien et ça se fait tout seul.





Avatar
Mielmonster
Merci pour les infos.
j'ai essaye d'implementer votre methode mais le principe de lier les deux
controles ne me plait pas trop.
apres plusieurs essais, j'en suis arrive au code suivant :

sur le web control qui contient les commandes :

public delegate void PaginationChangedEventHandler(object sender,
PaginationChangedEventArgs pce);
public event PaginationChangedEventHandler PaginationChangedEvent;

private void lnkBtnNext_Click(object sender, System.EventArgs e)
{
if (PaginationChangedEvent != null)
PaginationChangedEvent(this, new
PaginationChangedEventArgs(PaginationChangedEventArgs.MoveEnum.MoveNext));
}

private void lnkBtnPrevious_Click(object sender, System.EventArgs e)
{
if (PaginationChangedEvent != null)
PaginationChangedEvent(this, new
PaginationChangedEventArgs(PaginationChangedEventArgs.MoveEnum.MovePrevious));
}

sur le controle de liste :

public void OnPaginationChanged(object sender, PaginationChangedEventArgs
pce)
{
// traitement a effectuer sur la liste
int val = Convert.ToInt32(Label1.Text);
if (pce.Move == PaginationChangedEventArgs.MoveEnum.MoveNext)
val++;
else
val--;
Label1.Text = val.ToString();
}

et enfin, je lie les deux sur ma page de test :

override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
this.UcSelectRubrique1.PaginationChangedEvent +=new
FrontOffice.UserControls.ucSelectRubrique.PaginationChangedEventHandler(this.Liste1.OnPaginationChanged);
this.UcSelectRubrique2.PaginationChangedEvent +=new
FrontOffice.UserControls.ucSelectRubrique.PaginationChangedEventHandler(this.Liste1.OnPaginationChanged);
}

ai-je trouve la bonne methode ?
j'apprecie celle-ci car a priori les deux controls ne se connaissent pas.
l'un d'eux leve un evenement, l'autre se contente de capter un certain
nombre d'evenements.

qu'en pensez vous ?

Yannick
Avatar
Pascal Mercier
Ce qui est semblable entre votre code et le mien, c'est que les contrôles,
de toute façon, ne se connaissent pas à l'avance. Les contrôles qui
s'abonnent ne sont pas connus à l'avance.
Ce qui est différent entre votre code et le mien, c'est que vous encapsulez
les événements click du contrôle des commandes dans un événements unique qui
passe en paramètre le sens du click (next ou previous). C'est sans doute
plus élégant mais fonctionnellement cela revient quelque part au même.
L'élégance, en effet, se situe dans le fait que les contrôles à cliquer dans
la commande peuvent être changer (passer d'un HtmlAnchor à un ImageButton)
sans modification de la méthode d'abonnement. De ce point de vue, ma méthode
est un raccourci de la vôtre en figeant "en dur" le type de bouton à
cliquer.
Conclusions:
- Les deux méthodes sont parfaitement viables.
- suivant votre approche, je vous suggère d'aller jusqu'au bout de la
logique et de développer un véritable custom control.

A lire :
Building a DataNavigator Control :
http://msdn.microsoft.com/msdnmag/issues/02/04/cutting/toc.asp?frame=true. A
priori, cet article décrit, avec code à l'appui, exactement ce que vous
souhaitez réaliser.
Building a Data Navigator Control, Part III :
http://msdn.microsoft.com/msdnmag/issues/02/06/cutting/toc.asp?frame=true.
Developing a Templated Data-Bound Control :
http://msdn.microsoft.com/library/en-us/cpguide/html/cpcondevelopingtemplateddataboundcontrol.asp?frame=true
Templated Data-Bound Control Sample :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpcontemplateddataboundcontrolsample.asp

Cordialement,
Pascal Mercier
Microsoft France - MCS

"Mielmonster" wrote in message
news:416e48ab$0$7226$
Merci pour les infos.
j'ai essaye d'implementer votre methode mais le principe de lier les deux
controles ne me plait pas trop.
apres plusieurs essais, j'en suis arrive au code suivant :

sur le web control qui contient les commandes :

public delegate void PaginationChangedEventHandler(object sender,
PaginationChangedEventArgs pce);
public event PaginationChangedEventHandler PaginationChangedEvent;

private void lnkBtnNext_Click(object sender, System.EventArgs e)
{
if (PaginationChangedEvent != null)
PaginationChangedEvent(this, new
PaginationChangedEventArgs(PaginationChangedEventArgs.MoveEnum.MoveNext));
}

private void lnkBtnPrevious_Click(object sender, System.EventArgs e)
{
if (PaginationChangedEvent != null)
PaginationChangedEvent(this, new



PaginationChangedEventArgs(PaginationChangedEventArgs.MoveEnum.MovePrevious)
);
}

sur le controle de liste :

public void OnPaginationChanged(object sender, PaginationChangedEventArgs
pce)
{
// traitement a effectuer sur la liste
int val = Convert.ToInt32(Label1.Text);
if (pce.Move == PaginationChangedEventArgs.MoveEnum.MoveNext)
val++;
else
val--;
Label1.Text = val.ToString();
}

et enfin, je lie les deux sur ma page de test :

override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
this.UcSelectRubrique1.PaginationChangedEvent +=new



FrontOffice.UserControls.ucSelectRubrique.PaginationChangedEventHandler(this
.Liste1.OnPaginationChanged);
this.UcSelectRubrique2.PaginationChangedEvent +=new



FrontOffice.UserControls.ucSelectRubrique.PaginationChangedEventHandler(this
.Liste1.OnPaginationChanged);
}

ai-je trouve la bonne methode ?
j'apprecie celle-ci car a priori les deux controls ne se connaissent pas.
l'un d'eux leve un evenement, l'autre se contente de capter un certain
nombre d'evenements.

qu'en pensez vous ?

Yannick




Avatar
Mielmonster
merci beaucoup pour votre analyse et vos liens.

je vais m'empresser de les consulter.

encore merci pour votre aide

Yannick

"Pascal Mercier" a écrit dans le message de
news:
Ce qui est semblable entre votre code et le mien, c'est que les contrôles,
de toute façon, ne se connaissent pas à l'avance. Les contrôles qui
s'abonnent ne sont pas connus à l'avance.
Ce qui est différent entre votre code et le mien, c'est que vous
encapsulez
les événements click du contrôle des commandes dans un événements unique
qui
passe en paramètre le sens du click (next ou previous). C'est sans doute
plus élégant mais fonctionnellement cela revient quelque part au même.
L'élégance, en effet, se situe dans le fait que les contrôles à cliquer
dans
la commande peuvent être changer (passer d'un HtmlAnchor à un ImageButton)
sans modification de la méthode d'abonnement. De ce point de vue, ma
méthode
est un raccourci de la vôtre en figeant "en dur" le type de bouton à
cliquer.
Conclusions:
- Les deux méthodes sont parfaitement viables.
- suivant votre approche, je vous suggère d'aller jusqu'au bout de la
logique et de développer un véritable custom control.

A lire :
Building a DataNavigator Control :
http://msdn.microsoft.com/msdnmag/issues/02/04/cutting/toc.asp?frame=true.
A
priori, cet article décrit, avec code à l'appui, exactement ce que vous
souhaitez réaliser.
Building a Data Navigator Control, Part III :
http://msdn.microsoft.com/msdnmag/issues/02/06/cutting/toc.asp?frame=true.
Developing a Templated Data-Bound Control :
http://msdn.microsoft.com/library/en-us/cpguide/html/cpcondevelopingtemplateddataboundcontrol.asp?frame=true
Templated Data-Bound Control Sample :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpcontemplateddataboundcontrolsample.asp

Cordialement,
Pascal Mercier
Microsoft France - MCS

"Mielmonster" wrote in message
news:416e48ab$0$7226$
Merci pour les infos.
j'ai essaye d'implementer votre methode mais le principe de lier les deux
controles ne me plait pas trop.
apres plusieurs essais, j'en suis arrive au code suivant :

sur le web control qui contient les commandes :

public delegate void PaginationChangedEventHandler(object sender,
PaginationChangedEventArgs pce);
public event PaginationChangedEventHandler PaginationChangedEvent;

private void lnkBtnNext_Click(object sender, System.EventArgs e)
{
if (PaginationChangedEvent != null)
PaginationChangedEvent(this, new
PaginationChangedEventArgs(PaginationChangedEventArgs.MoveEnum.MoveNext));
}

private void lnkBtnPrevious_Click(object sender, System.EventArgs e)
{
if (PaginationChangedEvent != null)
PaginationChangedEvent(this, new



PaginationChangedEventArgs(PaginationChangedEventArgs.MoveEnum.MovePrevious)
);
}

sur le controle de liste :

public void OnPaginationChanged(object sender, PaginationChangedEventArgs
pce)
{
// traitement a effectuer sur la liste
int val = Convert.ToInt32(Label1.Text);
if (pce.Move == PaginationChangedEventArgs.MoveEnum.MoveNext)
val++;
else
val--;
Label1.Text = val.ToString();
}

et enfin, je lie les deux sur ma page de test :

override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
this.UcSelectRubrique1.PaginationChangedEvent +=new



FrontOffice.UserControls.ucSelectRubrique.PaginationChangedEventHandler(this
.Liste1.OnPaginationChanged);
this.UcSelectRubrique2.PaginationChangedEvent +=new



FrontOffice.UserControls.ucSelectRubrique.PaginationChangedEventHandler(this
.Liste1.OnPaginationChanged);
}

ai-je trouve la bonne methode ?
j'apprecie celle-ci car a priori les deux controls ne se connaissent pas.
l'un d'eux leve un evenement, l'autre se contente de capter un certain
nombre d'evenements.

qu'en pensez vous ?

Yannick