在WPF应用程序中以编程方式生成Progressbar

时间:2018-06-28 14:44:21

标签: c# wpf

在任何.cs文件中,我都可以这样称呼,

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

,这将在当前活动窗口上方生成一个消息框。我正在寻找一种具有类似行为但使用ProgressBar的方法。

编辑

更具体地说,我知道我可以使用

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

在我的XAML文件中。但这意味着我将在执行任务的所有窗口中添加它。因此,我的目标是在可能的情况下直接在任务代码中生成它。

编辑

我最终写了一段复杂得多的代码来实现我想要的。我将在另一个问题上引用我的解决方案。参见此https://stackoverflow.com/a/51212664/7692463

2 个答案:

答案 0 :(得分: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();
        });

    }

基本上,这将打开进度栏窗口,并在完成后将其关闭。您将必须弄清楚如何将进度放置在要运行进度的窗口上。

答案 1 :(得分:1)

您可以创建一个新窗口,而不是显示MessageBox,而是将其Content属性设置为ProgressBar,然后调用窗口的ShowShowDialog方法取决于您是否希望窗口为模态:

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