通過製作一個簡單的時鐘學習WPF中DispatcherTimer的使用 Level 100

來源:互聯網
上載者:User

作者:Tony Qu
註:大家可以對本文的寫作風格作一些點評,看看是否喜歡,是否有更好的建議,先謝謝了!

Timer控制項是WinForm開發中必備的控制項之一,在.net 3.0之前的版本中,我們可以很方便的從工具箱中拖出一個Timer來,在組件可視化列表中,我們會看到一個時鐘,這就表示該WinForm中存在一個計時器。

可能是CTP版本的關係,在WPF的VS2005外掛程式的工具箱中,根本無法找到Timer控制項的蹤影。看來我只有自力更生了

既然我們要製作時鐘,首先來畫介面,自然要先定義視窗的XAML,如下:

<Window x:Class="EClock.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="EClock" Height="97" Width="187"
    >
    <Grid>
    <TextBlock Margin="14,11,19,12" Name="textBlock1" Loaded="OnTextBlockLoaded" FontFamily="Time New Roman" FontSize="40">00:00:00</TextBlock>      
  </Grid>
</Window>

有心人已經應該發現了,這個程式叫做EClock,而這個Window則叫做Window1(可以從x:Class中看出,這是code-behind代碼的引用)

我定義了一個TextBlock,ID為textBlock1。其他的一些基本屬性如FontFamily, FontSize, Margin就不說了,大家都會設定。來說說這個Loaded屬性,目前的WPF還不支援在可視化介面下建置事件處理常式(event handler),所以得自己加,這裡的Loaded就是TextBlock的載入事件,那麼裡面的OnTextBlockLoaded自然就是事件處理常式的名稱。

首先,我在WPF 視窗Window1的Class聲明中定義了一個新的變數,叫做timer,請注意我們並沒有使用System.Timers.Timer,而是使用了DispatcherTimer,至於原因將在本文最後講解。定義代碼如下:

System.Windows.Threading.DispatcherTimer timer;

下面我們來看看這個事件處理常式的內容:

private void OnTextBlockLoaded(object sender, RoutedEventArgs e)
{
     timer = new System.Windows.Threading.DispatcherTimer();
     timer.Interval = new TimeSpan(0,0,1);   //間隔1秒
     timer.Tick += new EventHandler(timer_Tick);
     timer.Start();
}

如注釋所說,我把間隔設定為1秒。該計時器的間隔事件也是Tick事件。好了,一切就緒,最後讓我們來看看timer_Tick中的代碼:

void timer_Tick(object sender, EventArgs e)
{
     textBlock1.Text = DateTime.Now.ToLongTimeString();
}

似乎和原來的Tick事件中的代碼沒啥兩樣,那就運行一下看看效果吧。。。。

     

左側為Windows 2003下運行結果,右側為Vista下運行結果(發覺一個細節,ToLongTimeString在不同環境下返回的字串盡然不一樣,有誰知道為啥嗎?)

完工!一個簡單的電子鐘做好了。下面讓我們來講講為什麼我們沒有用我們相對熟悉的System.Timers.Timer。其實在.net 3.0中這個Timer已經與過去我們所瞭解的Timer不同了,如果我們在這個例子中使用該計時器的話,我們將收到一下錯誤資訊:

由於其他線程擁有此對象,因此調用線程無法對其進行訪問。

根據MSDN文檔的說明,System.Timers.Timer是在一個獨立的線程上實現的,而我們要更新的TextBlock位於視窗線程中,所以會出現以上錯誤。所以在國外的大部分的WPF Blog中,作者們比較喜歡使用DispatcherTimer,因為它簡單方便,似乎和過去Timer更相似。至於System.Timers.Timer到底該如何?對UI的更新,我還沒有底,如果有誰已經知道怎麼弄了,請分享一下。

=======================Update on 2006.12.23======================
基於System.Timers.Timer的解決方案(由Tyrael 提供)

private delegate void UpdateTimer();

private void UpdateTimerCallback()
{
textBlock1.Text = DateTime.Now.ToLongTimeString();
}

void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new UpdateTimer(UpdateTimerCallback)); 
}

這裡的timer_Elapsed事件處理常式對應於Timer的Elapsed事件

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.