Keep form on top of another form in modal fashion, but continue execution - vb.net

I have a form in a vb.net windows form application called PolicyRefreshStatus.vb that has a ProgressBar control on it. From the main form called EditPolicy.vb I need to show PolicyRefreshStatus.vb over top of EditPolicy.vb - but the way things are wired I'm controlling the the ProgressBar and it's steps from logic inside EditPolicy.vb.
If I display the PolicyRefreshStatus.vb bar using the .show() method things work fine. The problem is if the user clicks back on the main form then PolicyRefreshStatus.vb losses focus. If I show PolicyRefreshStatus.vb as a modal form using .ShowDialog() then execution halts in EditPolicy.vb after the .ShowDialog() statement.
so for example in the code:
mPolicyRefreshStatus = New PolicyRefreshStatus
mPolicyRefreshStatus.pbMax = mPolicy.ClaimsUpdateMax
mPolicyRefreshStatus.ShowDialog()
mPolicy.UpdateFromFIS()
The line mPolicy.UpdateFromFIS() never executes because it's waiting for the PolicyRefreshStatus form to close.
How can I show PolicyRefreshStatus in a modal form but let execution continue in EditPolicy.vb?

You've got a couple of related options.
This first is to pass the unit of work to the progress bar in the form of a delegate or a class implementing an Interface. Something like this (not checked for correctness, just a rough example):
mPolicyRefreshStatus = New PolicyRefreshStatus
mPolicyRefreshStatus.pbMax = mPolicy.ClaimsUpdateMax
mPolicyRefreshStatus.UnitOfWork = AddressOf(mPolicy.UpdateFromFIS())
mPolicyRefreshStatus.ShowDialog()
Then within the progress form you can call back to the routine that actually does the work.
Another approach is to define events on your ProgressForm and then the owning/launching object can handle those events to do the work in. With this option you can create a fairly detailed set of events to be able to handle incremental work or cancels, but the concept is the same, youu are calling back from the progress form into launcher to perform the actual business logic.

You cannot show the form modally and let your routine continue. You must show the form Non-modally and then do your other stuff, closing the form when you've finished. Maybe a loop until the task has finished?
Using Show() with a parent form parameter will give you better usability. More like a tool window.

Related

Stop button in LabVIEW cannot be pressed during while loop execution inside an event structure

I am currently working on a LabVIEW project and have found myself stuck on how to make a while loop exit when I press the abort (stop) button. For a simple while loop I understand how to do this - but the problem is that this while loop is nested inside of an event structure and I'm guessing that the button cannot be pressed while the loop is executing. Attached here is a picture of part of my code (that contains this specific event case which is causing me problems): To spend a little more time explaining what the problem is - I think the code is doing what I want it to do (namely output a set of commands in a repeated cycle with a wait timer) but I cannot stop the code mid cycle (pressing the abort button with my mouse does nothing - as in the button doesn't show it being pressed and the indicator shows no change, I also can't use any other functionality of my program during the cycle which I'm assuming is related). And I do not want to stop the LabVIEW program from running entirely - just the code inside the while loop pictured above. This is what the front panel is configured too for completeness:
Essentially what I want to happen is the while loop to execute when I press DWG and in the middle of the cycle be able to abort it. Sorry if my code seems a little messy. Additionally, I've tried the same code with a for loop originally (via a conditional terminal so it could stop early) and that didn't work either. Thanks for any help I appreciate it!
Your problem is that inside the event structure, by default the UI is frozen so no UI actions (keyboard/mouse/etc) are processed until you exit that frame.
Option 1. You can right click the Event Structure and select "Edit events handled by this case" dialog and then uncheck the "Lock panel" checkbox -- that will allow the UI to be live while you are in that frame. I do not recommend this solution generally unless you have an extremely simple user interface because it leads to the user being able to change controls without the events behind those controls being processed (not a good UI experience for users). But if the UI is simple enough, that works.
Option 2. You can create a user event that is the code you want inside your While Loop. When the Deg Wait Go button is pressed, use the "Generate User Event" node to trigger that event. Do the same thing in the user event case so that the event re-triggers itself if and only if the Abort button has not been pressed.
Option 3. Create a separate loop OUTSIDE your UI loop that does your processing with some sort of command queue running between the UI loop and that other loop. The other loop moves into various states at the request of the UI loop... it's the one that does nothing until it receives a "go" message and then keeps looping until it receives a "stop" message. You can Google "queued message handler" for extensive details of this solution. This is the most common solution for complex UI requirements, especially useful for separating concerns of the UI code from the execution code.

Is There a Way To Simulate the Form Activate from Modal/Pop Up Form

I have a form that opens a modal pop up helper form to collect some data. When this modal pop up form closes, focus returns to the main form. I would like to trigger some activity when focus comes back to my main form.
The event model for the form does not trigger the Form_Activate or Form_GotFocus events when returning from a model popup as per Microsoft documentation.
These forms and all controls are completely unbound.
Is there a trick to knowing in code when focus returns to my form?
If both forms are placed in normal mode, Form_Activate does fire in the primary form when the helper form closes, but this does not meet my needs. I have not been able to find a similar event to trap this. I'm hoping someone has a workaround.
For clarity, the issue I ran into was I had the design time properties in the helper form set to act as a dialog - (pop up and modal as true). When I opened the form responding to the button click event on the main form, I did NOT include the acDialog option.
If you omit the WindowMode=acDialog setting the code operates asynchronously completing the code in the click event handler in full, NOT halting and waiting.
The acDialog option apparently forces the DoCmd.OpenForm command to run synchronously, halting code execution, then returning once the modal form has been closed.
Private Sub btnHelper_Click()
DoCmd.OpenForm "frmHelper", WindowMode:=acDialog
'Do stuff after frmHelper closes
End Sub

Using BackgroundWorker to fetch data

I used the data sources tab to drag and drop some fields from my database onto a form. This created the reqired textboxes/fields/designer components and also created a fill command by default, which is expected.
On my form load event, the following command takes place:
Me.TblQueueTableAdapter.dt_FillIncompleteCases(Me.BE_DataSet.tblQueue)
This command can take a while to fill on the end user's PC. I would like to display something in the meantime while the data is being retrieved so I added a new borderless form which will show before the fill event, then hide after completion.
So the problem as it stands is the main thread is being blocked due to the database fill code above, and my main thread will not display the borderless form. The process of showing and hiding works, but because the thread is blocked, the content of the borderless form is blank. I need to stop the main thread from blocking.
I know I can probably use a background worker to get this data out of the database. I could instantiate a new table adapter and use the fill command in the do work event. If I do this, I canpass back the datatable through e.result but I dont know how to set the datatable to my designer controls. How do I do this?
In the run worker completed event, I imagined something like:
Me.BE_DataSet.tblQueueDataTable = e.result
But this is a type and cannot be set in this way. What do I need to do?

Difference form.Close() and form.hide()

What is the difference between form.Close() and form.Hide() in desktop application.
i know Form_Close event will not be fired in form.Hide() method what about other differences.
Is anyone faster?
form.Close() unloads the form from memory and makes it available to be garbage collected; you can no longer interact with the form in code.
form.Hide() just hides the form, but you can still interact with it in your code.
So it is not really a question of which one is faster, but rather "are you really done using this form or not"?
Hide makes the form invisible to the user. Close actually closes it and calls dispose on it.
From: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.close(v=vs.110).aspx
"When a form is closed, all resources created within the object are closed and the form is disposed. "
Hide only hides the form from the screen. Close is of course closes the form. If you want to get rid of the form that you don't want to use anymore then you should use Close. Hide and Close are different things.
Ditto the above... Typically the way you open the form determines which to use. If you use .Show() the calling code continues while the form is loaded and shown. If you use ShowDialog() then calling code stops while the form is loaded and shown. When you Hide the called form the calling code resumes to the next statement.
Here is a sample of the second case:
Dim frm As New frmSearch2
frm.inFormName = "frmFacility"
frm.ShowDialog(Me)
If frm.outPrimaryKey.Length > 0 Then
frmMain.Open_Form("frmFacility", frm.outPrimaryKey)
End If
frm.Close
frm = Nothing
outPrimaryKey is a form level Public variable. You can also address any of the controls on the form.

TabControl.SelectedIndex being changed, but SelectedIndexChanged even not firing

All,
I have a TabControl in an application that started behaving strangely. Some background...
This program was converted from VB6 to VB .NET 2008, and used to refer to forms using their class names. In other words, I might have a form class called frmFoo. In the code for the program you might see:
frmFoo.Show()
or
frmFoo.UserDefinedProperty = True
During some recent changes, I created variables to represent instances of my forms much like these:
Public MyForm as frmFoo
MyForm = New frmFoo
MyForm.Show()
In doing so, I also removed code from the form's Load event handler and put it in the form's constructor.
When the form loads, or when a document is loaded and should influence the TabControl's selected index, something like the following will not necessarily fire the SelectedIndexChanged event.
MyForm.tbsForm.SelectedIndex = ValueReadFromFile
...or...
MyForm.tbsForm.Tabs(ValueReadFromFile).Select
Sorry to be so wordy, but there's more. If I open the form and look at the TabControl to verify that it's been set properly, everything works like it's supposed to. The misbehaving TabControl is contained within another TabControl, so I have to click the parent TabControl to see it. If I can see it, and run a test, the test always works. If I can't see it, and run a test, the first test I run will not fire the event. ...paging Dr. Heisenberg...
It's almost as if the control has to be initialized first by changing the value or making it visible onscreen...I'm totally lost on this one. It's the most unusual behavior I've ever seen. And everything worked perfectly before I began using variables to represent forms and placed the Load event code into the form constructors.
Can anyone help, or at least put me out of my misery?
SH
-------------------------------------------------------------- Edit #2
I just performed a test after having attempted to eliminate some of the variability in the behavior. But I wanted to confirm the previously-stated behavior.
I opened the program and read a file. This file contained a value that should have triggered the event handler. Without making the control visible, I can change the SelectedIndex property of the tab control without the event firing.
I closed the program down again, and reopened it. This time, selected the parent tab that allowed the child tab (the one whose event I'm concerned with) to become visible. I then selected a different tab in the parent control, meaning that the child control was no longer visible. When I opened the same file as before, it fired the event.
I'm tempted to implement a flag that confirms that the control has been repainted or whether the parent tab has been displayed. I may have to fire the event in code if the flag isn't set.
I want to reiterate that everything worked when the program referred to the forms by their class names and much of the arrangement of controls on the forms was done in the load event. Now the program creates variables and the arrangement of the controls is done in the form's constructor. I'm sure this has something to do with the problem I'm having, but I can't understand how. Any wisdom to share?
MyForm.tbsForm.SelectedIndexChanged = ValueReadFromFile
doesn't make a lot of sense. Is tha trying to assign a handler to the SelectedIndexChanged event? or is ValueReadFromFile the name of the tab?
What you're saying is that you have two tab controls, say, A and B. Tab control B is contained within a tab of A, and unless A has the tab page selected that contains the tab control B, the SelectedIndexChanged event of B will not fire if you change its tab programatically?
In which different ways have you tried to select a tab within the child tab control, and when is this code being executed?