这是我在这里的第一篇文章,所以我希望我做的一切都是正确的。
我正在使用 .NET Framework 4 客户端配置文件。
我想将 .doc 文件中的数据加载到我的程序中并使用这些信息。这可能需要很多时间,因为我需要浏览文档的表格并检查里面的内容。这已经奏效了,这里唯一的问题是屏幕卡住,您看不到是否发生了什么事。
我也知道这在 excel 中会更快更容易,但是由于这种类型的数据一直并且一直存储在我们公司的 word 文档中,所以我必须保持这种状态。
所以我想要做的是计算我必须读取的表中的所有行,将其设置为进度条的最大值,然后在每一行之后我将计算值 + 1。
我有我的负载Button
与 Command
绑定(bind)到LoadWordDocCmd
和进度条:
<Button Name="btnLoadFile"
Content="Load" Height="23"
Command="{Binding LoadWordDocCmd}"
HorizontalAlignment="Right" Margin="0,22,129,0"
VerticalAlignment="Top" Width="50"
Visibility="{Binding VisModeAddNew}"
/>
<ProgressBar HorizontalAlignment="Left" Height="24" Margin="574,52,0,0"
VerticalAlignment="Top" Width="306"
Name="prgBarAddNewLoadWord"
Minimum="0"
Maximum="{Binding AddNewProgressBarMaxVal, Mode=OneWay}"
Value="{Binding AddNewProgressBarValue, Mode=OneWay}"
Visibility="{Binding AddNewProgressBarVisible}"/>
这里是
RelayCommand
:/// <summary>
/// Relaycommand for Function loadWordDocument
/// </summary>
public RelayCommand LoadWordDocCmd
{
get
{
if (this.m_loadWordDocCmd == null)
{
this.m_loadWordDocCmd = new RelayCommand(this.loadWordDocument, canLoadWordDoc);
}
return m_loadWordDocCmd;
}
private set
{
this.m_loadWordDocCmd = value;
}
}
/// <summary>
/// checks if the Word Document can be loaded
/// </summary>
/// <param name="parameter">not used</param>
/// <returns>if it could Execute, then true, else false</returns>
private bool canLoadWordDoc(object parameter)
{
bool ret = false;
if (this.m_fileSelected)
{
ret = true;
}
return ret;
}
我已经做的是使用
BackgroundWorker
.我能够将 Button-Command 绑定(bind)到具有
RelayCommand
的函数与 BackgroundWorker
,但后来我无法再检查 canExecute 函数了。我用它来测试进度条,它正在工作:
xml:
<Button ...
Command="{Binding Path=InstigateWorkCommand}"
/>
CS :
private BackgroundWorker worker;
private ICommand instigateWorkCommand;
public ProggressbarSampleViewModel()
{
this.instigateWorkCommand = new
RelayCommand(o => this.worker.RunWorkerAsync(), o => !this.worker.IsBusy);
this.worker = new BackgroundWorker();
this.worker.DoWork += this.DoWork;
this.worker.ProgressChanged += this.ProgressChanged;
}
public ICommand InstigateWorkCommand
{
get { return this.instigateWorkCommand; }
}
private int _currentProgress;
public int CurrentProgress
{
get { return this._currentProgress; }
private set
{
if (this._currentProgress != value)
{
this._currentProgress = value;
OnPropertyChanged("CurrentProgress");
}
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.CurrentProgress = e.ProgressPercentage;
}
private void DoWork(object sender, DoWorkEventArgs e)
{
// do time-consuming work here, calling ReportProgress as and when you can
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
_currentProgress = i;
OnPropertyChanged("CurrentProgress");
}
}
但是我怎样才能让它与 canExecute 一起工作?这是我的函数标题:
/// <summary>
/// Function for Load Word Document
/// </summary>
/// <param name="parameter">not used</param>
private void loadWordDocument(object parameter)
这是中继命令类:
public class RelayCommand : ICommand
{
private readonly Action<object> methodToExecute;
private readonly Func<object, bool> canExecute;
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
EventHandler handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
public RelayCommand(Action<object> execute)
: this(execute, null) { }
public RelayCommand(Action<object> methodToExecute, Func<object, bool> canExecute)
{
this.methodToExecute = methodToExecute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
// wird keine canExecute-Funktion übergeben, so liefert diese
// true zurück, ansonsten wird die custom canExecute-Funktion
// mit den übergebenen Parametern aufgerufen.
return canExecute == null ? true : canExecute.Invoke(parameter);
}
public void Execute(object parameter)
{
methodToExecute(parameter);
}
}
感谢您的帮助,我希望我发布了这个问题是正确的!
最佳答案
我希望我能正确理解您的问题。
GUI 应用程序的基本规则是:不要使用 GUI 线程进行(耗时的)数据处理。您必须在后台线程上执行此任务。
由于您使用的是 .NET 4.0 客户端配置文件,async
/await
您无法使用该功能。然而,这将是最简单的解决方案。
您可以使用 ThreadPool
反而。 BackgroundWorker
不再推荐。
在您的 XAML 中,您将绑定(bind) ProgressBar.Value
属性到 AddNewProgressBarValue
属性,所以我假设您已经有一个具有该属性的 View 模型。您必须确保更改 AddNewProgressBarValue
将提高 PropertyChanged
事件。好消息是,WPF 绑定(bind)引擎自动将属性值传输操作编码到 GUI 线程,因此您无需关心哪个线程正在更改您的进度条绑定(bind)到的属性。
所以解决方案可能看起来像这样(不是生产代码,只是一个想法!):
class ViewModel : INotifyPropertyChanged
{
private bool isProcessing;
public bool AddNewProgressBarVisible
{
get { return this.isProcessing; }
// SetProperty here is a PRISM-like helper to set the backing field value
// and to raise the PropertyChanged event when needed.
// You might be using something similar.
private set { this.SetProperty(ref this.isProcessing, value, "AddNewProgressBarVisible");
}
private int progressValue;
public int AddNewProgressBarValue
{
get { return this.progressValue; }
private set { this.SetProperty(ref this.progressValue, value, "AddNewProgressBarValue");
}
// This is your command handler
private void LoadWordDocument(object parameter)
{
if (this.isProcessing)
{
// don't allow multiple operations at the same time
return;
}
// indicate that we're staring an operation:
// AddNewProgressBarVisible will set isProcessing = true
this.AddNewProgressBarVisible = true;
this.AddNewProgressBarValue = 0;
// Notify the bound button, that it has to re-evaluate its state.
// Effectively, this disables the button.
this.LoadWordDocCmd.RaiseCanExecuteChanged();
// Run the processing on a background thread.
ThreadPool.QueueUserWorkItem(this.DoLoadWordDocument);
}
private void DoLoadWordDocument(object state)
{
// Do your document loading here,
// this method will run on a background thread.
// ...
// You can update the progress bar value directly:
this.AddNewProgressBarValue = 42; // ...estimate the value first
// When you're done, don't forget to enable the button.
this.AddNewProgressBarVisible = false;
// We have to marshal this to the GUI thread since your ICommand
// implementation doesn't do this automatically
Application.Current.Dispatcher.Invoke(() => this.LoadWordDocCmd.RaiseCanExecuteChanged());
}
// this is your command enabler method
private bool CanLoadWordDoc(object parameter)
{
// if we're already loading a document, the command should be disabled
return this.m_fileSelected && !this.isProcessing;
}
}
关于c# - 长任务期间的进度条进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47160619/