Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 558
  • Last Modified:

Need Help Disposing A Button in a .NET Dialog Popup

Hello,

I am building a VB.NET PC application using VS 2008 and .NET Framework 3.5.

I am trying to dispose a control (a button) created programmatically in a dialog popup (by executing code connected to another button).

My code is: Me.Controls("btnMXReset").Dispose(), where btnMXReset is the name of the button.

My code compiles without error, but crashes on execution.  The error message tells me nothing of value ("Object reference not set to an instance of an object").

Oddly, I'm using exactly the same syntax to dispose of User Controls on the popup, and that code works.

Can anyone supply me with the correct syntax?

Thank you, Stu Engelman
0
stuengelman
Asked:
stuengelman
  • 23
  • 10
  • 9
  • +1
2 Solutions
 
rgn2121Commented:
Although I haven't used this to dispose, the syntax is probably correct otherwise you would have gotten the error long before you tried to debug.  I am more interested in the code before this, more specifically dealing with "...executing code connected to another button"

It seems at some point your btnMXReset becomes Nothing...
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
The syntax is OK, it is probably the timing and the logic in the application that causes the error.

Is the error happening on the call to Dispose or after that? What is the line that causes the error?

If you call Dispose and the Control is no longer part of the Form (might have been removed by Me.Controls.Remove, set to Nothing or Dispose is in the FormClosed event), Dispose will crash.

If there is code later that tries to use the Control, that code will crash because the Control will have been disposed?
0
 
stuengelmanAuthor Commented:
Hi Rgn2121,

After the dialog pops, the Load handler for the dialog populates the form with a variable number of User Controls (depending on how many records are on a DB table), and then renders two control buttons on the bottom.  What's strange is that I'm having no problem using the Dispose method to eliminate the User Controls, but the code crashes when I try to Dispose either of the buttons.

The basic idea is that when the "dispose button" is pressed, it's supposed to perform all the Dispose operations (including disposing the "dispose button" itself).

The code for creating one of the buttons is shown in the snippet (this code is in the Load handler for the dialog popup).

It seems strange that the buttons could become Nothing, as the Close button operates (its handler btnMXClose_Clicked closes the popup).  Also, the "dispose button" operates too, in the sense that it properly disposes the User Controls, before crashing on trying to Dispose either of the buttons.  Thus, it seems unlikely that the buttons could have a value of Nothing after being rendered.  I think it's more likely a syntax issue of some type.

Stu
Dim btnMXClose As New Button
Me.Controls.Add(btnMXClose)
btnMXClose.Text = "Close"
btnMXClose.BackColor = Color.White
btnMXClose.Left = (Me.Width / 2) - (btnMXClose.Width / 2)
btnMXClose.Top = resettop
AddHandler btnMXClose.Click, AddressOf btnMXClose_Clicked

Open in new window

0
NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

 
stuengelmanAuthor Commented:
Hi James,

Please see my 09/13/11 09:09 AM reply to Rgn2121.

The crash occurs on the invocation of the Dispose method (just for the native button objects; the Dispose method is working perfectly for the User Controls).

An example of a line that crashes is: Me.Controls("btnMXClose").Dispose()

There are no issues with Remove or setting to Nothing (I'm not doing either of these).

Do you think syntax like Me.Controls("controlname").Remove might work better?  If this works, will the control be wiped out of RAM (either immediately, or later by the Garbage Collector)?

Thanks, Stu
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
If I understand well, you call Dispose on the button inside of the Click event of the button?

This is not permitted.

If this is the case, set and start a Timer at the end of the event button. This will enable the event to terminate, and you will be able to dispose of the button when the event fires.

You do not absolutely have to Dispose of the Button however. It is a good practice, but Dispose simply releases a bit of memory (not much for a button) faster than it would be otherwise. And since the Button has been included in the form's Controls collection, it will be Disposed by the form when you close it. If you are curious, give a look at the Dispose method of the form in the usually hidden .Designer.vb file for the form. This method is called when you close the form, and it calls Dispose on all the controls on the form.
0
 
stuengelmanAuthor Commented:
Hi James,

I follow what you're saying, but I tried commenting out the Dispose call on the "dispose button" itself.  The same crash occured when I tried to Dispose the other button.  I still think I have some type of a syntax issue.

Stu
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
How many buttons do you have to dispose of. As I told you, Dispose is a good practice, but is usually not necessary. Most people do not dispose of their controls otherwise.

Here is another one to try if you absolutely want to dispose of your controls.

You are disposing of the buttons while the form still has a reference to them through its Controls collection. Since we do not know what the form does under the hood, it is possible that the message comes indirectly from there.

Keep the reference to as a class member so that you still have it when disposing of your controls, and remove the control from the Controls collection before disposing of it:

Me.Controls.Remove(btnName)
btnName.Dispose()
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
You haven't set the Name() property of your Button when you create it.  Thus Me.Controls("btnMXClose") is returning Nothing because a match is not found.

Set the Name() property when you create it:   *The variable name is not the same thing!

    Dim btnMXClose As New Button
    btnMXClose.Name = "btnMXClose"

0
 
stuengelmanAuthor Commented:
James - good ideas, will try them out.

Idle - I bet that's a BIG part of it (the User Controls ARE "named", which is why I can reference them). HAHAHAHA  - Thank you, will incorporate what you said.

To both - have been working about 10 hours, and I may not be able to reply again until late PM or early AM US EST (due to need to get some rest).  Sorry for the short delay, and thanks to both of you so much for your help.

Best regards, Stu
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
You do not have to name controls. If you keep a reference (variable) active, the 3 following lines do the same thing.
Me.Controls("btnMXClose").Dispose()
Me.Controls(btnMXClose).Dispose()
btnMXClose.Dispose()

Open in new window

If you use the second one, then you do not need to give a name to the control, and save the memory for 1 String.

Since a reference is only a pointer (32 bits), but a String is a reference PLUS 16 bits for every character, the reference takes less space in memory. Direct access to the button through its reference (btnMXClose.Visible as an example) is also faster than going through the collection (Me.Controls("btnMXClose").Visible)
0
 
stuengelmanAuthor Commented:
Hi James,

Thanks, will take that into account.

Stu
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
While true James, the amount of memory being used and speed difference in the grand scheme of things is negligible.

The searching method can be quite useful for situations where you end up having to deal with many dynamic controls as you wouldn't need to keep a hard coded reference for each one (especially if you don't know how many might be created!).
0
 
stuengelmanAuthor Commented:
Hi Idle,

Will keep your point in mid.

Thank you, Stu
0
 
stuengelmanAuthor Commented:
*mid" s/b "mind"
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
Any approach can be good at that level. And I concur with you Idle, the amount of memory and speed difference would be negligible.

But in my way of thinking, negligible is not nothing. Performance issues are often an accumulation of those little negligible things. If you develop coding reflexes that automatically takes care of those negligible things, they wont accumulate. Thus, performance issues arise less often, and when you get one, you spend less time spent trying to point out possible sources of a performance issue. I value my own time more than performance, but my customers do not have the same idea.

For me, if I had many dynamic controls, I would simply add them to a collection, thus only one reference to keep. Over the best way to do things, we also all have our style :-).
0
 
stuengelmanAuthor Commented:
Hi James,

Good points, I agree.

Stu
0
 
stuengelmanAuthor Commented:
Hi Guys,

Making good progress.  Assigning the Name properties to the buttons eliminated the crash.  Now two additional issues popped up:

(1) The form takes a long time to dispose the User Controls; you actually see it flashing as it eliminates them one-by-one.  I use the following syntax to speed up initial rendering of controls:

Me.SuspendLayout()
'create controls programmatically
Me.ResumeLayout()
Me.PerformLayout()

The above logic does not speed up Dispose operations.  Would it help if I did a Remove before doing the Dispose?

(2) After running the dispose button handler, the popup is scolled to the bottom.  Apparently, Dialog Boxes don't have a ScrollTo method.  How do I get the scroller to go to the top?

Thanks, Stu
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Use SendMessage() and WM_SETREDRAW to suppress repainting while you remove the controls:
http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21963638.html#17368567

For scrolling, try something like:

    this.ScrollToControl(someControlReferenceHere);
0
 
stuengelmanAuthor Commented:
Hello again,

Further to my last post:

(1) I tried using the Remove method instead of the Dispose method for the User Controls, but the clearing speed was the same.

(2) I tried Me.ScrollToControl(lblExpenseList), where lblExpenseList is a label near the top of the form.  As before, I am getting unpredictable results.  Sometimes after the "refresh" (dispose button is pressed), the form auto-scrolls to the top user control, or just remains at the bottom.  What I'm really looking for is something equivalent to the ScrollToTop Method (WPF has it, but dialog boxes don't appear to have this method).  The idea is to scroll all the way to the top of the dialog as the final step of the dispose button handler.

Stu
0
 
stuengelmanAuthor Commented:
Hi Idle,

In regard to:

(1) Could you please provide some VB sample code (I can't read C#)?  What I'm doing now is shown in the code snippet.

(2) As mentioned, I tried the ScrollToControl method, but it didn't work.  If dialog boxes don't have a ScrollToTop method, is there any method provided so I can scroll to stated coordinates (i.e., (0,0))?

Stu
Me.SuspendLayout()
For i = 1 To ctlcounter
    Me.Controls("mxrow" & CStr(i)).Dispose()
Next
Me.Controls("btnMXReset").Dispose()
Me.Controls("btnMXClose").Dispose()
Me.ResumeLayout()
Me.PerformLayout()

Open in new window

0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Sorry about the C# code...I switch back and forth so often I forget where I am and it all looks the same to me!

VB Code would look something like:  
Public Class Form1

    Private Const WM_SETREDRAW As Integer = &HB

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        SendMessage(Me.Handle, WM_SETREDRAW, False, 0) ' Turn OFF updates

        ' ... do some stuff in here ...

        SendMessage(Me.Handle, WM_SETREDRAW, True, 0) ' Turn ON updates
        Me.Refresh()
    End Sub

End Class

Open in new window


>> "If dialog boxes don't have a ScrollToTop method"

How is your form a "dialog"?...how was it created and shown...and how did you make it scrollable?
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
I tried using the Remove method instead of the Dispose method for the User Controls, but the clearing speed was the same.

Let's clarify something, because I see that you do not understand what Dispose does.

I repeat, although it is a good practice, you do not have to call Dispose on controls, any controls. It will eventually be done automatically by the system.

You manipulate a variable through a variable. You do not always see it that way, but when you name a Button something like btnClose, a variable called btnClose is created. When you add the control (Me.Controls.Add(btnMXClose)) to the collection of Controls, you are simply passing this pointer to a collection that sometimes works will all controls.

The button itself is somewhere in memory. That pointer is only the location of the button. The pointer exists as long as you still have your variable OR the controls is part of the collection.

If you lose your variable (End Sub for a local variable / Setting the variable to Nothing), the pointer still exists in the Controls collection.

If you Remove the control from the collection, you simply remove that copy of the variable. You do not destroy the Object.

When you have both removed the control and lost the variable, the pointer is lost. This is not much, this is only the address in memory (4 bytes on 32-bits computers). You do not see the control anymore, but the Object itself, all the properties of the Control are still in memory. They are managed by something called the Garbage Collector. It's role is to optimize the use of memory.

So, losing a variable and calling Remove does not do much, it clears up 4 bytes.

Dispose does something completely different. But it still does not clear up the memory used by the control. It calls the object and tells it to clean up the ressources it could be using. If the object opened a file, started a timer in Windows, those will be closed. But the object will still be in memory. .NET used Managed code. The Garbage Collector is the manager. The memory used by the object will be cleared only when the GC decides so. You have no control over that (yes you have, but you should not do it, otherwise you obliterate the usefullness of a Garbage Collector, so I won't tell you how). If you did not call Dispose while you had the pointer to the object, the Garbage Collector will do it when it decides to reclaim the memory used up by the object.

What happens when you call Dispose on a Control then? Almost Nothing for most controls.

What happens if you do not call Dispose? If you look at the code hidden in the .designer.vb file that is hidden under your Form, you will see that it contains a Dispose method. This method is automatically called when you close the form. This Dispose method loops through all the controls on your form and call their Dispose method.

You do not need to implicitely call Dispose, it is done for you by the code generator by the Form Designer.

What happens if the application crashes? The Gargage Collector knows it because he (or she?) is aware of everything that happens in the framework memory space. It does nothing though.

When it will need some memory, it will look through the useless objects lying there, select one, call its Dispose and then clean up that space in memory.

When you shutdown Windows, the Garbage Collector calls Dispose on all the objects still lying in its memory space, to make sure that all files, network connections, database connections, you name it, has been take care of.

So all that discussion about having problem disposing of a simple Button is over the head. Dispose will be called when needed.

I repeat. This is a good practice, but not necessary. There are a few cases where it can help, but its hard to tell because we do not know the inner workings of all those 9000+ classes in the framework. When it can help, usually the documentation suggests calling Dispose before losing the reference (the pointer / the variable). It could help if you had 2000 buttons to dispose of, because it would give the GC a better choice when come time to reclaim memory with as little impact as possible on the performance of running applications.

But all this discussion because you are not able to dispose of one Button is greatly overrated. Don't call Dispose on those Buttons. The system will do it for you when you close the form, when the garbage collector decides that it's time to do so, or when you shutdown windows.
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
In this case, calling Dispose() also removes the control from the form:  
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Button2.Dispose()
    End Sub

End Class

Open in new window

Idle-Mind-500007.flv
0
 
stuengelmanAuthor Commented:
Idle,

Your code for suppressing the very lengthy "flickering" as my logic disposes the User Controls does not help.  I get exaclty the same long flickering as when I do no layout suspension, or I suspend layout using:

Me.SuspendLayout()
'Dispose of multiple User Controls via FOR Loop
Me.ResumeLayout()
Me.PerformLayout()

I tried my logic shown just above using the Remove method, but it makes no difference.  In both cases I get the long flickering.

I also tried your suppression code using Remove instead of Dispose, but the result is the same.

I feel really stumped here.  My logic shown just above does a beautiful job speeding up the rendering of my User Controls when I instantiate them programmatically.  The issue is that I need the ability to refresh the entire dialog (purge and reinstantiate all the User Controls) via a "Refresh" button.  I simply can't get the "purge" portion of the logic to operate quickly.

Stu
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Can you show your attempt with WM_SETREDRAW?....
0
 
stuengelmanAuthor Commented:
Hi James,

Thanks so much for the lesson on Dispose and Remove.  Please tell me if this understanding is correct:

(1) Remove eliminates an object from a collection, but in some cases it may still be accessible directly or as part of a different collection.
(2) Dispose completely eliminates all access to an object.
(3) In both cases above, RAM used by the object is not cleared until the GC does this for you.

Stu
0
 
stuengelmanAuthor Commented:
Hi Idle,

Please see code snippet.

Thanks, Stu
At Popup's Class Level:
-----------------------
Private Const WM_SETREDRAW As Integer = &HB
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

Within Handler For Reset Button
-------------------------------
SendMessage(Me.Handle, WM_SETREDRAW, False, 0)
For i = 1 To ctlcounter
    Me.Controls("mxrow" & CStr(i)).Dispose()
Next
Me.Controls("btnMXReset").Dispose()
Me.Controls("btnMXClose").Dispose()
SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
Me.Refresh()
mdgExpListMgr_Load(Nothing, Nothing)

Note: the final line above calls the dialog's Load handler to recreate the controls on the form.

Open in new window

0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
What else is being added to the form?...what other code is there?...what is in the UserControls?

How many controls are we talking about?

I'm not getting any flickering at all...
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
Almost right for (1), confused for (2), right on the spot for (3). These concepts can be hard to grasp because they involve things that happens under the hood, things that we do not see unless we have special tools to examine the computer memory while the application is running. So let's clarify, you were almost there.

 -----

(1) Almost, because it can be something else than a Collection, but for the purpose of your previous discussion, lets stick to the collection.

You lose the access when you lose all reference. In you original code, you had two references. The variable btnMXClose, as well as the Controls collection once the button was added to the collection.

Assuming that it is a local variable, when you get out of your procedure, you lose btnMXClose. But since the Controls collection is managed by the Form and you still have access to it, there is one reference left. When you Remove the button from the collection, you cannot access it throuh Controls. You have lost your second reference, none is left. The control is not accessible, but still in memory.

Probably no big deal for a Button.

But if you had used an object that "works" with the system, let's say a FileStream object that opens a file in Windows. And let's say that you forgot to Close the file before losing all your references. Who will close the file?

This one is easy to grasp, a file left opened and probably locked. But since we do not know the inner working of classes, it is not always evident that you might need to force some kind of cleanup before losing a reference to an object. And even when you know you should do it, you could forget (not closing the file).

That's were Dispose comes into play.

-----
(2) Dispose does not eliminates the access to an object, this is done when you lose all references (variables and properties) that would enable you to manipulate the object.

Dispose is a safeguard. A standard method that Microsoft has designed so that it will be called at some point no matter what, as explained in my previous post.

Not all classes need a Dispose, and most do not have one.

But a programmer who knows how to program a class in .NET and who knows that his class uses external resources outside of .NET will provide a Dispose method. This method will clean up everything that was started by the class and could cause problems if it is not stopped (opened files and database connections, timers, and a few others).

That is the sole role of Dispose.

It can be called by you, by the garbage collector when it needs to free memory, by Windows that is closing. A form automatically calls Dispose on it's controls when you close it. The thing is that except for a power failure on the computer, Dispose will be called at some point in time to make sure that everything is terminated properly.

-----

(3) You got just right.
0
 
stuengelmanAuthor Commented:
Hi James,

Thanks, I follow now.

Stu
0
 
stuengelmanAuthor Commented:
Hi Idle,

There are about 200 User Controls.  Each User Control contains a combobox, two textboxes, a checkbox, and three buttons.

The only other things on the form are the background, a label, and two buttons.

The Reset button's handler disposes the 200 User Controls and the two buttons, and then calls the dialog's Load handler to recreate them.  The recreate process is just as fast as the original load.  The problem is the time required to dispose the 200 User Controls.  The system flickers as it disposes each User Control, and the process takes about 30-60 seconds.

Stu
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
I have seen "background". Very bad word.

It is very hard if not impossible to prevent flickering when you use an intricate background such as a bitmap or a gradient. The Paint event is called for every control that gets added to the form. Since in intricate background takes some time to redraw itself, it produces flickering.

That problem arose in another post that was closed today.

Your solution is to use a plain background.
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
This combo seemed to work for me...
Public Class Form1

    Private Const WM_SETREDRAW As Integer = &HB
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        SendMessage(Me.Handle, WM_SETREDRAW, False, 0)
        Me.SuspendLayout()

        For i As Integer = 1 To 200
            Dim uc1 As New UserControl1
            uc1.Name = "UserControl1" & i
            uc1.TextBox1.Text = "Instance #" & i
            uc1.Location = New Point(25, 25 + (uc1.Height + 7) * i)
            Me.Controls.Add(uc1)
        Next

        Me.ResumeLayout()
        SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        SendMessage(Me.Handle, WM_SETREDRAW, False, 0)

        For i As Integer = 1 To 200
            Me.Controls("UserControl1" & i).Dispose()
        Next

        SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
        Form1_Load(Nothing, Nothing)
    End Sub
End Class

Open in new window

0
 
stuengelmanAuthor Commented:
Hi Idle,

Have already tried the method in your last post.

Will try the idea James put forward (have a short background at the top, followed by a solid background color).

Stu
0
 
stuengelmanAuthor Commented:
Idle and James,

I tried two additional tests, each time invoking the line Me.BackgroundImage = Nothing before doing anything else in the Reset button handler.  The first test used the SuspendLayout strategy, and the second used Idle's SendMessage strategy.  In both cases I got the long flickering.

Stu
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
In my last submission, I'm using both SuspendLayout and SendMessage...lines #7 and #8.
0
 
stuengelmanAuthor Commented:
Idle,

I'm having no speed issue on User Control instatntiation and rendering; the sole issue is the disposal speed.  Should I try the layered SuspendLayout and SendMessage within the Reset handler logic that performs the disposal?

Thanks, Stu
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
Ideas are running out.

If you try to add the controls to a brand new form, with nothing else in it, do you still get the problem? If so the problem could be in the UserControl itself.
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
I come back to it.

If the problem is with disposal, and knowing that disposal is not required, why don't you just skip the dispose. It will be done eventually by the Garbage Collector when it will need resources.
0
 
stuengelmanAuthor Commented:
Hi James,

The disposal is required.  The point of the Reset button is to eliminate all the User Controls and refresh them from the database.  The popup itself is not closed on this operation, so the GC does not enter into the issue.

Stu
0
 
stuengelmanAuthor Commented:
Hello guys,

See the code in the code snippet (the handler for the Reset button).  You'll see I turned the background image off.  I tried it as shown, and also with the order of the SendMessage and SuspendLayout strategies nested in reverse.  In both cases, the long flickering occured.

Stu
Me.BackgroundImage = Nothing
SendMessage(Me.Handle, WM_SETREDRAW, False, 0)
Me.SuspendLayout()
For i = 1 To ctlcounter
    Me.Controls("mxrow" & CStr(i)).Dispose()
Next
Me.Controls("btnMXReset").Dispose()
Me.Controls("btnMXClose").Dispose()
SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
Me.ResumeLayout()
Me.PerformLayout()
mdgExpListMgr_Load(Nothing, Nothing)

Open in new window

0
 
stuengelmanAuthor Commented:
James,

Some good news.  Your solution on the other ticket regarding the background image leaving traces of itself as I scroll provided a solution to the "scroll to top" issue in this ticket.  I simply added the line "Me.ScrollControlIntoView(pbExpListBackground)" at the bottom of the Reset button handler, where pbExpListBackground is the PictureBox containing the upper background image.

So all we have left is the flickering issue.

Stu
0
 
stuengelmanAuthor Commented:
Hi James and Idle.  Closing this ticket out and awarding points to both of you.  Idle resolved the dispose issue, and James pointed me to the solution of the "scroll to top" issue.  Will set up a separate ticket for the flickering problem that still remains.  Thanks so much to both of you for your help.  Stu
0

Featured Post

Become an Android App Developer

Ready to kick start your career in 2018? Learn how to build an Android app in January’s Course of the Month and open the door to new opportunities.

  • 23
  • 10
  • 9
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now