I'm creating an desktop application with UWP
and C#. Basically, I want to read and elaborate an Excel file. During the elaboration of this file, I want to display in the UI a progress bar and a text message. For that, I update the property in the view model: for example for the message the code is:
private string _message;
public string Message
{
get { return _message; }
set
{
if (_message != value)
{
_message = value;
OnPropertyChanged(nameof(Message));
}
}
}
So, in the view model I have the function to read and elaborate the file.
public async Task DecodeFile()
{
ImportExcel excel = new ImportExcel();
excel.ReadCompleted += Excel_ReadCompleted;
excel.ReadHeader += Excel_ReadHeader;
excel.UpdatedRow += Excel_UpdatedRow;
await excel.ReadToGrid(FileName);
}
If I use the function as it is, the UI is freezing when it executes this code. Then, I tried to change the last line with
await System.Threading.Tasks.Task.Run(() => excel.ReadToGrid(FileName));
but in this case I have another kind of error.
What is the best/correct practice to resolve this issue?
Update
The function ReadToGrid
is part of a class called ImportExcel
and it reads the Excel file with SpreadsheetDocument
using the package DocumentFormat.OpenXml.Spreadsheet
. In this class there are few events defined like
public event EventHandler<UpdatedRowEventArgs> UpdatedRow;
protected virtual void OnUpdatedRow(UpdatedRowEventArgs e)
{
EventHandler<UpdatedRowEventArgs> handler = UpdatedRow;
if (handler != null) handler(this, e);
}
I create an instance of this class in the view model. When an event is raised, the view model updates a property. For example, when it reads a new row of the Excel file, UpdateRow
is raised and the view model updates the property CurrentRow
related to the Value
in the ProgressBar
private void Excel_UpdatedRow(object sender, UpdatedRowEventArgs e)
{
CurrentRow = e.CurrentRow;
Message = $"Read record {e.CurrentRow}/{e.TotalRows}";
}
In the same event, I change the property Message
. None of them are changing in the UI. The UI is completely freezed.
Update 2
I tried to change the OnPropertyChanged
but the UI is still freezed
public event PropertyChangedEventHandler PropertyChanged;
private async void OnPropertyChanged(string propertyName)
{
PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(propertyName));
});
}
Update 4
I have published the full source code on GitHub.
Update 5 - Fix the issue
I have fixed the problem. I removed the call to ReadToGrid
from the UI and moved in the view model. I removed all the code behind and replaced it with properties in the view model. Added everywhere
CoreDispatcher dispatcher = CoreApplication.MainView?.CoreWindow?.Dispatcher;
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
});
and I changed OnPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected async void OnPropertyChanged(string propertyName)
{
PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
await dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(propertyName));
});
}
For future reference or if someone else has the same issue, the full source code is on GitHub.