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

发布于 2024-07-09 10:42:03 字数 402 浏览 6 评论 0原文

在 WPF UserControl 中,我必须调用 WebService。 我正在一个单独的线程上进行此调用,但我想通知用户该调用可能需要一些时间。

WebMethod 返回一个对象集合,并将其绑定到 UC 中的 ListBox。 到目前为止,一切都很好...这部分效果非常好。 但是,我想在通话期间显示进度条(或任何类型的动画...)。 该动画将位于 ListBox 控件的顶部并居中。

我尝试了 Adorner,它部分起作用。 但是,我必须在 protected override void OnRender(DrawingContext DrawingContext) 中绘制所有控件...我只想添加一个控件几秒钟...

有人知道我如何实现这一点吗?

谢谢!

In a WPF UserControl, I have to make to call to a 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. 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.

I tried Adorner and it partially works. 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...

Anybody has an idea of how I could achieve this?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

二货你真萌 2024-07-16 10:42:03

不要使用装饰器 - 我所做的是有两个独立的容器控件(通常是网格)占据屏幕的同一区域。 一是我的“进度”控制,二是我的“内容”控制。 默认情况下,我将进度控件的可见性设置为“折叠”,将内容控件的可见性设置为“可见”。

如果您以这种方式进行设置,那么当您开始对 Web 服务进行异步调用时,您可以使进度控件可见并折叠内容控件。 当 Web 服务完成时,让它使用 Dispatcher.BeginInvoke 更新 UI,然后将进度控件切换回折叠状态,将内容控件切换回可见状态。

我通常使进度控制不确定。 这是一个例子; 在此,我有一个名为 ProgressGrid 的单独用户控件,其中有我的进度栏。

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

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.

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. 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.

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.

    <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;
    }
江湖彼岸 2024-07-16 10:42:03

您可以使用一个可能有效的零高度画布技巧。 Chris Anderson 的 WPF 书详细介绍了这一点及其工作原理,但内容是这样的。

  • 创建一个 StackPanel
  • 将高度为“0”的 Canvas 和高 z 索引添加到堆栈面板
  • 将用户控件添加到堆栈面板。

当您想显示进度条时,将其添加到零高度画布。 它将允许您将其放置在用户控件上。 Canvas 可以让你超越它的边界。 将进度条居中应该只需要查看用户控件的尺寸并相应地设置进度条在画布上的位置。 完成后从画布上删除进度条。

这是一个使用文本框的简单示例。 它并不完美,但它展示了这个想法。 单击按钮会在 InkCanvas 顶部显示文本框

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

There is a trick you can use with a zero height Canvas that might work. Chris Anderson's WPF book goes into detail on this and why it works, but it goes something like this.

  • create a StackPanel
  • add a Canvas with Height="0" and a high z-index to the stack panel
  • 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. 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. It's not perfect but it shows the idea. Clicking the button shows the TextBox on top of the InkCanvas

<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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文