2009-02-26 5 views
1

J'ai le scénario suivant: lorsqu'un utilisateur déplace la souris hors d'un popup, je veux qu'une animation se produise, et cinq secondes plus tard, je veux enlever un Apparaitre.Silverlight: Threads/Actions retardées/Invocations/événements asynchrones

Ceci est le code que je comptais faire avec est:

private bool leftPopup = false; 
public void AnimatePopupOut(object sender, MouseEventArgs e) 
{ 
    myAnim.Begin(); 
    (new Thread(new ThreadStart(delayedRemovePopup))).Start(); 
} 

private void delayedRemovePopup() 
{ 
    leftPopup = true; 
    Thread.Sleep(5000); 
    PopUp.IsOpen = false; 
} 

La première ligne, "leftPopup = true" est très bien, mais le troisième, "PopUp.IsOpen = false" me donne un accès exception de violation, probablement parce que cet objet appartient au thread graphique. Est-il possible d'accéder à la propriété PopUp.IsOpen? Si non, y a-t-il un autre moyen que je puisse appeler un événement après un certain temps pour le faire?

Vive

Nik

Répondre

3

Essayez d'utiliser le PopUp.Dispatcher.Invoke(). Cela rappellera votre rappel au fil de l'interface utilisateur.

+0

Merci beaucoup pour cette suggestion. Au lieu de la clause thread j'ai utilisé "Action a = new Action (delayedRemovePopup); PopUp.Dispatcher.BeginInvoke (a);" et cela a résolu tout cela. :-) Merci beaucoup! –

+0

FYI vous n'avez pas besoin d'une variable temporaire, appelez simplement Popup.Dispatcher.BeginInvoke (delayedRemovePopup); – chakrit

1

Voici un truc que j'ai fait dans WPF. Il est porté pour une utilisation dans Silverlight et dépend de la classe Dispacher. Je ne connais pas la réponse de Maurice parce que je ne vois pas de méthode "Invoke" dans SL5. Je vois le BeginInvoke, qui est à peu près inutile quand il s'agit d'actions retardées. Utilisation: Vous devez inclure l'espace de noms System.Windows dans votre fichier de code ou cette méthode d'extension n'apparaîtra pas.

// lets say you want to enable a control 1 second after a save event 
// lets say you just want to prevent click happy users from going crazy 
// This code assumes you disabled the button on the click event 
Button b = this.idButton1; 
b.Dispatcher.DelayInvoke(TimeSpan.FromSeconds(1),() => { b.Enabled = true; }); 

C'est tout. Juste une ligne de code fait l'affaire. Voici la classe d'extension qui rend le code ci-dessus possible.

using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Threading; 

namespace System.Windows { 

    public static class DispatcherExtensions { 

     public static void DelayInvoke<TArg1, TArg2, TArg3>(this Dispatcher dispatcher, TimeSpan delay, Action<TArg1, TArg2, TArg3> action, TArg1 arg1, TArg2 arg2, TArg3 arg3) { 
      dispatcher.DelayInvoke(delay, (Delegate)action, arg1, arg2, arg3); 
     } 

     public static void DelayInvoke<TArg1, TArg2>(this Dispatcher dispatcher, TimeSpan delay, Action<TArg1, TArg2> action, TArg1 arg1, TArg2 arg2) { 
      dispatcher.DelayInvoke(delay, (Delegate)action, arg1, arg2); 
     } 

     public static void DelayInvoke<TArg1>(this Dispatcher dispatcher, TimeSpan delay, Action<TArg1> action, TArg1 arg1) { 
      dispatcher.DelayInvoke(delay, (Delegate)action, arg1); 
     } 

     public static void DelayInvoke(this Dispatcher dispatcher, TimeSpan delay, Action action) { 
      dispatcher.DelayInvoke(delay, (Delegate)action); 
     } 

     public static void DelayInvoke(this Dispatcher dispatcher, TimeSpan delay, Delegate del, params object[] args) { 

      if (dispatcher == null) 
       throw new NullReferenceException(); 
      if (delay < TimeSpan.Zero) 
       throw new ArgumentOutOfRangeException("delay"); 
      if (del == null) 
       throw new ArgumentNullException("del"); 

      var task = new Task(() => { Thread.Sleep(delay); }); 

      task.ContinueWith((t) => { dispatcher.BeginInvoke(del, args); }); 
      task.Start(); 
     } 
    } 
} 
Questions connexes