我试图通过将两个方法设为公共然后从另一个类调用方法来在WinForm上创建一个进度条(请参阅下面的代码示例)。但没有运气,酒吧不动。
以下是两个类:
namespace GP_Avantis_Integration
{
//Class B
public partial class GP_Avantis_Integration_Window : Form
{
public GP_Avantis_Integration_Window()
{
InitializeComponent();
}
DataSet ds = new DataSet();
SqlDataAdapter sqlda = new SqlDataAdapter();
SqlCommand sqlcomm = new SqlCommand();
public static int recno;
public void button1_Click(object sender, EventArgs e)
{
try
{
//Fetch data into memory
//Fill in Header table
//Fill in Line table
//Cleaning open connection
//Creating relationship in the Dataset between Header and Line table
// Instantiating and Crearintg Header and Line source
//Binding the Header source to the Header table
//Binding the Line source to the relationship
}
catch (ApplicationException ae)
{
}
finally
{
}
}
public void button2_Click(object sender, EventArgs e)
{
try
{
//Calling CreateJE Class
//Class Method ProcessData
CreateJE JE = new CreateJE(); --------> Calls the Class B
JE.ProcessData(ds);
MessageBox.Show("Complete!");
}
catch (ApplicationException ae)
{
}
finally
{
}
}
public void progress_Bar_setup()
{
progressBar1.Minimum = 0;
progressBar1.Maximum = CreateJE.max;
}
public void progressBar_updates(int recno)
{
progressBar1.Value = recno;
progressBar1.Update();
}
}
// Class B
class CreateJE
{
static public int max;
public void ProcessData (DataSet ds)
{
//Create an eConnect Trx type object
//POPTransactionType po = new POPTransactionType();
// ***** PO Header and Line
int ln;
ln = 0;
//Setting up ProgressBar
int recno = 1;
max = ds.Tables[0].Rows.Count;
GP_Avantis_Integration_Window w = new GP_Avantis_Integration_Window();
w.progress_Bar_setup();
// Create an eConnect PO Header node object
// Create an array for lineitems
foreach (DataRow dtrHDR in ds.Tables["Header"].Rows)
{
//ProgressBar Updates
w.progressBar_updates(recno);
//Instantiating GetJE object
//Retrieves the next JE from GP
//Create an eConnect PO Header node object
//Add the header node to the trx type object
ln = 0;
foreach (DataRow dtrLine in dtrHDR.GetChildRows("HdrLine"))
{
// Populate the elements of the taPoLIne_ItemsTaPOLine XML node
//Avantis Inv Trx Key
// Avantis GL Trx Type
//Add POLine to an Array
ln ++;
}
// Add the header node to the trx type object
// Add the lineitem node to the trx type object
// ***** Process information only
// Create an eConnect document object
// Create a file on the HD
// Serialize using the XmlTextWriter to the file
// Call the eConnectMethods
// Separate Class
// Instantiating the object for eConnectMethods class
// Passing last JRNENTRY retreived using the GetJE class
// so if there is an error on the eConnectEntry Method of eConnectMethods Class
// I can pass the last JE number back to GP
recno++;
}
}
}
}
答案 0 :(得分:0)
很难说出了什么问题。可能是max
值未初始化,可能是update()
方法没有重绘进度条。
还有一件事:使用BackgroundWorker可能会更好,因此您的UI不会锁定?这是一个例子:http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo
答案 1 :(得分:0)
我认为您需要使用渲染优先级调用更新,如下所示:
public void progressbar_updates(int recno)
{
Dispatcher.Invoke(new Action(() =>
{
progressbar1.Value += recno;
progressbar1.UpdateLayout();
}), DispatcherPriority.Render);
}
答案 2 :(得分:0)
实施backgroundWorker并使用backgroundworker.ReportProgress
更新进度条。然后它将在一个线程中实现您的代码,在另一个线程中实现UI。然后表单将响应更新。在读取和写入UI时要小心(因为它位于另一个中)当您启动Backgroundworker并在ReportProgress中写入时,请阅读UI。
答案 3 :(得分:0)
使用背景工作者 这是最好的例子 Click here for BackGroundWorker
答案 4 :(得分:0)
我实施了一个“工人表单”,显示后台任务的进度。
这是我的代码(WorkerForm)
#region Form
private void frmLoader_Load(object sender, EventArgs e)
{
if (OnExecute != null)
{
OnExecute(this, null);
}
}
#endregion
#region "Public"
public void OnInitialize(object sender, EventArgs<String, int> e)
{
if (pbLoader.InvokeRequired)
{
pbLoader.Invoke(new Action<object, EventArgs<String, int>>(OnInitialize), new Object[] { sender, e });
}
else
{
lblDynamicText.Text = e.Param1;
pbLoader.Step = 1;
pbLoader.Minimum = 1;
pbLoader.Value = 1;
pbLoader.Maximum = e.Param2;
}
}
public void OnCreate(object sender, EventArgs<String> e)
{
if (lblDynamicText.InvokeRequired)
{
lblDynamicText.Invoke(new Action<object, EventArgs<String>>(OnCreate), new Object[] { sender, e });
}
else
{
lblDynamicText.Text = e.Param1;
pbLoader.PerformStep();
}
}
public void OnFinished(object sender, EventArgs<String> e)
{
if (lblDynamicText.InvokeRequired)
{
lblDynamicText.Invoke(new Action<object, EventArgs<String>>(OnFinished), new Object[] { sender, e });
}
else
{
lblDynamicText.Text = e.Param1;
}
}
在我的演示者中(我使用的是ModelViewPresenter体系结构),我同时注入了对Winform和实际工作者类的引用。
internal WorkerPresenter(IWorkerView WorkerView,IWorker ConcreteWorker)
{
this.WorkerView = WorkerView;
this.ConcreteWorker = ConcreteWorker;
WorkerView.OnExecute += StartExecute;
}
在我的工人表单的表单加载事件期间引发了StartExecute。
private void StartExecute(Object sender, EventArgs e)
{
ConcreteWorker.OnCreate += Create;
ConcreteWorker.OnFinish += Finished;
ConcreteWorker.OnInitialize += Initialize;
var task = new Task<bool>(ConcreteWorker.Execute);
task.Start();
task.ContinueWith(c_task =>
{
((frmWorker)WorkerView).DialogResult = System.Windows.Forms.DialogResult.OK;
});
}
IWorker界面:
public interface IWorker {
event EventHandler<EventArgs<String>> OnCreate;
event EventHandler<EventArgs<String>> OnFinish;
event EventHandler<EventArgs<String, int>> OnInitialize;
bool Execute();
}
混凝土工人:OnInitialize =&gt;在进度条中设置文本和步骤数。 OnCreate =&gt;将步计数器递增1并设置另一个文本。 OnFinish =&gt;显示文本并再次关闭Worker表单。