I have a question that I can't find an answer (and I am sure it is due to my limitation :) .
I have a custom control which contains a Grid and its items sources is already filled let's say using a timer. So when I use that custom control in my application (in a wpf) after each 10 seconds, the grid will have some data.
What I want to know, is there a way to catch when the grid content is modified and this from my application, so I will be able to save the content into a file?
I tried to override the Event OnTargetModied but did not succed.
Thank you in advance.
You don't need an event if you already know where in your code that you are updating your items sources. In your timer, after each 10 seconds, after you fill the items sources, also call a method to save the content to a file.
Like this:
// The timer runs every 10 seconds, and it calls this method every time
void TimerCallback()
{
// 1. Update the items sources data here
// 2. Save the content into a file here
}
Related
There were already a few similar questions on stackoverflow, but I haven't found the answer
I have an application that consists of several tab pages. On one of them I'm loading a list of a few dozen user controls at a time. Currently I'm doing it in Load event and because of that I have a small delay before this page is loaded. What I want to do is to make UI more responsive and fill the list after the page is fully loaded. Is there any way to track when the user control has fully loaded it's content?
VisibleChanged doesn't help too, because it fires before any other child control is shown. That causes some ugly visual effects when some of the child controls are still not visible when I'm starting to load control list.
EDIT
To make it more clear. I have some child controls on a page container and I have a list of custom controls I'm trying to load later. The problem with two approaches described in several answers below is that when I'm starting to load controls they do not let other child controls on the container to be shown and that is why I have those ugly effects (and I'm doing that with BackgroundWorker, but anyway it has to interact with the main thread to add controls to the list)
In order to make the UI more responsive, you should post yourself a message (Control.BeginInvoke), do one operation, post yourself another message. Then every time you do anything, the next step will get queued after all user messages, so user actions will get processed promptly.
One really nifty approach is to use yield return and let the compiler take care of all the closures logic:
IEnumerable AsyncLoadUI()
{
var p = new Panel();
Controls.Add(p);
yield return null;
for( int i = 0; i < 50; ++i ) {
var txt = new TextBox();
p.Controls.Add(txt);
yield return null;
}
}
override void OnLoad(EventArgs e)
{
IEnumerator tasks = AsyncLoadUI().GetEnumerator();
MethodInvoker msg = null;
msg = delegate { if (tasks.MoveNext()) BeginInvoke(msg); };
msg();
}
Take a look at my solution offered to another. They had a very similar issue. Wait until EVERYTHING finished its loading before doing a certain action, but not every time a form necessarily became "activated" or "shown". It involves attaching to the Load handler of your outermost control of interest. In your case, the tabbed page, but the example solution I provided was at the FORM level.
If the loading of this list incurs a small delay then doing this load on the UI thread will always make the form unresponsive no matter what event you do it in - changing this to be done after the form has loaded then it will just make the form unresponsive and visible as opposed to just causing a delay before the form is shown.
If there is no way to speed up the loading of the list then you will probably need to change your form loading logic so that the "heavy lifting" is instead done in a background thread so that the form remains responsive while the list is being populated. You should be aware that multithreaded code is more difficult to understand and when done incorrectly can produce bugs that are intermittant and difficult to debug and so you should definitely try to speed up your existing code first. That said if you can't speed up your list loading and the delay is unacceptable then there is not really any alternative.
If you do choose to load your list asynchronously (in a background thread) then the idea is to start a background thread (usually via a BackgroundWorker ) that does the hard work of preparing a list of items to be added - when this has finished (or failed) the form / list box is updated with the supplied list of items.
You should be able to find plenty of resources on how to do this on the internet that will cover this in more detail.
I have a Canvas with ca. 100 Lines and Ellipses.
Now I add 100s of these Canvas to a WrapPanel. This process takes ca. 4-5 Seconds.
Is there a Way to add/load these Canvases asynchrony? I didn't found a way to do so and Dispatcher.Invoke doesn't work (because it is not asynchrony).
Thanks for any suggestion...
Not sure async is the solution here, as I read your question it sounds like you're adding many thousands of UI elements to the UI which are all triggering.
Still not much to go on but...
There is only one UI thread so any work that can offloaded elsewhere will improve performance.
try adding Debug.WriteLine to your logic and use a StopWatch object to time stamp them. You can trace where delays are being created.
review the code which sets up the lines and ellipses, how are you calculating any properties such as size and position. If this can be loaded into an array using an async Task method, you might get some responsiveness back.
are all the elements visible on the screen at the same time. If not, only load the ones that are by using a virtualizing panel.
If you need more pointers, you might have to share the code.
In our application, we are having various windows which contain grid and their respective stores. General code structure of a window we have is as following:
function showWin(){
var storeVar = //code for store
var gridVar = //code for grid with store as storeVar
var winVar = //code for window having gridVar as item
winVar.show();
}
This showWin() function is being called say on a button click which displays the window.
Now when this window is closed then it is destroyed along with its child item grid. But does this also destroy the store associated with the grid? I guess not.
Thus, if storeVar is not destroyed on closing of window (more precisely on destruction of grid) then should this be forcefully removed in order to reduce the extra baggage (as a new copy gets created everytime the function is called) from the memory? If yes, how?
Thanks for any help in advance.
PS: We are using ExtJs ver 4.0.7
Usually you don't create store objects yourself. There is StoreManager class in ExtJs which handles all this in the background. You just access store objects by calling Ext.getStore('MyStore1').
And with this approach each store usually has only one instance in the memory. So you don't need to worry about destroying it either.
Asked the same question in sencha forum and as per the answer received there, I guess that the store doesn't need to be destroyed forcefully as the garbage collector would itself take care of it. More here.
Updating the things here too, hoping it helps someone else looking for the same.
I have a WinForms data entry form that will have upwards of 1500 questions. I have the questions broken into sections, and each section will have an unkown number of questions. Each section is its own user control and has rows (2 panels, 2 labels, a textbox, and another user control) created and added dynamically for each question. The section controls are then added to the form.
My problem is that the process takes a lot of time, even with using TPL (Task Parallel Library). I would ultimately like to create/add the controls and allow the user to start entering data at the same time. The controls are going into a scrollable panel. While the user is entering data, that data will need processed on a local database...so more threading could be necessary.
I have tried working with TPL, which I am new to, by having all the controls added to a list during processing and then sorted and added to the form after the Parallel.ForEach was complete...takes about 20 seconds for over 1200 questions.
I also tried utilizing a BackgroundWorker component. Using the BWC seems to be the faster of the two, but there is a race condition for the ProgressChanged() eventhandler and not all controls get added...not to mention the way the form looks with all the rerendering.
Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?
Thanks
Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?
Most likely, you can use TPL, and get the same response time as BW, but a nicer API for this type of operation.
The trick here is to get a TaskScheduler setup for UI interaction, and then use the Task class to push the controls back onto the UI thread as they're ready. I have a blog post on this specific subject which shows how to get a TaskScheduler setup to use with UI threads.
However, I would recommend keeping these in memory and pushing them in batches, to avoid constantly re-rendering the UI. This is likely to be an issue no matter what you're doing.
That being said - I'd question your overall visual design here - if you're trying to display over 1200 questions to the user, some form of paging is probably a much nicer approach than a huge scrollable container. If you page these, you could load and process the first few (which is probably near instantaneous, since you mentioned you can process about 50 questions/second), and then continue loading the others after the first few questions have been displayed.
Please could you give me your thoughts on the following (especially if its advisable or not to do so)...
Basically, I can successfully import CSV data into a datatable and then bind that datatable to a datagridview. What I would like to do now is run through some validation checks for each row in the grid. Each row will have its data validated thru a Stored Procedure that will do a bunch of checks and return one of two values. I would then like to display this value in the last column (originally empty) of the grid, and then move on to the next row and repeat this action until all rows have been validated.
I hope this paints a clear picture of my intentions. In order to update the UI I would have to use the BackgroundWorker component, but am just concerned that this may not be the right way to go about it, and especially how to go about it.
Please advise me. Thank u!
For a long operation, a background worker is the best way to perform a long task without making the GUI freeze.
You can use the worker's event ProgressChanged event to update the DataGrid. Note that you will have to update the DataGrid using the Invoke method, since GUI must be updated from the correct thread and Invoke transfers your action from the BG's thread to the GUI's thread.