【问题标题】:Display operation progress layer for a time consuming operation using Prism 6 (WPF)使用 Prism 6 (WPF) 显示耗时操作的操作进度层
【发布时间】:2016-03-30 12:40:58
【问题描述】:

我正在开发我的第一个使用 Prism 6 的 WPF 应用程序。 单击按钮时,应该会启动大约需要 1-2 分钟的操作。

我想在窗口内所有其他控件之上显示一个半透明层,并显示操作进度和一个取消按钮,如下图和代码所示

<Window x:Class="TestingApplication.Shell"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://www.codeplex.com/prism">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Border Grid.Column="0">
            <ContentControl x:Name="NavigationItemsControl" 
                          prism:RegionManager.RegionName="MainNavigationRegion" 
                          Grid.Column="0"/>
        </Border>

        <ContentControl prism:RegionManager.RegionName="MainContentRegion" 
                        Grid.Row="1"/>

        <Grid Grid.RowSpan="2" Background="#5555">
            <Border BorderBrush="Gray" BorderThickness="1"
                    Width="400" Height="200" Background="White">
                <StackPanel Margin="10">
                    <TextBlock Text="Loading... Please wait" 
                               Margin="0,10" FontSize="18"/>
                    <ProgressBar HorizontalAlignment="Stretch" Height="40"/>
                    <Button Content="Cancel" HorizontalAlignment="Center"
                            Margin="0,10"/>
                </StackPanel>
            </Border>
        </Grid>
    </Grid>
</Window>

您能否给我任何建议,这将是实现这一点并同时利用 Prism 和 MVVM 的最佳实践?

谢谢你, 娜迪亚

【问题讨论】:

  • 我很困惑,你是什么意思。你能解释一下,这是你需要的吗:单击按钮时,应该会出现一些灰色布局,直到过程完成?
  • 是的,这正是我所需要的

标签: wpf mvvm prism


【解决方案1】:

我会使用 eventAggrgator 。

<ProgressBar HorizontalAlignment="Stretch" Height="40" Value{Binding ProgressBarValue}/>

public class ViewModel:BindableBase
{
    private readonly IEventAggregator _eventAggregator;

    public ViewModel(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
        _eventAggregator.GetEvent<ProgressbarEvent>().Subscribe(PopulateProgress);
    }

    private void PopulateProgress(double value)
    {
        ProgressbarValue = value;
    }

    private double _progressbarValue;

    public double ProgressbarValue
    {
        get { return _progressbarValue; }
        set { SetProperty(ref(_progressbarValue),value); }
    }

//this is how you would send event
        public void SendProgress()
        {
            for (double i = 0; i < 100; i++)
            {
                _eventAggregator.GetEvent<ProgressbarEvent>().Publish(i);
            }
        }

    }
    public class ProgressbarEvent : PubSubEvent<Double> { }

确保您在执行长时间操作时处于单独的线程中。

【讨论】:

    【解决方案2】:

    我建议你从ExtendedWPFToolkitBusyIndicator

    您的 XAML 应该是这样的:

    <extToolkit:BusyIndicator IsBusy="{Binding IsBusy}" BusyContent="Processing..." >
       <extToolkit:BusyIndicator.ProgressBarStyle>
          <Style TargetType="ProgressBar">
            <Setter Property="IsIndeterminate" Value="False"/>
            <Setter Property="Height" Value="15"/>
            <Setter Property="Margin" Value="8,0,8,8"/>
            <Setter Property="Value" Value="{Binding ProgressValue}"/>
          </Style>
       </extToolkit:BusyIndicator.ProgressBarStyle>
    
       <ListBox ItemsSource="{Binding Persons}"/>
    
    </extToolkit:BusyIndicator>
    

    然后在您的 ViewModel 中实现布尔型​​ IsBusy 属性:

    private bool isBusy;
    public bool IsBusy
    {
        get { return isBusy; }
        set
        {
            this.isBusy = value;
            this.OnPropertyChanged("IsBusy");
        }
    }
    

    然后将ProgressValue 属性添加到您的 ViewModel:

    private int progressValue ;
    public int ProgressValue
    {
        get { return progressValue ; }
        set
        {
            this.progressValue = value;
            this.OnPropertyChanged("ProgressValue ");
        }
    }
    

    然后将耗时的操作放在BackgroundWorker 类的DoWork lambda-expression 中,以免UI 冻结:

        BackgroundWorker worker = new BackgroundWorker();
        worker.WorkerReportsProgress = true;        
        worker.DoWork += (o, ea) =>
        {
               IsBusy = true;
               //Do your heavy work here
               worker.ReportProgress(10);
    
               //Do your heavy work here
               worker.ReportProgress(20);
    
               //And so on
        };
    
    
        worker.ProgressChanged += (o,ea) =>
        {
            ProgressValue = e.ProgressPercentage;
        };
    
        worker.RunWorkerCompleted += (o, ea) =>
        {
          IsBusy = false;
        };
    

    【讨论】:

    • @JamTay317 随时提出任何问题。如果您觉得我的回复对您有帮助,那么您可以将我的回复标记为答案,以简化日后其他人的搜索。请阅读此meta.stackexchange.com/questions/5234/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多