在主窗口的代码块开始时异步更新TextBlock
本文关键字:开始时 异步 更新 TextBlock 代码 窗口 | 更新日期: 2023-09-27 18:07:59
我有一个问题已经困扰我好几天了,我已经尝试了每一个选项,我现在的结果是张贴我自己的问题,从你们那里找到一些具体的帮助。
我需要更新一个TextBlock在代码块的开始,这是运行在一个简单的按钮点击。
下面是我的代码:
private void NewProject(bool blnCopy = false, string strFileName = null)
{
if (App.ApplicationBusy == false)
{
App.ApplicationBusy = true;
try
{
Action action = delegate()
{
Cursor = Cursors.Wait;
lblStatus.Text = "Opening Project...";
};
Dispatcher.Invoke(DispatcherPriority.Send, action);
if (blnCopy == false) { Project = new GSProject((App.RecentProjectCount + 1)); }
if (Project != null)
{
Projects.Add(Project);
if (blnCopy == false)
{
if (strFileName == null)
{
Project.ProjectName = string.Format("GSProject{0}", Projects.Count.ToString());
Project.ProjectDescription = string.Format("{0} - HW GS Project", Project.ProjectName);
Project.LoadResource();
}
else
{
Project.Load(strFileName);
}
}
else
{
Project = Project.Copy();
}
p_objNewPane = objDocker.AddDocument(Project.ProjectDisplayName, Project);
if (p_objNewPane != null)
{
p_objNewPane.DataContext = Project;
BindingOperations.SetBinding(p_objNewPane, ContentPane.HeaderProperty, new Binding("ProjectDisplayName") { Source = Project });
p_objNewPane.Closing += new EventHandler<PaneClosingEventArgs>(ContentPane_Closing);
}
if (Project.CalculationExists == true)
{
InitializeCalculation(true);
}
}
tabStartPage.Visibility = Visibility.Collapsed;
objDocumentTabs.SelectedIndex = 0;
}
catch (Exception ex)
{
ModernDialog.ShowMessage(string.Format("An error has occurred:{0}{0}{1}", Environment.NewLine, ex.Message), "Error", MessageBoxButton.OK, Application.Current.MainWindow);
}
finally
{
App.ApplicationBusy = false;
Cursor = Cursors.Arrow;
AppStatus = "Ready";
p_objNewPane = null;
}
}
}
在try块的开始,我需要更新TextBlock (lblStatus)来说明发生了什么。void本身,NewProject,在主窗口上,通过点击按钮调用。
谁能告诉我我哪里错了?我已经尝试了无数种可能的解决方案,所以如果我回复你说我已经尝试过了,请不要生气。
问候,汤姆。
经过几天的痛苦,我终于把它修好了。通过查看任务调度等,我完全搞错了方向。相反,所需要的只是一个DependencyProperty。
XAML(主窗口):
<TextBlock x:Name="lblStatus"
Text="{Binding AppStatus, IsAsync=True}"
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontFamily="Segoe UI"
FontSize="12"
Foreground="White"
Margin="5, 0, 0, 0" />
c#(主窗口):
public string AppStatus
{
get { return (string)GetValue(AppStatusProperty); }
set { SetValue(AppStatusProperty, value); }
}
public static readonly DependencyProperty AppStatusProperty =
DependencyProperty.Register("AppStatus", typeof(string), typeof(MainWindow), new PropertyMetadata(null));
public void StatusBarUpdate(string strMainMessage)
{
Dispatcher.BeginInvoke((Action)(() => { AppStatus = strMainMessage; }));
}
我可以在任何时候调用StatusBarUpdate
方法,它将异步更新UI。
您正在使用WPF,因此实现
INotifyPropertyChanged
,并使用正确的数据绑定。
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public string StatusText
{
get {return this.m_statusText;}
set
{
if (value != this.m_statusText)
{
this.m_statusText= value;
NotifyPropertyChanged("StatusText");
}
}
}
和XAML
<TextBox Text="{Binding Path=StatusText}"/>
你还没有提到到底是什么问题,但看看代码,我可以猜测文本框显示"打开项目…"只有在你的代码完成后或显示"准备好",如果AppStatus
正在做同样的事情。
如果是,问题是你在UI线程上做所有的事情。虽然您更改了文本框的文本,但它将在您的工作完成后呈现,因此出现了问题。要解决这个问题,需要在工作线程上运行从if (blnCopy == false)
到objDocumentTabs.SelectedIndex = 0;
的代码。这将解决你的问题。
您可以使用TPL,也可以使用.ContinueWith
与TaskScheduler.FromCurrentSynchronizationContext
和TaskContinuationOptions.OnlyOnRanToCompletion
来执行finally块。
编辑:由于您不使用MVVM,因此需要大量的Invoke
才能使代码正常工作。正如我所看到的p_objNewPane也是一个UI元素,就像Project
是一个视图属性一样,很难将所有这些转换为TPL。你可以让p_objNewPane = ...
的代码保持原样(即外部工作线程)。这似乎不是非常cpu密集,除了InitializeCalculation
,你可以在另一个工作线程中运行。
更好的方法是使用await/async方法来等待所有繁重的方法。