private void RevenueSummary_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'accountingDataSet1.Revenue' table. You can move, or remove it, as needed.
this.revenueTableAdapter.Fill(this.accountingDataSet1.Revenue);
string strGEC = GEClabel.Text;
fillByToolStripButton.PerformClick();
}
hi, I am having problems displaying the data after I add a new revenue item. It will be display in the database but not in the datagridview. It will only appear if I close the application and run it again.
As i can see in your code you are calling the fill method only when the form is Loaded (I am assuming RevenueSummary_Load method is to handle the load event of the form), this makes the accountingDataSet1 to be filled only when your Form is loaded and thats why when you update the database its not reflected in the dataset.
There are two things you can do to solve this.
1) Employ a ServiceBroker that will notify your application when the database is updated via SqlDependency (I assume your Database has this facility).
2) The other simple method would be have a refresh button where you fill the dataset again.
3) Finally you can have a timer that fills the dataset on every interval
NOTE: Both SQL Server and Oracle support Change Data Capture.
Update
I dont know if MS Access has any push notification feature. As i have searched over internet your only options are either to go with timer based database polling or Implement a FileSystemWatcher object to monitor whether your MS Access database file gets changed.
here is an example to this approach.
Related
I'm developing a PDF creator using Windows Forms application in Visual Studio Community 2017. I'm using MigraDoc to generate PDFs and they are directly created by a series of data inserted by the user in textboxes.
The page for inserting and displaying the data is the same, because I want a real time update of the PDF document preview. To display the PDF I'm using an axAcroPDF element obtained in the COM section after the installation of Adobe Reader.
In order to update the PDF document I have written a class that simply introduces the new elements (I use a Leave event trigger on textboxes to call the update) and load the new PDF file inside the axAcroPDF element:
axAcroPDF1.LoadFile(filename);
The problem is the fact that each time I insert new data in one of the textboxes and the leave event is triggered it is like the entire form is reloaded and I lose focus on the textbox I was writing on (data inserted remains but the focus gets totally lost and the writing cursor is not preserved). This happens to the other textboxes if I click on another one or if I use tab to move to the next one. Notice that the PDF is correctly updated. Is there any method to avoid this problem and update the PDF section without losing focus on textboxes? Is it also possible doing that on a changetext event listener for those textboxes?
Here is an extract of the code use. The function updateText is called when a changetext event is detected on the textbox:
private void updateText(object sender, EventArgs e)
{
updateDocument();
axAcroPDF1.LoadFile(filename);
TextBox s = (TextBox)sender;
s.Focus();
}
I have inherited a form and have been tasked with speeding it up. Basically, it is a form which makes a WCF call to a service for some data, and then displays the data in a DataGridView.
I originally thought the bottleneck was the WCF call, so I moved that to a BackgroundWorker, to stop the UI from freezing up.
That helped a little bit, but it turns out that the bottleneck is actually this line:
DumpInfoGrid.DataSource = dumpGridBinding;
where the data retrieved from the WCF is assigned to the DataSource property.
The code basically boils down to this:
private BackgroundWorker dataGatherer;
dataGatherer.DoWork += dataGatherer_DoWork;
dataGatherer.RunWorkerCompleted += dataGatherer_RunWorkerCompleted;
private void dataGatherer_DoWork(object sender, DoWorkEventArgs e)
{
dumpGridBinding = WCF.GetDataFromService();
}
private void dataGatherer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DumpInfoGrid.DataSource = dumpGridBinding;
}
Is there anything I can do to speed this up? Or any part I can move to the BackgroundWorker ? The assignment freezes the UI for far too long.
One possible solution for this would be to use FastDataGridView (or FastDataListView) which is found in ObjectListView, which greatly improves the speed of the DataGridView control by not attempting to process all the records at one time.
Another solution would be to page the DataGridView you currently have, spreading out the load time across the pages as you use them as seen here
You could use virtual mode -
MSDN: http://msdn.microsoft.com/en-us/library/15a31akc.aspx
This mode shows just the rows the user is looking at through the viewable region - you only load the rows actually being viewed - which is fast.
You handle the CellValueNeeded event and provide data from your list when the user scrolls through the list. Tex example shows you how to do that, but it's easy to write a linq statement to skip, take whatever is requested from your datasource (returned from the WCF service).
I have a problem with populating my comboBoxes in a WinForm application that I'm writing. The data that I use to populate these comboBoxes is pulled from database. The problem is that there is a lot of data that needs to be binded to the comboBoxes, so this process takes a very long time during which the entire application is locked (the entire process of binding data takes over 9 seconds, while the process of pulling the data from the database takes only 400 milliseconds). I'm trying to speed things up by splitting the processes of creating the controls (main thread) and populating the comboBoxes (background worker), but naturally I get the cross thread error.
This is the part of code that I use:
private void Populate()
{
comboBox1.BindingContext = new System.Windows.Forms.BindingContext();
comboBox1.DataSource = MyClass.dtMyDataTable;
comboBox1.DisplayMember = "TitleColumn";
.//I repeat the same code for each comboBox
.//I use the BiningContext because some of the comboBoxes have to display the
.//same data.
}
I created a class that contains all DataTables that I need in this form - there are multiple forms that use the same data from the database, so I created a class and created an object that fills all of these DataTables on the parent Form.Load(), and then I pass them to the children forms when I create them. This way I load the data when the application loads (it doesen't even take that long), so it should be ready to use when I call it from child forms. I've tried to call the Populate() method from backgroundWorker.DoWork() method, and there I get the cross thread error.
My question is - is there a way to make this work, and if not, what could I use as alternative solution.
Thank you
I'm not a full bottle on invoking but try this:
PopulateData()
{
if (combobox1.InvokeRequired)
{
combobox1.Invoke(new EventHandler(delegate(object o, EventArgs a)
{
PopulateData();
}
));
}
else
{
// Do your updates here...
}
}
I believe this will find the thread responsible for combobox1, which is going to be the same thread for the other combo's, and then run.
I'm sure someone else will chime in with a better way to invoke perhaps at the form level ?
I've found a good alternative, and it sped things up from 9 seconds to 1.5 seconds. The solution is to place the comboBox.DisplayMember BEFORE the 'comboBox.DataSource' line because when you change the DisplayMember (or ValueMember) the data source repopulates itself. So if the comboBox.DisplayMember is after the 'comboBox.DataSource' line, the data source populates itself 2 times (I think that ClearBeforeFill is enabled by default when binding data sources, that is why there are no duplicates in the binded data).
Thanks anyway.
I have a weird issue with the DataGridView control in virtual mode and threading. I use a Cache class to stored 2 pages of data. When I scroll down and I have to load a new page in cache, there is a little delay before data is display (it's ok). But, instead of having
the next row displayed(199th,200th,201th), the control skip many rows (CellValueNeeded). By example, I cached 1 to 200 rows, when I scrolling at 199, I'm loading a page to 200 à 299. However, in the datagrid it's display the row 320.. instead of 300. (I kept the mouse button pressed 2-3 secondes, before releasing it). I notice I have the problem only when I load the cache in a particular thread. Does anyone have a idea how I can fix this?
private void datagridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
e.Value = m_rfiCache.RetrieveElement(e.RowIndex, e.ColumnIndex);
}
....
public DataTable SupplyPageOfData(int lowerPageBoundary, int rowsPerPage)
{
e : " + lowerPageBoundary);
DataTable dt = new DataTable();
if (m_useThreading) //THIS DOESN'T WORK WELL
{
Thread MulThread = new Thread(delegate()
{
dt = this.LoadData(lowerPageBoundary, rowsPerPage);
});
MulThread.Start();
MulThread.Join();
}
else //OK.
{
dt = this.LoadData(lowerPageBoundary, rowsPerPage);
}
return dt;
}
P.S. : This is only a snippet, I used an external API to extract data from ODB. This API used thread to load data.
Does anyone have a idea or I can fix this?
You can load the data in a background thread, but you can't add it to your main DataTable in the background thread itself.
One potential approach would be to load the data as you're doing, but into a separate DataTable. You could then, on the UI thread, call DataSet.Merge to merge this data in with your bound data correctly (which will be reasonable fast).
Finally, I found the solution. When the tread is processing and the scroll down button is pressed, my event for scrolling aren't sent to the datagrid unless my thread is finished. So I received a bunch of calls for drawing cells and the index was wrong. To avoid this, I removed the vs scrollbar from the datagridview and added a VSscrollbar control. When I'm loading data in my thread, I set to false the enable property on my scrollbar. When the thread is completed, I enable the scrollbar. Is not the BEST solution, but at least, there is now row skipped.
Note : Virtual Mode works very well if you don't load your data in a separate thread.
I've built a form that has a listbox on the left side, and a bunch of text fields on the right for each field in the data source.
When the user clicks on an entry on the left it moves to that record so they can modify the fields on the right. All works fine up to this point.
The problem is that each user has a unique ID number and once they start typing in the record fields I want to populate a hidden field with their ID number so when they save, I know who touched that record.
I cannot find a suitable event to handle this method. I am not using a datagrid, I simply dragged members from the data sources window onto the form accordingly. CurrentChanged and CurrentItemChanged fire off when switching between items on the listbox so these don't reflect the behavior I need.
Any thoughts?
I feel this is a somewhat ugly answer, but it gets the job done without major any major effort. Once everything has been validated and the binding source EndEdit function has been called, you may check the DataSet for changed rows.
Before_Update handles this logic and looks at each row if changes have been made, making the necessary modifications to columns before calling UpdateAll.
Checking for Changed Rows -
http://msdn.microsoft.com/en-US/library/czb9z269%28v=VS.80%29.aspx
// Save event
private void clientBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.clientBindingSource.EndEdit();
Before_Update();
this.tableAdapterManager.UpdateAll(this.dP_TestDataSet);
}
// Place logic in here to modify records if they are changed
private void Before_Update()
{
if (dP_TestDataSet.HasChanges())
{
for (int tRow = 0; tRow < dP_TestDataSet.Tables["Client"].Rows.Count; tRow++)
{
// Modification Logic
if (dP_TestDataSet.Tables["Client"].Rows[tRow].RowState == DataRowState.Modified)
{
dP_TestDataSet.Tables["Client"].Rows[tRow]["userID"] = Program.SYSNG.UserID;
}
// Addition Logic
if (dP_TestDataSet.Tables["Client"].Rows[tRow].RowState == DataRowState.Added)
{
// Addition Logic
// ...
}
// Other RowStates such as Deleted, Detatched or Unchanged work here too
}
}
}
This successfully solves my problem though I am hoping someone comes along to trump this answer. I feel that I am doing extra work that the framework has hidden somewhere under the sheets on me and hope someone can provide me insight to this functionality.