用WPF實現“等待”小轉盤

來源:互聯網
上載者:User

我們在開發過程中常常會遇到一些比較耗時的操作,比如一次較慢的網路訪問,或者複製一個較大的檔案等,如果不使用多線程,而是直接用UI線程去做這些動作,那麼就會讓使用者介面失去響應,帶來很不好的使用者體驗。較好的做法是在介面上呈現出一個小動畫,使用者看到有東西在動,就不認為程式已經死掉,例如這個:

 當然了,更好的做法是實現一個進度條,但很多時候我們根本不能擷取到進度,所以只能顯示這麼一個小轉盤,小轉盤效果的比較簡單的實現方法是顯示一個小小的gif,但WPF預設的Image控制項並不直接支援gif動畫效果,所幸的是我們可以通過一個叫“WpfAnimatedGif”第三方的庫來很方便地把這個動畫效果顯示出來,這個庫可以通過NuGet擷取到,我提供的完整代碼下載裡也有。這是我的Demo的:

小轉盤出現的同時,我們希望能夠暫時阻擋使用者的操作,我最早想到的辦法是把視窗Disable掉,也就是把它的IsEnabled屬性設為False,但這樣做可能達不到我們想要的效果,因為這樣只能把視窗的客戶區Disabled掉,而非客戶區卻仍然可以操作,比如標題列上的最小化,最大化和關閉按鈕,所以比較好的做法是用一個模態對話方塊。這是我設計的模態對話方塊:

<Window x:Class="WaitingDemo.WaitingDlg"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:gif="http://wpfanimatedgif.codeplex.com"        Title="WaitingDlg" Height="100" Width="400" WindowStyle="None" Background="Transparent" AllowsTransparency="True"        WindowStartupLocation="CenterOwner" Closing="Window_Closing" Loaded="Window_Loaded"        TextOptions.TextFormattingMode="Display">    <Grid>        <Border CornerRadius="5" Height="40" BorderBrush="Black" BorderThickness="1" Background="White" Width="350">            <Border.Effect>                <DropShadowEffect Color="Black"></DropShadowEffect>            </Border.Effect>            <Grid VerticalAlignment="Center">                <Image gif:ImageBehavior.AnimatedSource="loading.gif" Width="28" Height="28" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5,0,0,0"/>                <TextBlock Name="tbPrompt" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.ColumnSpan="2" Margin="0,7">任務執行中...</TextBlock>            </Grid>        </Border>    </Grid></Window>

這是幾個要注意的屬性設定:

  • WindowStyle - 設定為None來使得這個模態對話方塊沒有標題列,當然也就沒有了最小化、最大化和關閉按鈕
  • Background - 設定為Transparent來讓這個模態對話方塊背景透明
  • AllowsTransparency - 如果不把這個屬性設定為True,那模態對話方塊的依然是不透明的,你將看到一個黑框
  • WindowStartupLocation - 設定為CenterOwner讓模態對話方塊預設置中顯示

細心的你也許還發覺了:只是不顯示關閉按鈕還是不夠的,使用者還是可以通過<Alt>+<F4>來關閉這個對話方塊,所以需要處理Closing事件,判斷這個關閉動作是否我們的程式提出來的。

對於處理任務,我建立了一個介面:

    public interface ILongTimeTask    {        void Start(WaitingDlg dlg);    }

將WaitingDlg傳入的原因是想讓背景工作執行緒結束的時候關閉掉這個模態對話方塊:

        public void TaskEnd(Object result)        {            m_taskResult = result; //用於返回執行的結果(也可以為null)            m_bCloseByMe = true; //這個標誌表示“關閉”動作由我們的程式提出            Dispatcher.BeginInvoke(new CloseMethod(Close)); //背景工作執行緒對介面元素的操作必須用這種調用方式        }

完整代碼:下載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.