Have a modal form but be able to access another already open form
Hi,
I know this sound strange but here is my scenario.
I have designed my app for multiple gridviews. When a user double clicks a row it opens up the data in a modal form and when they commit changes the row gets updated.
While they have that modal window open they can not go back to the grid.
But I have a alerts/messages window always running (like outlook tasks). As soon as I open the modal window I can not access that tasks window. (Default behaviour)
How can I open the modal form and still let the user access/view the tasks window while they work on the modal window.
(I tried creating it in a differant thread, but got a lot of cross thread errors so decided to abandon that approach.
I thought that 2 modal form can run at the same time as long as they have differant parents. But aparently the main GUI thread pauses as soon as you open a modal window on it.
p.s. I use LINQ-SQL entity objects.
Re: Have a modal form but be able to access another already open form
Additional threads are the answer. The cross thread errors are normal. But instead of abandoning that approach just because you don't know how to use it, doesn't mean it's not the best method.
Check the codebank for JMC's post on backgroundworkers and you'll find an appropriate solution.
Re: Have a modal form but be able to access another already open form
Quote:
Originally Posted by
weirddemon
Additional threads are the answer. The cross thread errors are normal. But instead of abandoning that approach just because you don't know how to use it, doesn't mean it's not the best method.
Check the codebank for JMC's post on backgroundworkers and you'll find an appropriate solution.
I've made modifications to the code so it does not throw cross-thread errors. But still running into some problems.
I have a singleton class that creates the connection and provides the datacontext for my LINQ-SQL objects. It is called everytime I need a new datacontext. (For ex. When a new data entry form opens up and needs to populate itself with data)
But as soon as it is accessed via a differant thread I'm getting strange behaviour.
This is the code I have.
Code:
'GUITasksManager.showBusyCursor(False, Me)
'I've commented out the above line because it causes cross thread operations
db = AppTasksManager.GetSingleton.getDB 'cretate new context and return it = line 42
cmbAssignedTo.Items.AddRange(db.Users.Where(Function(u) u.isInactive = False).ToArray)
cmbAssignedTo.DisplayMember = "UserNameFull"
This works fine when run on the same thread, but gives an error saying "Invalid Cast Opeation" on line 42 when running in a differant thread.
the GetDB function looks like
Code:
Public Function getDB() As DataClassesDataContext
Return New DataClassesDataContext(_connString)
End Function
Any idea why?
Re: Have a modal form but be able to access another already open form
System.Threading.ThreadStateException was unhandled by user code
Message="Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.ComboBox.set_AutoCompleteMode(AutoCompleteMode value)
at LuxtonPlant_AssetMan.frmCustomerTask.InitializeComponent() in F:\my work\Luxton Plant\LuxtonPlant_AssetMan\LuxtonPlant_AssetMan\Graphical User Interface\Data Entry Forms\Tasks\frmCustomerTask.Designer.vb:line 167
at LuxtonPlant_AssetMan.frmCustomerTask..ctor()
at LuxtonPlant_AssetMan.GUITasksManager.viewCustomerTask(LogEntry m, Boolean asDialog) in F:\my work\Luxton Plant\LuxtonPlant_AssetMan\LuxtonPlant_AssetMan\Application Control Classes\GUITasksManager.vb:line 1731
at LuxtonPlant_AssetMan.frmMain.WorkerTask_DoWork(Object sender, DoWorkEventArgs e) in F:\my work\Luxton Plant\LuxtonPlant_AssetMan\LuxtonPlant_AssetMan\Graphical User Interface\Application Forms\frmMain.vb:line 180
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
InnerException:
I get that error when using the bakground worker to open a new form.
Re: Have a modal form but be able to access another already open form
It seems to me that, if you want this dialogue to be modal, it needs to be your alerts window that gets created on a different thread.
You can't use a BackgroundWorker is you need an STA thread because the BackgroundWorker uses ThreadPool threads. You will need to create your own Thread explicitly, so that you can call its SetApartmentState method before calling its Start method.
Re: Have a modal form but be able to access another already open form
This sounds headachey. Why not create a single form with a split panel. One panel holds the grid, the other holds the edit form. By default the width of the grid panel is 100% and the edit panel is 0%. Double-clicking an entry 'brings up' the edit form by reversing the widths, like a slider. Only when the save or cancel button is pressed on the edit panel does the slider return to its original position. In this manner you are able to prevent returning to the gridview while a record is being edited, but without the complications of multiple message pumps.
Re: Have a modal form but be able to access another already open form
Quote:
Originally Posted by
MaximilianMayrhofer
This sounds headachey. Why not create a single form with a split panel. One panel holds the grid, the other holds the edit form. By default the width of the grid panel is 100% and the edit panel is 0%. Double-clicking an entry 'brings up' the edit form by reversing the widths, like a slider. Only when the save or cancel button is pressed on the edit panel does the slider return to its original position. In this manner you are able to prevent returning to the gridview while a record is being edited, but without the complications of multiple message pumps.
This is why.
The alerts/tasks can be clicked and responses posted to them.
Say the user gets an alert saying an invoice is overddue. The user clicks on the alert and brings up an window (modal) to add a response.
While typing the response they need to go back to the main screen and browse around customer files and invoices.
And opening a invoice will again bring up a modal window.
See my problem?
I'm developing a fairly complicated IS and the split panels wouldn't work in all scenarios.
Is it worthwhile considering developing a seperate app for the alerts, or giving up letting the user go back to the main screen while they have a alert opened up?
I'm really stuck here. All the dataentry scenarios (about 100) so far have been written in the form of (Click Object -> Open object in modal -> send response back to grid ->refresh grid as neccessary)
Re: Have a modal form but be able to access another already open form
As a very simple example, this worked for me:
vb.net Code:
Imports System.Threading
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim t As New Thread(AddressOf ShowForm2)
t.IsBackground = True
t.SetApartmentState(ApartmentState.STA)
t.Start()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Using f3 As New Form3
f3.ShowDialog()
End Using
End Sub
Private Sub ShowForm2()
Application.Run(New Form2)
End Sub
End Class
Obviously, any communication between Form2 and other forms would require delegation, so you might need to keep the appropriate reference(s) around to use for the purpose.
Re: Have a modal form but be able to access another already open form
Quote:
Originally Posted by
jmcilhinney
As a very simple example, this worked for me:
vb.net Code:
Imports System.Threading
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim t As New Thread(AddressOf ShowForm2)
t.IsBackground = True
t.SetApartmentState(ApartmentState.STA)
t.Start()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Using f3 As New Form3
f3.ShowDialog()
End Using
End Sub
Private Sub ShowForm2()
Application.Run(New Form2)
End Sub
End Class
Obviously, any communication between Form2 and other forms would require delegation, so you might need to keep the appropriate reference(s) around to use for the purpose.
thanks for the reply.
I tried this approach before, but was getting some errors (see my second post).. I have a heap of singleton classes that do the dataconnections.
Is it a good design idea to have a singleton class that can be accessed by many threads?
Re: Have a modal form but be able to access another already open form
There's nothing specific about using a singleton in a multi-threaded environment that should be a problem. If you had issues then they were most likely cross-thread access of controls, which can be fixed using delegation, or synchronisation issues, which can be fixed using SyncLock blocks or the like.
Re: Have a modal form but be able to access another already open form
Quote:
Originally Posted by
jmcilhinney
There's nothing specific about using a singleton in a multi-threaded environment that should be a problem. If you had issues then they were most likely cross-thread access of controls, which can be fixed using delegation, or synchronisation issues, which can be fixed using SyncLock blocks or the like.
thanks, that's what I thought.
No errors so far, I wrapped the cross thread calls in delegate methods. Will give this a fair go.
Thanks everyone.