绑定到viewmodel属性的标签内容不会在后台worker的RunWorkerCompleted事件期间更新
本文关键字:RunWorkerCompleted worker 后台 事件 更新 属性 viewmodel 标签 绑定 | 更新日期: 2023-09-27 18:11:09
我在视图模型中使用后台工作器查看了UI更新上的几个线程,并根据需要进行了代码更改,不幸的是我不能让它工作。
我正在尝试更新我的标签内容,该内容绑定到在视图模型中实现INotifyPropertyChanged的属性。报告被创建了,但是更新的标签内容只有在从主窗口视图重新打开MyWindow时才会显示。
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Messenger.Default.Register<NotificationMessage>(this,
NotificationMessageReceived);
Closing += (s, e) => ViewModelLocator.Cleanup();
}
private void NotificationMessageReceived(NotificationMessage msg)
{
if (msg.Notification == "ShowMyWindow")
{
MyWindow ReportWind = new MyWindow();
ReportWind.DataContext = msg.Sender;
MyWindow.ShowDialog();
}
}
}
ViewModel.cs
public class MyViewModel
{
//Fields
public static string statusProp = string.Empty;
BackgroundWorker _BWorker = new BackgroundWorker();
//Properties
public string LblStatusContent
{
get
{
return statusProp;
}
set
{
statusProp = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("LblStatusContent");
}
}
public RelayCommand GoCmd { get; private set; }
public MyViewModel(IDialogService dService)
{
_dialogService = dService;
GoCmd = new RelayCommand(() => Go(_dialogService), () => true);
}
private void Go(IDialogService dService)
{
//dialogservice to show a savedialogbox
//do something.
//start my thread to save a pdf refort
_BWorker = new BackgroundWorker()
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
_BWorker.DoWork += new DoWorkEventHandler(DoWork);
_BWorker.ProgressChanged += new
ProgressChangedEventHandler(WorkerProgress);
_BWorker.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(WorkerCompleted);
if (_BWorker.IsBusy !=true)
{
_BWorker.RunWorkerAsync();
}
}
private void WorkerProgress(object sender, ProgressChangedEventArgs e)
{
try
{
if (e.UserState != null && e.UserState.ToString() != "")
{
// LblStatusContent =
//((ReportWindow.ReportProgressArg)e.UserState).smsg;
//BatchCompareProgressBar.Value = e.ProgressPercentage;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
ErrorLogger.Log(LogLevel.Error, ex.ToString());
}
}
private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
try
{
if ((e.Cancelled == true))
{
this.LblStatusContent = "Cancelled";
}
else if (!(e.Error == null))
{
LblStatusContent = "Failed to create report";
OnPropertyChanged(LblStatusContent);
LblStatusVisibility = System.Windows.Visibility.Visible;
}
else
{
System.Windows.Application.Current.Dispatcher.Invoke(
DispatcherPriority.Normal,
(Action)delegate()
{
this.LblStatusContent = "Report created successfully";
OnPropertyChanged(LblStatusContent);
LblStatusVisibility = System.Windows.Visibility.Visible;
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
ErrorLogger.Log(LogLevel.Error, ex.ToString());
}
}
private void DoWork(object sender, DoWorkEventArgs e)
{
try
{
StartReport();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
ErrorLogger.Log(LogLevel.Error, ex.ToString());
}
finally { }
}
}
MyWindow.xaml
<Label Name="lblStatus" VerticalAlignment="Center"
Content="{Binding LblStatusContent}"
Visibility="{Binding LblStatusVisibility, Mode=TwoWay}"
Margin="0,80,12,203" Height="36"
HorizontalAlignment="Right" Width="450" />
也许这个小例子能帮你弄明白?
<Window x:Class="WpfApplication1.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:WpfApplication1.ViewModel"
Title="MainWindow"
Height="80"
Width="140">
<Window.DataContext>
<viewModel:MainViewModel />
</Window.DataContext>
<Label Content="{Binding Property}" />
</Window>
namespace WpfApplication1.ViewModel
{
public class MainViewModel : ViewModelBase
{
readonly BackgroundWorker _worker = new BackgroundWorker();
private string _property;
public MainViewModel()
{
_worker.WorkerReportsProgress = true;
_worker.DoWork += (sender, args) =>
{
int iterations = 0;
Property = "Starting...";
Thread.Sleep(1000);
while (iterations < 5)
{
_worker.ReportProgress(iterations * 25);
iterations++;
Thread.Sleep(350);
}
};
_worker.ProgressChanged += (sender, args) =>
Property = string.Format("Working...{0}%", args.ProgressPercentage);
_worker.RunWorkerCompleted += (sender, args) =>
{
Property = "Done!";
};
_worker.RunWorkerAsync();
}
public string Property
{
get { return _property; }
set { _property = value; RaisePropertyChanged(); }
}
}
}
我不知道我是如何错过订阅INotifyPropertychanged在类声明,即使我已经实现了Onpropertychanged正确。为了在后台进程完成后窗口仍然打开时更新属性,我所要做的就是:公共类MainViewModel: ViewModelBase, INotifyPropertyChanged.