У меня есть строка состояния в окне, которое я хочу обновить строкой во время фонового процесса.
В частности, пользователь нажимает кнопку, и данные считываются из файла. Когда файл читается, выполняются внутренние вызовы БД для заполнения объектов данных. Это делается для всех строк в файле. Это может занять немного времени. Все это делается в фоновом режиме.
Я хочу, чтобы пользователь почувствовал, что что-то происходит. Я хотел бы предоставить пользователю имя объекта, который был только что прочитан в строке состояния. Я вижу, что BackgroundWorker предоставляет значение обновления промежуточного числа, но как мне сделать строку, чтобы я мог ее отобразить?
Это общая проблема, с которой люди сталкиваются в 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));
}
}
}
Теперь давайте перейдем к вашему коду Control или Window за конструктором.
//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
и оно готово к MyStatus.Status
обновлениям из любого вызывающего потока.
<Label Content={Binding MyStatus.Status, UpdateSourceTrigger=PropertyChanged}/>
Для обновления просто установите значение MyStatus.Status
из вашего BackgroundWorker.
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 и как вы можете это сделать. обновлять такие вещи, как метка статуса, гораздо проще. Требуется немного больше работы на переднем конце, но экономит так много времени на заднем конце.
Удачи.