2008-12-01 119 views
8

在WPF UserControl中,我必須調用WebService。我在單獨的線程上進行此調用,但我想通知用戶該調用可能需要一些時間。如何在WPF中的控件上顯示進度條

WebMethod返回對象集合,並將其綁定到我的UC中的ListBox。到目前爲止,這麼好......這部分工作得很好。但是,我想在通話過程中顯示進度條(或任何類型的動畫...)。該動畫將位於頂部並位於ListBox控件的中心。

我試過Adorner,它部分工作。然而,我必須繪製所有控制在保護覆蓋無效OnRender(DrawingContext drawingContext)...我只是想添加一個控制幾秒鐘...

任何人都有我如何能實現這個想法?

謝謝!

回答

9

不要跟裝飾者 - 我所做的是有兩個獨立的容器控件(通常是網格)佔據屏幕的相同區域。一個是我的「進度」控制,另一個是我的「內容」控制。默認情況下,我將進度控件的可見性設置爲「已摺疊」,並將內容控件的可見性設置爲「可見」。

如果按照這種方式設置,當您開始對web服務的異步調用時,可以使進度控件可見並且內容控件摺疊。當webservice完成後,讓它使用Dispatcher.BeginInvoke來更新UI,並且在那一點上,將進度控制切換回合併且內容控制回到可見狀態。

我通常使進度控制不確定。這是一個例子;在這裏,我有一個名爲ProgressGrid的獨立UserControl,它有我的進度條。

<Grid x:Name="layoutRoot"> 
     <Grid x:Name="contentGrid" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Visible"> 
      <!-- snip --> 
     </Grid> 

     <controls:ProgressGrid x:Name="progressGrid" Text="Signing in, please wait..." Visibility="Collapsed"/> 
    </Grid> 

而且在後面的代碼,只是簡單的東西是這樣的:

private void SignInCommand_Executed(object sender, ExecutedRoutedEventArgs e) 
    { 
     contentGrid.Visibility = Visibility.Collapsed; 
     progressGrid.Visibility = Visibility.Visible; 
    } 
+0

哇!很好的答案!但是,在您的解決方案中,如何將ProgressBar控件置於ListBox的中心?帆布? – Martin 2008-12-01 01:06:43

1

有你可以用一個零個高度畫布可能工作使用的一招。克里斯安德森的WPF書詳細介紹了這一點以及它爲什麼有效,但它是這樣的。

  • 創建一個StackPanel
  • 與高度=「0」和一個高z索引添加畫布到堆疊面板
  • 添加用戶控制到堆棧面板。

當您想要顯示進度條時,將其添加到零高度畫布。它將允許您將其放在用戶控件上。帆布可以讓你超越它的邊界。居中進度條應該只需要查看用戶控件的尺寸並相應地在畫布上設置進度條的位置。完成後,從畫布上移除進度條。

這是一個使用TextBox的簡單示例。這並不完美,但它顯示了這個想法。單擊該按鈕將顯示InkCanvas頂部的TextBox

<DockPanel LastChildFill="True"> 
    <Button DockPanel.Dock="Top" Name="showButton" Click="showProgress">show</Button> 
    <StackPanel DockPanel.Dock="Bottom"> 
     <Canvas Name="zeroHeight" Height="0"/> 
     <InkCanvas Name="inky"> 
     </InkCanvas> 
    </StackPanel> 
</DockPanel> 


private void showProgress(object sender, RoutedEventArgs e) 
{ 
    TextBox box = new TextBox(); 
    box.Text = "on top"; 
    StackPanel.SetZIndex(zeroHeight, 8); 
    zeroHeight.Children.Add(box); 
    box.Width = 30; 
    box.Height = 30; 
    Canvas.SetLeft(box, 10); 
    Canvas.SetTop(box, 10); 
    Canvas.SetZIndex(box, 10); 
}