There is actually a (subtle) difference between the two. Imagine you have the following code in File1.cs:
// File1.cs
using System;
namespace Outer.Inner
{
class Foo
{
static void Bar()
{
double d = Math.PI;
}
}
}
Now imagine that someone adds another file (File2.cs) to the project that looks like this:
// File2.cs
namespace Outer
{
class Math
{
}
}
The compiler searches Outer
before looking at those using
directives outside the namespace, so it finds Outer.Math
instead of System.Math
. Unfortunately (or perhaps fortunately?), Outer.Math
has no PI
member, so File1 is now broken.
This changes if you put the using
inside your namespace declaration, as follows:
// File1b.cs
namespace Outer.Inner
{
using System;
class Foo
{
static void Bar()
{
double d = Math.PI;
}
}
}
Now the compiler searches System
before searching Outer
, finds System.Math
, and all is well.
Some would argue that Math
might be a bad name for a user-defined class, since there's already one in System
; the point here is just that there is a difference, and it affects the maintainability of your code.
It's also interesting to note what happens if Foo
is in namespace Outer
, rather than Outer.Inner
. In that case, adding Outer.Math
in File2 breaks File1 regardless of where the using
goes. This implies that the compiler searches the innermost enclosing namespace before it looks at any using
directive.
The conversion you have done of the original C# code is not perfect (you should understand what each part does, instead of copying bit by bit). In the SetVisible
/SetInvisible
part this is the problem:
Public Shared Function SetInvisible(page As TabPage, frm As Form) 'As Boolean
page = frm.Controls(page.Name)
If IsVisible(page) Then
Dim tabCtrl As TabControl = DirectCast(page.Parent, TabControl)
Dim tpinfo As TabPageData
tpinfo = New TabPageData(tabCtrl.TabPages.IndexOf(page), tabCtrl, page)
tabCtrl.TabPages.Remove(page)
hiddenPages.Add(TabPageData.GetKey(tabCtrl, page), tpinfo)
End If
End Function
(this should be a Sub
rather than a Function
) You are adding a bit not present in the original code: page = frm.Controls(page.Name)
; I guess that it is an adaptation to make the code work under your specific conditions (you have added to the form a TabPage
alone, instead one inside a TabControl
, what is the normal behaviour). This would be fine, but you are not adapting the SetVisible function to this reality:
Public Shared Sub SetVisible(page As TabPage, parent As TabControl)
If parent IsNot Nothing AndAlso Not parent.IsDisposed Then
Dim tpinfo As TabPageData
Dim key As String = TabPageData.GetKey(parent, page)
If hiddenPages.ContainsKey(key) Then
tpinfo = hiddenPages(key)
If tpinfo.Index < parent.TabPages.Count Then
parent.TabPages.Insert(tpinfo.Index, tpinfo.Page)
Else
' add the page in the same position it had
parent.TabPages.Add(tpinfo.Page)
End If
hiddenPages.Remove(key)
Else
PrintAllKeys()
End If
End If
End Sub
Understand what both functions do: the first one (modified by you) expects a TabPage added to the form directly (thus with no parent TabControl); the second one (as in the original C# code) expects a TabPage with a parent TabControl but your input does not have that. How I know that? If your TabPage would have a TabControl as a parent, the page = frm.Controls(page.Name)
would be Nothing
.
If you want to use this code you have to provide the expected inputs, that is, TabPages inside a TabControl. Otherwise, you should modify it accordingly (not just one part, all the parts). Easy test for you to understand what is required:
1- Open a new project and add a new TabControl via "Design View".
2- Copy your class but let SetInvisible as in the original version (delete page = frm.Controls(page.Name)
).
3- Test your class with the main form and see that it works fine. Sample code (these are the default names when you add a new TabControl
):
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim test As clsTabManager = New clsTabManager()
test.SetInvisible(TabPage1, Me)
test.SetVisible(TabPage1, TabControl1)
End Sub
Best Answer
You can turn a Form class back to a child control by setting its TopLevel property to False. It becomes essentially a UserControl with some unused overhead. Make it look similar to this: