2009-02-26 67 views
1

我有以下情況:當用戶將鼠標移出彈出窗口時,我想要動畫發生,並且五秒鐘後,我想要刪除彈出。Silverlight:線程/延遲操作/異步調用/事件

這是我的預期與做這個代碼:

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; 
} 

第一行,「leftPopup = true」是好的,但第三,「PopUp.IsOpen =假」給了我一個訪問違例異常,可能是因爲這個對象屬於GUI線程。有什麼方法可以訪問PopUp.IsOpen屬性嗎?如果沒有,我還有什麼可以在一段時間後打電話給一個事件來做到這一點?

乾杯

的Nik

回答

3

嘗試使用PopUp.Dispatcher.Invoke()。這會將您的調用回傳給UI線程。

+0

非常感謝您的建議。而不是我使用的「Action a = new Action(delayedRemovePopup); PopUp.Dispatcher.BeginInvoke(a);」並解決了這一切。 :-)謝謝一堆! – 2009-02-26 15:22:56

1

這裏是我在WPF中做的一個技巧。它被移植到Silverlight中並掛在Dispacher類上。我不知道Maurice的答案,因爲我在SL5中沒有看到「Invoke」方法。我確實看到了BeginInvoke,當涉及到延遲操作時,這是毫無用處的。

用法:必須在代碼文件中包含System.Windows命名空間,否則不會顯示此擴展方法。

// 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; }); 

就是這樣。只需一行代碼即可實現。以下是使上述代碼成爲可能的擴展類。

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(); 
     } 
    } 
}