Программно порождает Progressbar в приложении WPF - PullRequest
0 голосов
/ 28 июня 2018

В любых .cs файлах я могу назвать что-то вроде

MessageBox.Show(
    "This is an example",
    "Example",
    MessageBoxButton.OK,
    MessageBoxImage.Warning
);

, и это приведет к появлению окна сообщения поверх текущего активного окна. Я ищу способ иметь подобное поведение, но с ProgressBar.

EDIT

Если быть более точным, я знаю, что мог бы использовать что-то вроде

<ProgressBar Minimum="0" Maximum="100" Name="pbStatus" IsIndeterminate="True" />

в моем файле XAML. Но это будет означать, что я добавлю его во все окна, которые будут выполнять задачу. Поэтому моя цель состоит в том, чтобы напрямую вызывать его в коде задания, если это возможно.

EDIT

Я закончил тем, что написал гораздо более сложный кусок кода для достижения того, чего хотел. Я буду ссылаться на мое решение по другому вопросу. Смотрите это https://stackoverflow.com/a/51212664/7692463.

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Вместо показа MessageBox вы можете создать новое окно, установить его свойство Content равным ProgressBar и вызвать метод Show или ShowDialog окна в зависимости от того, хотите ли вы, чтобы окно было модальным :

Window window = new Window();
window.Content = new ProgressBar()
{
    Minimum = 0,
    Maximum = 100, IsIndeterminate = true
};
window.Show();
0 голосов
/ 28 июня 2018

Не выполняя весь процесс за вас, вы можете создать окно, которое открывается в верхней части активного окна с индикатором выполнения, а затем отправить ему прогресс с событием.

Я только что создал этот индикатор:

<Window x:Class="ProgressBar.Views.ProgressBar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    WindowStyle="None"
    Title="ProgressBar" Height="25" Width="250">
<Grid VerticalAlignment="Center">

    <ProgressBar Minimum="0" Maximum="100" Height="25" Value="{Binding Progress}"></ProgressBar>

</Grid>

и модель вида выглядит так:

 public class ProgressViewModel:INotifyPropertyChanged
{
    private int _progress;
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public ProgressViewModel()
    {
        ProgressBarEvent.GetInstance().ProgressChanged += (s, e) => Application.Current.Dispatcher.Invoke(()=> Progress = e);
    }

    public int Progress
    {
        get => _progress;
        set
        {
            _progress = value;
            OnPropertyChanged();
        }
    }
}

Событие выглядит как

 public class ProgressBarEvent
{
    private static ProgressBarEvent _instance;

    public static ProgressBarEvent GetInstance()
    {
        if(_instance == null)
            _instance = new ProgressBarEvent();
        return _instance;
    }

    public EventHandler<int> ProgressChanged;

    public EventHandler Show;
    public EventHandler Close;

    public ProgressBarEvent Start()
    {
        OnShow();
        return this;
    }

    public ProgressBarEvent Stop()
    {
        OnStop();
        return this;
    }

    private void OnShow()
    {
        if (Show is EventHandler show)
        {
            show.Invoke(this, new EventArgs());
        }
    }

    private void OnStop()
    {
        if (Close is EventHandler close)
        {
            close.Invoke(this, new EventArgs());
        }
    }

    public void SendProgress(int progress)
    {
        if (ProgressChanged is EventHandler<int> progressChanged)
        {
            progressChanged.Invoke(this, progress);
        }
    }
}

И App.xaml.cs выглядит так:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        ProgressBarEvent.GetInstance().Show += ShowProgressBar;
        ProgressBarEvent.GetInstance().Close += CloseProgressBar;
    }

    private Views.ProgressBar progressBarWindow;

    private void CloseProgressBar(object sender, EventArgs e)
    {
        Application.Current.Dispatcher.Invoke(() => progressBarWindow.Close());
    }

    private void ShowProgressBar(object sender, EventArgs e)
    {
        progressBarWindow = new Views.ProgressBar();
        var activeWindow = Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
        progressBarWindow.Owner = activeWindow;
        progressBarWindow.Show();
    }
}

Затем я создал кнопку в MainWindow с обработчиком событий, который выглядит следующим образом:

    private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        ProgressBarEvent.GetInstance().Start();

        await Task.Run(() =>
        {
            for (int i = 0; i < 100; i++)
            {
                ProgressBarEvent.GetInstance().SendProgress(i);
                Thread.Sleep(100);
            }

            ProgressBarEvent.GetInstance().Stop();
        });

    }

По сути, это откроет окно индикатора выполнения и закроет его, когда это будет сделано. Вам нужно будет выяснить, как расположить прогресс над окном, на котором вы хотите запустить прогресс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...