10

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

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

我尝试了 Adorner,它部分有效。但是,我必须在受保护的覆盖 void OnRender(DrawingContext drawingContext) 中绘制所有控件...我只想添加一个控件几秒钟...

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

谢谢!

4

2 回答 2

10

不要使用装饰器——我所做的是有两个独立的容器控件(通常是网格),它们占据屏幕的同一区域。一个是我的“进度”控件,另一个是我的“内容”控件。我将进度控件的可见性设置为 Collapsed,并将内容控件的可见性默认设置为 Visible。

如果您以这种方式进行设置,当您启动对 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;
    }
于 2008-12-01T00:59:17.343 回答
1

有一个技巧可以用于零高度的 Canvas,它可能会奏效。Chris Anderson 的 WPF 书详细介绍了这一点以及它为什么起作用,但它是这样的。

  • 创建一个堆栈面板
  • 向堆栈面板添加一个 Height="0" 和高 z-index 的 Canvas
  • 将您的用户控件添加到堆栈面板。

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

这是一个使用 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);
}
于 2008-12-01T00:59:38.933 回答