使用 Prism 6 (WPF) 显示耗时操作的操作进度层
Display operation progress layer for a time consuming operation using Prism 6 (WPF)
我正在开发我的第一个使用 Prism 6 的 WPF 应用程序。
单击按钮时,大约需要 1-2 分钟的操作应该开始。
我想在 window 内的所有其他控件之上显示一个半透明层,并显示操作进度和一个取消按钮,如下图和代码所示
<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 的最佳实践?
谢谢,
纳迪亚
我会使用 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> { }
确保您在执行长时间操作时处于单独的线程中。
我建议你 BusyIndicator
来自 ExtendedWPFToolkit。
你的 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
class的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;
};
我正在开发我的第一个使用 Prism 6 的 WPF 应用程序。 单击按钮时,大约需要 1-2 分钟的操作应该开始。
我想在 window 内的所有其他控件之上显示一个半透明层,并显示操作进度和一个取消按钮,如下图和代码所示
<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 的最佳实践?
谢谢, 纳迪亚
我会使用 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> { }
确保您在执行长时间操作时处于单独的线程中。
我建议你 BusyIndicator
来自 ExtendedWPFToolkit。
你的 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
class的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;
};