2010-03-18 3 views
3

En regardant les extensions réactives pour la démo javascript sur Jeff Van Gogh's blog, j'ai pensé que je ferais un essai en C#/Winforms, mais cela ne semble pas fonctionner aussi bien.Le temps passe comme une démo de flèches dans WinForms

Je viens de jeter cela dans le constructeur d'un formulaire (avec le cadre Rx installé et référencé):

Observable.Context = SynchronizationContext.Current; 
var mousemove = Observable.FromEvent<MouseEventArgs>(this, "MouseMove"); 
var message = "Time flies like an arrow".ToCharArray(); 

for(int i = 0; i < message.Length; i++) 
{ 
    var l = new Label() 
      { 
       Text = message[i].ToString(), 
       AutoSize = true, 
       TextAlign = ContentAlignment.MiddleCenter 
      }; 
    int closure = i; 
    mousemove 
     .Delay(closure * 150) 
     .Subscribe(e => 
      { 
       l.Left = e.EventArgs.X + closure * 15 + 10; 
       l.Top = e.EventArgs.Y; 
       //Debug.WriteLine(l.Text); 
      }); 
    Controls.Add(l); 
} 

Lorsque je déplace la souris, les lettres semblent se déplacer dans un ordre aléatoire, et si Je décommenter la ligne de débogage, je vois plusieurs événements pour la même lettre ...

Des idées? J'ai essayé Throttle, mais cela ne semble pas faire de différence. Est-ce que je demande juste trop de WinForms pour déplacer toutes ces étiquettes autour?

(Cross posté sur Rx Forum)

+1

Avez-vous essayé WPF ? – jrista

+0

@jrista: Pas encore – Benjol

Répondre

2

croix réponse réaffecté de Rx Forum (si l'auteur est ici et veut réclamer, c'est bien pour moi):

Problème n ° 1: Vous êtes en utilisant des vieux morceaux. Observable.Context était parti il ​​y a environ 4 versions. Problème n ° 2: Javascript n'a aucun concept de threads, et Rx aime mettre des choses sur d'autres threads pour vous.

Ainsi, en utilisant les derniers morceaux, la solution ressemble à ceci:

void Form1_Load(object sender, EventArgs e) 
{ 
    Reactive("Time flies like an arrow"); 
} 

private void Reactive(string msg) 
{ 
    var mousemove = Observable.FromEvent<MouseEventArgs>(this, "MouseMove"); 
    var message = msg.ToCharArray(); 

    for(int i = 0; i < message.Length; i++) 
    { 
     var l = new Label() 
     { 
      Text = message[i].ToString(), 
      AutoSize = true, 
      TextAlign = ContentAlignment.MiddleCenter 
     }; 
     int closure = i; 
     mousemove 
      .Delay(TimeSpan.FromSeconds(0.07 * i), Scheduler.Dispatcher) 
      .Subscribe(e => 
      { 
       l.Left = e.EventArgs.X + closure * 12 - 5; 
       l.Top = e.EventArgs.Y + 15; 
      }); 
     Controls.Add(l); 
    } 
} 

Notez que le ObserveOnDispatcher et SubscribeOnDispatcher. Cela nous rapproche de la version Javascript, mais le filetage est le vrai problème ici.

MISE À JOUR, a ajouté la correction de Jeff Van Gogh dans le code ci-dessus


Juste pour le plaisir, voici un rendu vague de la même chose sans Rx:

private void Unreactive(string msg) 
{ 
    var message = msg.ToCharArray(); 

    for(int i = 0; i < message.Length; i++) 
    { 
     var l = new Label() 
     { 
      Text = message[i].ToString(), 
      AutoSize = true, 
      TextAlign = ContentAlignment.MiddleCenter 
     }; 
     Controls.Add(l); 
     int closure = i; 
     this.MouseMove += (s, e) => LabelDelayMove(closure, e, l); 
    } 
} 

private void LabelDelayMove(int i, MouseEventArgs e, Label l) 
{ 
    Point p = new Point(e.X + i * 12 - 5, e.Y - 15); 
    var timer = new System.Threading.Timer((_) => LabelMove(l, p), null, i * 70, System.Threading.Timeout.Infinite); 
} 

private void LabelMove(Label l, Point location) 
{ 
    this.BeginInvoke(new Action(() => l.Location = location)); 
} 
+0

Lien vers le message original? Ah, je le vois dans votre question, mais pas cette réponse. –

+0

@Richard, yup, j'ai ajouté un lien à la question, mais je ne peux pas pour la vie de moi voir où il pourrait y avoir un lien vers la réponse. Ils devraient vraiment laisser tomber leurs forums et venir ici pour rejoindre la fête! – Benjol

Questions connexes