|
Note quite sure I understand what you mean ...
|
|
|
|
|
I have two forms. One is ParentForm, and on it is a databind combobox. There is also a button, and when the user clicks it, it takes him to another form where he can enter some new information and add those information to a datasource to which my combobox is connected to. That information should then be displayed in combobox, but I need to refresh it first, and I have no idea how to do that.
The point it, I need to refresh combobox or the entire ParentForm.
|
|
|
|
|
If you created an instance of your and displayed a form (FormB) from FormA. Then the property FormB.Parent would be set to FormA (you can also set this yourself to any form)
Therefor by calling this.Parent.Refresh(); from your child form, your main form should be updated.
If your combobox still isn't updated, then you'll have to write a public method on your main form that updates the combobox. Then you can call the method from the child form by whatever means you know how.
My current favourite word is: Bacon!
-SK Genius
|
|
|
|
|
ok, you didn't say anything about data, I thought you just want to refresh the form .. anyways, the dirty solution is to reassign the data source that contains the data (whatever that is, a collection or a data table or view) to the datasource of the combobox, I think there's also a method on the data source property that you may call, you may check the documentation for that, so, create a public method in your parent form, something like RefreshComboBox(), and call it from the child form, (don't forget to pass a reference to your parent form in the constructor of the child form) .. the other solution is to bind your combobox to a BindingList (or a class that implements IBindingList), and pass a reference to the binding list to the child form, beware though that whenever the data in the binding list changes the data in the combobox will change regardless of whether the data was saved to the database or not, this will work very well with addition and deletion from the binding list, if you also want the combobox to display modified data, ie. the data of an item was changed, you have to implement INotifyPropertyChanged in the class of the objects contained in the binding list ..
hope this helps...
|
|
|
|
|
All,
I have a main GUI that is a singleton and I am trying to use it in a Background Worker that performs a ShowDialog on a newly created form. The ShowDialog needs and IWin32Window to properly render the new form, how do I "safely" use the main form instance in the ShowDialog? I keep getting [InvalidOperationException] and I am not sure how to use delegates on the entire form rather than a control.
Thanks,
Lawrence
|
|
|
|
|
First, it sounds like you're abusing the BackgroundWorker. The BackgroundWorker is meant for running non-UI work on a background thread. If you want to update the UI during that work, call worker.ReportProgress, which will fire the ProgressChanged event on the UI thread. Also, the RunWorkerCompleted event will fire when the work is done, and it will fire on the UI thread.
If you really have to create forms or controls on a background thread, you must ensure that the thread is STA. Look at Thread.SetApartmentState before you start the thread. You can't make BackgroundWorker threads be STA, so the BackgroundWorker won't work for this.
Ideally, however, you use just a single thread to create and change your UI controls. Without this, you're going to have thread marshalling nightmares if different UIs need to be accessed on different threads.
To sum up, use a background worker to perform non-UI related work on a background thread. If you need to update the UI from this background thread, call worker.ReportProgress and do the UI update inside a worker.ProgressChanged event handler.
|
|
|
|
|
Thanks for your response!!
Ok, so I have moved my functionality to a thread instead of a background worker but I still get the error when I try to ShowDialog(Instance()) with-in my thread where the instance is the Main GUI. How do I invoke the whole form or Instance?
By the way, I did set the SetApartmentState to STA.
Lawrence.
|
|
|
|
|
What does Instance() do? It's hard to diagnose your problem without some source code.
As I said before, I suspect you're approaching this wrong. Let's step back and ask, why do you want to create and show a form on a background thread?
|
|
|
|
|
Instance() returns static instance of the main form in my project..
Ok, I have a thread doing this work because I have a progress bar (marquee) on the main form that displays when potentially time consuming activities are happening. When I Show my new form it holds up the thread and I don’t see my progress bar being updated until after the form comes up. So I decided to kick off that work in its own thread so I can see my progress bar being updated.
If you need anymore info please don’t hesitate to ask.
Thanks,
Lawrence
|
|
|
|
|
I think the problem is that you're essentially modifying your main form on a background thread by making it become the owner of a form created on a different thread. This is bound to cause issues.
I guess what I'm saying is, there may not be a way to assign one form to be the owner of another when they're created on different threads. I think that's "illegal" by Win32 UI standards. I could be wrong about that, but I've never seen it done.
There are some alternatives that come to mind, both involve no threads:
- Forcibly update the main form's progress bar during the initialization of the second form. This involves sprinkling mainForm.ProgressBar.Update() calls during the creation and showing of the second form.
- Don't make the showing of the secondary form take so long: don't do any work during initialization, lazily initialize everything you can, wait for Application.Idle event to do anything, etc.
I guess both of those boil down to: find out what's taking long when showing the 2nd form, then spread out that work so it doesn't freeze your main form.
|
|
|
|
|
Thanks for all your help. I will try to force the updates on to the main form from the second form because I can't lazy initialize this time.
Thanks again.
Lawrence
|
|
|
|
|
Tried option 1 and the Main Form will not render the progress bar while it’s trying to load form 2. After form 2 is loaded then I see the progress bar update. I am now back to square 1.
Any other ideas?
Lawrence
|
|
|
|
|
Lawrence, what is the 2nd form doing that causes the UI to freeze? Is it performing a lot of work? Does it have a lot of controls on it?
|
|
|
|
|
Judah, it doesn't have much controls but it's doing a webrequest POST which takes some time.
I think I found a solution; the thread that starts the second form is being launched from a dummy class that inherits from Form. This allows the form to pop up; the only catch is I will have to do some manual work if I want to make it model.
Lawrence
|
|
|
|
|
lgelliott wrote: it's doing a webrequest POST
Can that be done on a background thread? This way, the UI won't freeze during the request.
Anyways, whatever solution works for you, if subclassing works, well, hell, so be it. I'm feeling especially pragmatic today.
|
|
|
|
|
It is being done in a background thread. I am not able to make the first form model because I am not doing a showdialog on the first form, I am doing it from my class that inherits form. So the model is really only on the thread.
Lawrence
|
|
|
|
|
Hello everyone,
For the following code pattern, suppose both Base class and Component class are implementing IDisposable.
In the destructor of Foo class, there is no need to call Dispose method of Base class and Component class explicitly, and they will be called automatically during the Finalize process of Foo instance?
Class Foo : Base
{
private Component component = new Component();
~Foo()
{
}
}
thanks in advance,
George
|
|
|
|
|
You shouldn't have a finalizer in the derived class, that will be inherited from the base class.
See here:
Dispose pattern guidelines[^]
If you follow this pattern, Your derived class (Foo) should have a Dispose(bool disposing) method that calls the dispose method of any private managed disposable objects (your component object) if true is passed. This method will be called by the finaliser and the dispose() methods of the base class.
Simon
|
|
|
|
|
Hi Simon,
1.
I am totally confused. In C#, we are not allowed to program Finalize method, so do you mean I should not have a destructor in derived class by below quoted comments?
2.
BTW: if the derived class manages native resource, I think it needs to have a destructor. Any comments?
Simon Stevens wrote: You shouldn't have a finalizer in the derived class, that will be inherited from the base class.
regards,
George
|
|
|
|
|
Ok,
there is no such thing as a destructor in c#. Destructors are methods that are deterministically called when an object is deleted. These exist in c++, but c# doesn't have them. Instead, in c# we have a finalize method. (with the ~ sign). When a class has a finalizer it indicates to the .net runtime that when the object is finished with, don't just free it's memory, first we need to clean up. So, when the object goes out of scope, the CLR puts the object in a finalizer queue. Periodcally, the CLR goes down the queue and calls all the finalizers. The important thing here is that you don't know when a finalizer will get called, (or it may in fact never get called).
Because of this, MS have created what is called the dispose pattern. The dispose pattern allows us to fake the behaviour of a deterministic destructor.
You need 3 methods.
1) A finalizer
2) A Dispose method that takes no parameters
3) A Dispose method that takes a boolean parameter.
From the finalizer call Dispose(false). From the dispose() method call Dispose(true).
Then make your 3rd method look like this
Dispose(bool isDisposing)
{
if(isDisposing)
{
if(component != null)
{
component.Dispose();
}
GC.SuppressFinalize(this);
}
}
Now, when you use your object, you can always make sure you call dispose() on it when your done with it. This then calls Dispose(true) and everything gets cleaned up exactly when you want it too (faking the behaviour of a deterministic destructor). If however, you forget to call dispose() when you're finished, (Or your class is used by a beginner programmer who doesn't know they have to do this) then you don't have to worry, because when the object is finished with, the CLR will automatically stick it in the finailzer queue so dispose(false) will get called eventually cleaning up any native resources to prevent memory leaks. (You don't clean up managed resources if the object is being finalized by the CLR, you just let them get finalized too)
Soooo... to answer your question. No, the derived class should not have a finalizer. Only the base class should. The derived class should override the Dispose(bool isDisposing) method to clean up the derived classes resources. The base classes finaliser will call the derived classes overridden dispose(false) method (because it's a virtual method) which will then clean up your derived classes native resources.
Really recommend you read CLR via C# to get a good idea of how this all works.
(Yes led mike, you don't have to say it... )
Simon
|
|
|
|
|
Great Simon!
Two more comments,
1. What are "MANAGED resources"? As you mentioned "// Clear up MANAGED resources here."? In my understanding, managed resource is a C# class which implements IDisposable interface or have a Finalizer, and such class may have wrapped native resource. Not sure whether my understanding of the concept of managed resource is correct?
2.
About your design pattern below, I think you mean some code like this, right?
http://msdn2.microsoft.com/en-us/library/b1yfkh5e(VS.80).aspx[^]
--------------------
No, the derived class should not have a finalizer. Only the base class should. The derived class should override the Dispose(bool isDisposing) method to clean up the derived classes resources. The base classes finaliser will call the derived classes overridden dispose(false) method (because it's a virtual method) which will then clean up your derived classes native resources.
--------------------
I think the issue of implementing Finalizer (implementation like, invokding Dispose with bool input parameter in Finalizer) in derived class is, the Dispose(bool) method in derived class will be called multiple of times from both base class's Finalizer and Derived class's Finalizer?
regards,
George
|
|
|
|
|
1. Yes, managed resources are C# classes that implement IDisposable. Or maybe for example a C# class that needs closing, like a file or database connection.
Yes, a managed class may wrap some native/unmanaged resources, but you don't have to worry about them. For example, the Form class wraps various native resources like window handles etc but you can just ignore that they are wrapped internally within the Form class and will be dealt with by the form. You can just treat any Form objects as managed resources.
2. Yes, that link is a good example of the full dispose pattern.
Yes, there are issues around the Dispose method being called twice if you implement the finalizer on dervied classes. You should always be careful to write your dispose method in such a way that it can get called twice without causing problems, because sometimes the finalizer can get kicked off before you've had chance to suppress it. This is why sometimes you see people setting a disposed flag the first time, so no work is done if it gets called again.
You seem to have an understanding of this. Disposal is complicated, just stick to the pattern on MSDN though and you can't go far wrong.
Simon
|
|
|
|
|
Thanks Simon,
I think there is another solution, which is only the most derived class implements Finalize method, and in the Finalize method, call Dispose method, in the Dispose method, call base class's Dispose method. As mentioned here,
http://msdn2.microsoft.com/en-us/library/b1yfkh5e(VS.80).aspx[^]
--------------------
Implement the dispose design pattern on a base type that commonly has derived types that hold onto resources, even if the base type does not. If the base type has a Close method, often this indicates the need to implement Dispose. In such cases, do not implement a Finalize method on the base type. Finalize should be implemented in any derived types that introduce resources that require cleanup.
--------------------
Do you think it will achieve the same effect as your method below?
--------------------
No, the derived class should not have a finalizer. Only the base class should. The derived class should override the Dispose(bool isDisposing) method to clean up the derived classes resources. The base classes finaliser will call the derived classes overridden dispose(false) method (because it's a virtual method) which will then clean up your derived classes native resources.
--------------------
regards,
George
|
|
|
|
|
Thats talking about a special case where your base class doesn't need a finalizer.
If your base class needs a finalizer, put it in the base class and don't put one in the derived class.
Simon
|
|
|
|
|
Thanks Simon,
The special case, you mean only derived class wrap real native resource, but base class does not wrap native resource, so in this case, we only need to add Finalizer in derived class?
regards,
George
|
|
|
|
|