我在窗口上有一个状态栏,我想在后台进程运行时用字符串更新它。
具体来说,用户按下按钮,然后从文件中读取数据。在读取文件时,将进行后端db调用以填充数据对象。这是针对文件中的所有行完成的。这可能需要一点时间。 这一切都是在后台工作人员中完成的。
我想做的是为用户提供一些正在发生的感觉。我想向用户提供刚刚在状态行上读取的对象的名称。我看到BackgroundWorker提供了一个整数更新值,但是我该怎么做一个字符串才能显示它呢?
答案 0 :(得分:2)
这是人们在WPF中面临的常见问题。我想您正在尝试从BackgroundWorker更新标签,而您却被“另一个线程拥有它”错误所困扰。您可能会找到答案,告诉您使用调度程序来更新标签。不要做!它不可靠,在繁重的工作量下通常不会更新。您应该在实例中使用适当的绑定技术。
希望这个例子(虽然不一定是重构得最充分,也不一定是最快实施的),可以通过解释一些核心基础知识或WPF来使您走上正确的道路。
创建一个实现INotifyPropertyChanged
的可观察类。这是您的模型。它基本上是如何存储数据的外壳(在您的实例中为状态)。
using System.ComponentModel;
public class Status_Update : INotifyPropertyChanged
{
//private property that stores value
private string status;
//public property the gets & sets value
public string Status
{
get {return status;}
set
{
if(status != value)
{
status = value;
NotifyPropertyChanged("Status");
}
}
}
//Logic to notify that property values have changed.
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
现在,让我们移至构造函数后面的控件或窗口的代码。
//Create a Status_Update object in your control.
public Status_Update My_Status {get;set;}
public My_Control_or_Window()
{
//Initialize the Status_Update object
MyStatus = new Status_Update(){Status=""};
InitializeComponent();
//Set the controls DataContext to itself in the constructor
DataContext=this;
}
现在,在前端的XAML中,您只需绑定到控件的MyStatus.Status
属性,它就可以从任何调用线程进行实时更新。
<Label Content={Binding MyStatus.Status, UpdateSourceTrigger=PropertyChanged}/>
要更新,只需在BackgroundWorker中设置MyStatus.Status
的值即可。
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
MyStatus.Status = "Updating the first item";
Some_Task();
MyStatus.Status = "Updating the next item";
Some_Task();
}
我想指出的是,该示例不是MVVM的最佳示例,也不是您要尝试执行的最佳代码结构,但是它应该有助于您更好地了解WPF和如何更轻松地更新状态标签之类的内容。它在前端需要做更多的工作,但是在后端可以节省很多时间。
好运。