Программно создайте Progressbar в приложении WPF

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

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

и это приведет к появлению ProgressBar над текущим активным окном. Я ищу способ иметь подобное поведение, но с .<ProgressBar Minimum="0" Maximum="100" Name="pbStatus" IsIndeterminate="True" />

РЕДАКТИРОВАТЬ

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

MessageBox

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

РЕДАКТИРОВАТЬ

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

c#,wpf,

-1

Ответов: 2


1 принят

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

Window window = new Window();
window.Content = new ProgressBar()
{
    Minimum = 0,
    Maximum = 100, IsIndeterminate = true
};
window.Show();

1

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

Я только что создал этот индикатор выполнения:

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

    }

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

C #, WPF,
Похожие вопросы
Яндекс.Метрика