Как отобразить индикатор выполнения поверх элемента управления в WPF - PullRequest
9 голосов
/ 01 декабря 2008

В WPF UserControl мне нужно сделать, чтобы вызвать WebService. Я делаю этот вызов в отдельной ветке, но хочу сообщить пользователю, что этот вызов может занять некоторое время.

WebMethod возвращает мне коллекцию объектов, и я связываю ее с ListBox в моем UC. Пока все хорошо ... Эта часть работает очень хорошо. Тем не менее, Я хочу отображать индикатор выполнения (или анимацию любого вида ...) во время вызова. Эта анимация будет сверху и по центру элемента управления ListBox.

Я попробовал Adorner, и он частично работает. Однако я должен нарисовать все элементы управления в защищенном переопределении void OnRender (DrawingContext drawingContext) ... Я просто хочу добавить элемент управления на пару секунд ...

У кого-нибудь есть идеи, как мне этого добиться?

Спасибо!

Ответы [ 2 ]

9 голосов
/ 01 декабря 2008

Не идите с обожателем - у меня есть два отдельных элемента управления контейнером (обычно сетки), которые занимают одну и ту же область экрана. Одним из них является мой контроль «прогресса», а другим - мой контроль «контента». Я установил видимость элемента управления прогрессом в Collapsed и видимость элемента управления содержимым в Visible по умолчанию.

Если он настроен таким образом, при запуске асинхронного вызова веб-службы вы можете сделать видимым элемент управления прогрессом и свернуть его. Когда веб-служба завершит работу, используйте Dispatcher.BeginInvoke, чтобы обновить пользовательский интерфейс, и в этот момент переключите управление выполнением обратно на свернутый, а управление содержимым - на видимое.

Я обычно делаю управление прогрессом неопределенным. Вот пример; в этом у меня есть отдельный UserControl с именем 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;
    }
1 голос
/ 01 декабря 2008

Существует прием, который можно использовать с холстом нулевой высоты, который может работать. В книге Криса Андерсона, посвященной WPF, подробно рассказывается об этом и о том, почему она работает, но примерно так.

  • создать StackPanel
  • добавить холст с высотой = "0" и высоким z-индексом на панель стека
  • добавьте свой пользовательский элемент управления на панель стека.

Если вы хотите показать индикатор выполнения, добавьте его на холст нулевой высоты. Это позволит вам расположить его над пользовательским контролем. Холст позволяет выйти за его пределы. Центрирование индикатора выполнения должно просто потребовать просмотра размеров пользовательского элемента управления и соответственно установить положение индикатора выполнения на холсте. Удалите индикатор выполнения с холста, когда вы закончите.

Вот простой пример, который использует TextBox. Это не идеально, но это показывает идею. Нажатие на кнопку показывает TextBox поверх 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);
}
...