简体   繁体   English

如何在WPF中的控件上显示进度条

[英]How to display a progress bar on top of a control in WPF

In a WPF UserControl, I have to make to call to a WebService. 在WPF UserControl中,我必须调用WebService。 I am making this call on a separate thread but I want to inform the user that the call may take some time. 我在一个单独的线程上进行此调用,但我想通知用户该调用可能需要一些时间。

The WebMethod returns me a collection of objects and I bind it to a ListBox in my UC. WebMethod返回一个对象集合,并将其绑定到我的UC中的ListBox。 So far, so good... This part works really well. 到目前为止,这么好......这部分效果非常好。 However, I want to display a progress bar (or an animation of any kind...) during the call. 但是, 我想在通话期间显示进度条(或任何类型的动画......)。 This animation would be on top and centered in the ListBox control. 此动画将位于顶部并以ListBox控件为中心。

I tried Adorner and it partially works. 我试过Adorner,它部分有用。 However, I have to draw all controls in protected override void OnRender(DrawingContext drawingContext)... I simply want to add a control for a couple of seconds... 但是,我必须在受保护的覆盖void OnRender(DrawingContext drawingContext)中绘制所有控件...我只想添加一个控件几秒钟......

Anybody has an idea of how I could achieve this? 任何人都知道如何实现这一目标?

Thanks! 谢谢!

Don't go with the adorner - what I do is have two separate container controls (usually grids) that occupy the same area of the screen. 不要与装饰者一起 - 我所做的是有两个独立的容器控件(通常是网格)占据屏幕的同一区域。 One is my "progress" control, and the other is my "content" control. 一个是我的“进步”控制,另一个是我的“内容”控制。 I set the visibility of the progress control to Collapsed and the visibility of the content control to Visible by default. 我将进度控件的可见性设置为Collapsed,默认情况下将内容控件的可见性设置为Visible。

If you have it set up that way, when you start the asynchronous call to the webservice you can make the progress control visible and the content control collapsed. 如果以这种方式设置它,当您启动对Web服务的异步调用时,您可以使进度控件可见并且内容控件已折叠。 When the webservice finishes, have it use Dispatcher.BeginInvoke to update the UI, and at that point, switch the progress control back to collapsed and the content control back to visible. 当webservice完成后,让它使用Dispatcher.BeginInvoke来更新UI,此时,将进度控制切换回折叠状态,然后将内容控件切换回可见状态。

I generally make the progress control indeterminate. 我通常使进度控制不确定。 Here is an example; 这是一个例子; in this, I have a separate UserControl called ProgressGrid that has my progress bar. 在这里,我有一个名为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>

And in the code behind, just something simple like this: 在后面的代码中,只是这样的简单:

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

There is a trick you can use with a zero height Canvas that might work. 有一个技巧可以使用可能有效的零高度Canvas。 Chris Anderson's WPF book goes into detail on this and why it works, but it goes something like this. 克里斯安德森的WPF书详细介绍了它及其工作原理,但它就是这样的。

  • create a StackPanel 创建一个StackPanel
  • add a Canvas with Height="0" and a high z-index to the stack panel 在堆栈面板中添加高度=“0”和高z-index的Canvas
  • add your user control to the stack panel. 将您的用户控件添加到堆栈面板。

When you want to show the progress bar add it to the zero height canvas. 当您想要显示进度条时,将其添加到零高度画布。 It will allow you to position it over the user control. 它允许您将其放在用户控件上。 Canvas allows you to go beyond its borders. Canvas允许您超越其边界。 Centering the progress bar should just require looking at the dimensions of the user control and setting the position of the progress bar on the Canvas accordingly. 使进度条居中应该只需要查看用户控件的尺寸并相应地设置“画布”上进度条的位置。 Remove the progress bar from the canvas when you are done. 完成后从画布中删除进度条。

Here is a simple example that uses a TextBox. 这是一个使用TextBox的简单示例。 It's not perfect but it shows the idea. 它不完美,但它显示了这个想法。 Clicking the button shows the TextBox on top of the InkCanvas 单击该按钮可在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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM