base forms and inherited forms

M

moondaddy

I'm writing an app using vb.net 1.1 and want to start making use of a base
form for all my forms. My question is that this base form will have some
common controls (a button for example). The state of this button will be
controlled in the base form (such as enabled and disabled). I don't need to
expose all of its properties to the derived form, but I do need to allow its
location to be changed from the derived form. is there a way to just expose
its location property at design time?

I also have a method in all of my forms called FormState. When called, the
formstate method gets the object state from the business class (where state
can be New-Not-Dirty, New-Dirty-Valid, New-Dirty-NotValid, etc.) and uses it
in a select case block to set the state of many controls on the form such as
menu items, add, close buttons, etc. and I want to move the bulk of this
into the base form. Is there a way in the derived form to call the
FormState method in the base form and pass in a value for this select block
to execute in the base form?

Thanks
 
M

Matt Berther

Hello moondaddy,
I'm writing an app using vb.net 1.1 and want to start making use of a
base form for all my forms. My question is that this base form will
have some common controls (a button for example). The state of this
button will be controlled in the base form (such as enabled and
disabled). I don't need to expose all of its properties to the
derived form, but I do need to allow its location to be changed from
the derived form. is there a way to just expose its location
property at design time?

No... The way to do this is to create a class called ButtonState (for example)
and expose the properties on it.. For example:

class ButtonState
{
private Button button;
public ButtonState(Button button)
{
this.button = button;
}

public bool Enabled
{
get { return button.Enabled; }
set { button.Enabled = value; }
}

// Add any additional properties that youd like to expose in the manner
above
}

class MyBaseForm : System.Windows.Forms.Form
{

private ButtonState okButtonState;

private Button myOkButton;
public MyBaseForm()
{
this.myOkButton = new Button();
this.okButtonState = new ButtonState(myOkButton);
}

public ButtonState OkButtonState
{
get { return okButtonState; }
}
}
I also have a method in all of my forms called FormState. When
called, the formstate method gets the object state from the business
class (where state can be New-Not-Dirty, New-Dirty-Valid,
New-Dirty-NotValid, etc.) and uses it in a select case block to set
the state of many controls on the form such as menu items, add, close
buttons, etc. and I want to move the bulk of this into the base form.
Is there a way in the derived form to call the FormState method in
the base form and pass in a value for this select block to execute in
the base form?

Sure... call MyBase.FormState (VB.NET) or base.FormState (C#)
 
M

moondaddy

OK I figured out part of the solution. In the base form I created a write
only property (baseFormState) and when called, it does all the form state
stuff I waned. For example, in one condition it will disable one button and
enable another.

A related question. I'm not sure exactly what the pattern is, but now that
I have a derived form, sometimes when I open it in design view I get a beep
sound like an error happened, but then when I open it again, it doesn't
beep. It's like something was out of sync with the base form when I
initially opened it, but then the designer fixed it so next time it opened,
all was ok. Does anyone know what's going on here?
 
M

Mike Edenfield

moondaddy said:
I'm writing an app using vb.net 1.1 and want to start making use of a base
form for all my forms. My question is that this base form will have some
common controls (a button for example). The state of this button will be
controlled in the base form (such as enabled and disabled). I don't need to
expose all of its properties to the derived form, but I do need to allow its
location to be changed from the derived form. is there a way to just expose
its location property at design time?

Not directly. You can get the same effect by setting up a protected
property in your form, and in the set {} handler for that property pass
through the value to the button's position. The downside is that you
won't be able to use this as design-time to move the button. For that
you need to just make the button field itself public.
I also have a method in all of my forms called FormState. When called, the
formstate method gets the object state from the business class (where state
can be New-Not-Dirty, New-Dirty-Valid, New-Dirty-NotValid, etc.) and uses it
in a select case block to set the state of many controls on the form such as
menu items, add, close buttons, etc. and I want to move the bulk of this
into the base form. Is there a way in the derived form to call the
FormState method in the base form and pass in a value for this select block
to execute in the base form?

In VB, I beleive you use the MyBase keyword to call the method, as:

Public Overrides Sub FormState(ByVal state As FormStateEmum)
MyBase.FormState(state)
End Sub

--Mike
 
G

Guest

I'm a C# developer so you might need to translate some of my words to VB.

Allowing derived forms to move your control, etc. is very easy. Bring up
your base form in the Visual Studio designer. Change the Modifiers property
to Protected. You can now change the location, size, etc. of the control in
your derived form.

Things to watch out for...
1) You can't move the control to another container on the form. For example
you want to move it from the form to a group box on the form. This probably
won't be a problem.
2) If you hook up an event to the control in your base form and somebody
else hooks up an event on your derived form, then both events will get run.
It's not like when you override a method and get to call its base or not.
3) If your form is Localizable (the form's Localizable property is true),
then really consider not using base forms. Microsoft doesn't seem to support
derived forms very well in a localized world.
4) Some weird stuff goes on with controls inside a container such as a group
box when they are anchored. This only happens in derived forms. Depending on
the difference in the sizes of the base and derived forms, the controls that
are anchored may get wider or narrower every time you open and change the
form.

Good luck! I wish Microsoft would be more excited about the cool stuff you
can do with derived forms, but it doesn't seem to.
 
J

Jeffrey Tan[MSFT]

Hi moondaddy,

I am glad your original problem resolved.

For your further problem about beep sound in inherited form, I can not
reproduce this issue out on my side. I suggest you provide a sample project
as attachment in another reply, then I can reproduce your issue out on my
side and help you better.

========================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
M

moondaddy

Thanks. Here's a zipped copy of the project. Its a small project as I'm
just prototyping things out. Note: make sure that sub main is the startup
object. Perhaps you can advice me on any other issues that you see when you
take a look at this. I'll go ahead and email you the attachment directly
incase it doesn't come through in this posting.

Thanks.

PS: I tried attaching a zip file but it wouldnt post so I emialed it to
you.
 
J

Jeffrey Tan[MSFT]

Hi moondaddy,

Thanks very much for your feedback!

I have received your project, after go through it, I reproduced out your
issue. After doing some research, I found that this problem occurs in
baseFormDE.vb TestBase_Load event. It is caused by the statement below:
Me.BackColor = MyBaseColors.FormBackColor
This "MyBaseColors" class is defined in "Libraries/basGen.vb" file. Then I
looked into this file.

I found that this problem is caused by GetRGBFromString method which is
called in LoadColors method(which is also called in FormBackColor property
in above statement)

Finally, I found that the root cause is that there is an
"NullRerenceException" thrown in GetRGBFromString() method. This is because
the following statement return an empty string:
Dim str As String =
System.Configuration.ConfigurationSettings.AppSettings("AppColors_FormBackCo
lor")
then the empty string is splited and cause the NullRerenceException:
colors = str.Split(",")

Actually, I found that you use ErrLog method to log the exception message
in the ErrorHandler.xml file, if you open this file, you will see a lot of
exception logs. You may place MessageBox.Show(ex.Message) in the exception
handler, then when you open the inherited form, you will see a dialog with
error message:
Private Shared Function GetRGBFromString(ByVal sColor As String) As Color
Try
Dim colors() As String

Dim str As String =
System.Configuration.ConfigurationSettings.AppSettings("AppColors_FormBackCo
lor")
colors = str.Split(",")
'
Dim R As Int32 = colors(0)
Dim G As Int32 = colors(1)
Dim B As Int32 = colors(2)
Dim newColor As Color = Color.FromArgb(R, G, B)
Return newColor
Catch ex As Exception
MessageBox.Show(ex.Message)
ErrLog(ex)
End Try
End Function
==========================================
Cause:
If we run the project, we will find that
System.Configuration.ConfigurationSettings.AppSettings("AppColors_FormBackCo
lor") return the correct string in the app.config, not an empty string. So
the problem only occurs at design-time.

Actually, this is because at design-time, when you inherit from the base
form, the application is at design-time but it is the IDE's runtime, the
code will try to find the config setting in the VS.net IDE process¡¯
(devenv) exe.config not the application's config file, this will fail and
return an empty string.

Solution:
To get rid of the problem, we should disable this code snippet from running
at design-time. We can use Control.DesignMode property to determine if it
is design-time. Just like below:

Private Sub TestBase_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Try
TT.ShowAlways = True
TT.SetToolTip(Me.btnSave, "Alt-S Save")
TT.SetToolTip(Me.btnDelete, "Alt-D Delete")
TT.SetToolTip(Me.btnUnDo, "Alt-U UnDo")
TT.SetToolTip(Me.btnNew, "Alt-N New")
TT.SetToolTip(Me.btnClose, "Alt-C Close")
TT.SetToolTip(Me.btnGoTo, "Alt-G Go To Selected Record")
If Me.DesignMode = False Then
Me.BackColor = MyBaseColors.FormBackColor
End If
Catch ex As Exception
ErrLog(ex)
End Try
End Sub
===========================================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
M

moondaddy

Wow that was awesome that you went all the way through that to find the
issue. An issue with the design environment isn't something I would have
thought of.

It worked great and now I can keep an eye out for similar issues in the
future.

--
(e-mail address removed)
"Jeffrey Tan[MSFT]" said:
Hi moondaddy,

Thanks very much for your feedback!

I have received your project, after go through it, I reproduced out your
issue. After doing some research, I found that this problem occurs in
baseFormDE.vb TestBase_Load event. It is caused by the statement below:
Me.BackColor = MyBaseColors.FormBackColor
This "MyBaseColors" class is defined in "Libraries/basGen.vb" file. Then I
looked into this file.

I found that this problem is caused by GetRGBFromString method which is
called in LoadColors method(which is also called in FormBackColor property
in above statement)

Finally, I found that the root cause is that there is an
"NullRerenceException" thrown in GetRGBFromString() method. This is
because
the following statement return an empty string:
Dim str As String =
System.Configuration.ConfigurationSettings.AppSettings("AppColors_FormBackCo
lor")
then the empty string is splited and cause the NullRerenceException:
colors = str.Split(",")

Actually, I found that you use ErrLog method to log the exception message
in the ErrorHandler.xml file, if you open this file, you will see a lot of
exception logs. You may place MessageBox.Show(ex.Message) in the exception
handler, then when you open the inherited form, you will see a dialog with
error message:
Private Shared Function GetRGBFromString(ByVal sColor As String) As Color
Try
Dim colors() As String

Dim str As String =
System.Configuration.ConfigurationSettings.AppSettings("AppColors_FormBackCo
lor")
colors = str.Split(",")
'
Dim R As Int32 = colors(0)
Dim G As Int32 = colors(1)
Dim B As Int32 = colors(2)
Dim newColor As Color = Color.FromArgb(R, G, B)
Return newColor
Catch ex As Exception
MessageBox.Show(ex.Message)
ErrLog(ex)
End Try
End Function
==========================================
Cause:
If we run the project, we will find that
System.Configuration.ConfigurationSettings.AppSettings("AppColors_FormBackCo
lor") return the correct string in the app.config, not an empty string. So
the problem only occurs at design-time.

Actually, this is because at design-time, when you inherit from the base
form, the application is at design-time but it is the IDE's runtime, the
code will try to find the config setting in the VS.net IDE process¡¯
(devenv) exe.config not the application's config file, this will fail and
return an empty string.

Solution:
To get rid of the problem, we should disable this code snippet from
running
at design-time. We can use Control.DesignMode property to determine if it
is design-time. Just like below:

Private Sub TestBase_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Try
TT.ShowAlways = True
TT.SetToolTip(Me.btnSave, "Alt-S Save")
TT.SetToolTip(Me.btnDelete, "Alt-D Delete")
TT.SetToolTip(Me.btnUnDo, "Alt-U UnDo")
TT.SetToolTip(Me.btnNew, "Alt-N New")
TT.SetToolTip(Me.btnClose, "Alt-C Close")
TT.SetToolTip(Me.btnGoTo, "Alt-G Go To Selected Record")
If Me.DesignMode = False Then
Me.BackColor = MyBaseColors.FormBackColor
End If
Catch ex As Exception
ErrLog(ex)
End Try
End Sub
===========================================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi moondaddy,

I am glad my work can help you :) Anyway, if you need further help, please
feel free to post, I will work with you. Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top