This is for Windows 10, Windows Application WPF .NET framework 4.7.2
I have code from an older windows form project (vs 2017 community) for a ProgressBar that worked fine (Windows Forms project). I have a wpf windows project now that works fine but I wanted to add a progress bar to the two buttons (Proccess and Insert buttons) click event because they take several seconds to complete and I want to see some progress. This project is for me only and it always runs inside visual studio (community 2019). I copied the old code to the new project but the progressbar does not show up or show progress. The code is in the buttonclick event in the old project as in the new one but no luck....I maybe missing something from the old project but I don't see what. I know about the "can not modify the UI from the calling thread" but I thought I used a different thread with Task.Factory.StartNew. There are a lot of posts/threads here for Dispatcher.BeginInvoke but I couldn't find one similar to mine ... one of them said that this approach was the wrong way to do it. I don't do MVVM stuff. I don't do windows programming C# very often so don't assume that I know what I'm doing....LOL. Any help to show the progressbar would be appreciated. A pointer on how to do it "right" also appreciated.Thanks. Here is the code for one of the buttons (ProcessButton_Click) its progressbar is named "ProgressBarProcess":
private void ProcessButton_Click(object sender, RoutedEventArgs e)
{
if (targetBOMTextBox.Text.Length != 11)
{
MessageBox.Show("Target BOM part number missing or incorrect format.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
Task.Factory.StartNew(() => ProcessButtonFunction());
}
private void ProcessButtonFunction()
{
ProgressBarProcess.Minimum = 1;
ProgressBarProcess.Maximum = 5;
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Visibility = Visibility.Visible; }));
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 1; }));
fillExcelLists();
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 2; }));
convertTofloatList();
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 3; }));
splitDesignatorList();
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 4; }));
fillRecordsList();
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 5; }));
insertButton.IsEnabled = true;
clearButton.IsEnabled = true;
}
private void fillExcelLists()
{
ExcelAccess ExcelAccessOBJ = new ExcelAccess();
//get part numbers from excel column to GlobalData.excelPartNoList
ExcelAccessOBJ.ExcelReadColumn(partNoComboBox.SelectedItem.ToString(), Convert.ToInt16(dataStartRowTextBox.Text), Convert.ToInt16(dataEndRowTextBox.Text), GlobalData.excelPartNoList);
//get quantities from excel column to GlobalData.excelQuantityList
ExcelAccessOBJ.ExcelReadColumn(quantityComboBox.SelectedItem.ToString(), Convert.ToInt16(dataStartRowTextBox.Text), Convert.ToInt16(dataEndRowTextBox.Text), GlobalData.excelQuantityList);
//get designators from excel column to GlobalData.excelDesignatorList
ExcelAccessOBJ.ExcelReadColumn(designatorsComboBox.SelectedItem.ToString(), Convert.ToInt16(dataStartRowTextBox.Text), Convert.ToInt16(dataEndRowTextBox.Text), GlobalData.excelDesignatorList);
}
public class ExcelAccess
{
public void ExcelReadColumn(string column, int rowStart, int rowEnd, List<String> saveData)
{
//set up excel stuff
Microsoft.Office.Interop.Excel.Application ExcelObj = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook theWorkbook = ExcelObj.Workbooks.Open(GlobalData.excelFilenameAndPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Microsoft.Office.Interop.Excel.Sheets sheets = theWorkbook.Worksheets;
Microsoft.Office.Interop.Excel.Range data_range;
Microsoft.Office.Interop.Excel.Worksheet sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(1); //first sheet
//Read column
for (int i = rowStart; i <= rowEnd; i )
{
data_range = sheet.get_Range(column i.ToString(), column i.ToString()); //read part number from excel sheet
//Convert cell value to string
string tempString = Convert.ToString(data_range.Cells.Value2);
if (tempString != string.Empty)
{
saveData.Add(tempString);
}
}
theWorkbook.Close();
ExcelObj.Quit();
}
}
CodePudding user response:
Stay on the dispatcher thread and await tasks that execute the long-running methods on background threads:
private async void ProcessButton_Click(object sender, RoutedEventArgs e)
{
if (targetBOMTextBox.Text.Length != 11)
{
MessageBox.Show("Target BOM part number missing or incorrect format.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
ProgressBarProcess.Visibility = Visibility.Visible;
ProgressBarProcess.Minimum = 1;
ProgressBarProcess.Maximum = 5;
ProgressBarProcess.Value = 1;
await Task.Run(() => fillExcelLists());
ProgressBarProcess.Value = 2;
await Task.Run(() => convertTofloatList());
ProgressBarProcess.Value = 3;
await Task.Run(() => splitDesignatorList());
ProgressBarProcess.Value = 4;
await Task.Run(() => fillRecordsList());
ProgressBarProcess.Value = 5;
insertButton.IsEnabled = true;
clearButton.IsEnabled = true;
}
No need to involve the dispatcher really.
CodePudding user response:
Here is what I end up doing and works. I wanna thanks everyone for their help. The main issue I had seems to be that I was accessing UI from where I wasn't supposed to. Also ProgressBarProcess.Minimum and ProgressBarProcess.Maximum don't seem to work as I read (Link), probably something I missed. Thanks again:
private void ProcessButton_Click(object sender, RoutedEventArgs e)
{
if (targetBOMTextBox.Text.Length == 11)
{
GlobalData.TargetBOMpartNo = targetBOMTextBox.Text;
GlobalData.partNoColumn = partNoComboBox.SelectedItem.ToString();
GlobalData.quantityColumn = quantityComboBox.SelectedItem.ToString();
GlobalData.designatorColumn = designatorsComboBox.SelectedItem.ToString();
GlobalData.dataRowStart = Convert.ToInt16(dataStartRowTextBox.Text);
GlobalData.dataRowEnd = Convert.ToInt16(dataEndRowTextBox.Text);
}
else
{
MessageBox.Show("Target BOM part number missing or incorrect format.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
ProcessButton.IsEnabled = false;
Task.Factory.StartNew(() => ProcessButtonFunction());
}
private void ProcessButtonFunction()
{
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Visibility = Visibility.Visible; }));
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 10; }));
fillExcelLists();
convertTofloatList();
splitDesignatorList();
fillRecordsList();
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 100; }));
//insertButton.IsEnabled = true; //this generates an exception do it like below
Dispatcher.BeginInvoke(new Action(delegate () { insertButton.IsEnabled = true; }));
//clearButton.IsEnabled = true; //this generates an exception do it like below
Dispatcher.BeginInvoke(new Action(delegate () { clearButton.IsEnabled = true; }));
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Visibility = Visibility.Hidden; }));
}
private void fillExcelLists()
{
ExcelAccess ExcelAccessOBJ = new ExcelAccess();
//get part numbers from excel column to GlobalData.excelPartNoList
ExcelAccessOBJ.ExcelReadColumn(GlobalData.partNoColumn, GlobalData.dataRowStart, GlobalData.dataRowEnd, GlobalData.excelPartNoList);
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 30; }));
//get quantities from excel column to GlobalData.excelQuantityList
ExcelAccessOBJ.ExcelReadColumn(GlobalData.quantityColumn, GlobalData.dataRowStart, GlobalData.dataRowEnd, GlobalData.excelQuantityList);
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 60; }));
//get designators from excel column to GlobalData.excelDesignatorList
ExcelAccessOBJ.ExcelReadColumn(GlobalData.designatorColumn, GlobalData.dataRowStart, GlobalData.dataRowEnd, GlobalData.excelDesignatorList);
Dispatcher.BeginInvoke(new Action(delegate () { ProgressBarProcess.Value = 90; }));
}