For more on this subject Google Search on VB Initproperties

You may wonder why we need the InitProperties event since the UserControl property already has an Initialize event in common with Class modules and other objects, such as forms.

The reason that we need InitProperties to initialize default values is that the Initialize event happens too often, that is, every time an instance or your control "wakes up." You only want the default property values to be assigned when the developers first sites a new copy of your control on a container. After that, you want the developer to be able to define persistent property values.

WARNING – Don’t Use the Initialize Event to Set an ActiveX Control’s Default Property Values : If you put code to initialize properties to their default values in your custom ActiveX control’s Initialize event instead of in the InitProperties event, then you will have some very frustrated developers on your hands. Your default values will override the values the developer has assigned at design time every time the developer runs an application using your control.

The Property Bag is a persistent UserControl object containing the values of your control’s custom, extender, and delegated properties. In fact, the Property Bag is so persistent that it doesn’t get destroyed with the instances of the UserControl. This means you can store property values in the Property Bag just before an instance of the UserControl is destroyed and then retrieve the stored values when a new instance of the UserControl "wakes up" in another part of the development life cycle.

The Property Bag has two methods to store and retrieve values respectively:

  • The WriteProperty method

  • The ReadProperty method

You must know how to manipulate the Property Bag in the following situations that we discuss in the sections immediately following this one:

  • You store property values into the PropertyBag by calling its WriteProperty method in the WriteProperties event procedure.

  • You retrieve property values from the PropertyBag by calling its ReadProperty method in the ReadProperties event procedure.

  • You ensure that the WriteProperties event will fire by calling the PropertyChanged method. You’ll usually do this in the Property Let procedures of your custom properties or at other appropriate places in your code where the storage value of a property changes.

—-

The operating environment fires a UserControl‘s ReadProperties and WriteProperties events whenever it thinks that the instantiated object’s properties need to be re-initialized (ReadProperties event fires) or stored for safekeeping (WriteProperties event fires).

This arrangement makes it much easier for you, the control author, to manage these properties since you don’t have to think about all the possible occasions when property values might need reading or writing. You simply need to put code for reading and writing property values in two centralized places: the ReadProperties and WriteProperties event procedures.

Both the ReadProperties and WriteProperties event procedures receive a single parameter named PropBag. This PropBag parameter obviously represents the Property Bag object that holds the UserControl‘s property values.

The PropertyBag object represented by the PropBag parameter has one method for reading properties (ReadProperty) and another for writing properties (WriteProperty).

Usually, the only code you need to write in the ReadProperties event procedure will be a series of calls to the ReadProperty method so you can retrieve persistent values for individual properties.

Conversely, the only code you usually need to write in the WriteProperties event procedure will be a series of calls to the WriteProperty method so you can store persistent values of individual properties.

Visual Basic fires the UserControl‘s WriteProperties event just before it fires the UserControl’s Terminate event provided that at least one property value has changed. In other words, the WriteProperties event fires whenever the current instance of the control is about to be destroyed and any property values that you want to persist have changed and, therefore, need to be saved.

As its name implies, you use the WriteProperties event procedure to save persistent property values. The specific mechanism you use to save property values is to call the WriteProperty method of the Property Bag for each property whose value you wish to save. The Property Bag is available in the event procedure of the WriteProperties event as a parameter named PropBag. The example code in Listing 13.7 shows how you would call the Property Bag‘s WriteProperty method to save individual property values. Notice that we use whatever repository has been storing the property value as the source for the current value: at times this might be a private memory variable, and at other times it might be a property of a constituent control (as in the final line before the End Sub).


USING THE WRITEPROPERTIES EVENT PROCEDURE TO SAVE PROPERTY VALUES TO THE PROPERTY BAG

Private Sub UserControl_WriteProperties (PropBag As PropertyBag)          ‘—Store the values of the custom properties to the Property Bag
      PropBag.WriteProperty  "BackColor", BackColor
      PropBag.WriteProperty  "Celsius", m_Celsius
      PropBag.WriteProperty  "Fahrenheit", m_Fahrenheit
      PropBag.WriteProperty  "TemperatureDate", m_TemperatureDate
      PropBag.WriteProperty  "Caption", lblCaption.Caption
End Sub

The system automatically fires the WriteProperties and ReadProperties events whenever it thinks you may need their services. To ensure that the system knows a property has changed, you have to call the PropertyChanged method. An example of this would be when you change the value of a Private variable that implements the value of a property. The system will have no way of knowing that this variable is connected with a property, and therefore it will not fire the WriteProperties event based solely on the change you have made.

In such cases, you can call the PropertyChanged method. This method informs the system that a particular property has changed and so ensures that the WriteProperties event will fire before the current instance of the control is destroyed. If you’ve written the appropriate code in the WriteProperties xvent, then your property values will be stored in the Property Bag.

You should call the UserControl‘s PropertyChanged method whenever you do something in code that will cause a change to a property whose value you wish to persist. The most typical place for you to call the PropertyChanged method would be in a Property Let or Property Set procedure. Note that we check the CanPropertyChange method that we discuss in "Calling the CanPropertyChange Method Before Allowing a Property Value to Change."

CALLING THE PropertyChanged METHOD TO ENSURE THAT WRITEPROPERTIES WILL FIRE

Property Let Celsius(sValue As Single)
   If CanPropertyChange("Celsius") Then                   ‘—assign incoming value to be stores in Private variable
      m_Celsius = sValue     
      PropertyChanged ("Celsius")                                  ‘—invoke UserControl’s PropertyChanged method so it knows to trigger WriteProperties and store new value     
      Slider1.Value = m_Celsius                                      ‘—perform other housekeeping specific to this application
      RecalcFahrenheitFromCelsius sValue
      DisplayTempsFromSlider
   End If
End Property

 

The ReadProperties event fires when a custom control is reinstantiated at some point in the development cycle (the Project where it resides has been retrieved and its container has been instantiated, the developer has just entered run mode from the design mode, or the developer has just returned to design mode from run mode).

Notice that we said that ReadProperties fires when the custom control is re-instantiated. We used this phrasing to purposely exclude the case when the developer places an instance of the control on its container for the first time from the Toolbox. For such first-time instantiation, the ReadProperties event doesn’t fire. Instead, the InitProperties event fires (see "Using the InitProperties Event to Set Default Starting Property Values"). The ReadProperties event, as its name implies, is the event that you will use to restore the values of properties that have been kept in the Property Bag. The Property Bag appears in the ReadProperties event procedure as a parameter named PropBag. You call PropBag’s ReadProperty method for each property whose value you wish to restore.

Notice that the ReadProperty method takes two arguments: the name of the property as a string and then a default value for the property (in case the property’s value has not been initialized in the Property Bag).

We store the results of each call to ReadProperties in the appropriate variable or control property that implements the property within this control.


USING THE READPROPERTIES EVENT PROCEDURE TO RESTORE PERSISTENT PROPERTY VALUES FROM THE PROPERTY BAG

Private Sub UserControl_ReadProperties (PropBag As PropertyBag)
      m_Celsius = PropBag.ReadProperty("Celsius", 30)
      m_TemperatureDate = PropBag.ReadProperty _
      ("TemperatureDate", DateSerial(1997, 1, 1))
      m_caption = PropBag.ReadProperty ("Caption", Extender.Name)
      BackColor = PropBag.ReadProperty  ("BackColor", Ambient.BackColor)      
      lblCaption.Caption = m_caption                                        
End Sub

Categories: CodingVisual-Basic

4 Comments

Jason MonsterID Icon Jason · February 26, 2009 at 6:41 am

I am creating an ActiveX control and for some reason, when I place the control on the form, the WriteProps method (not the ReadProps for the matter) are firing. Would you have any idea why that might be??

I know this isnt a public tech support board, but you seem to have a great understanding of the ActiveX Properties procedures.

Thanks

Jay

—————————————

Dim mLineHeight As Integer
Dim dLineHeight As Integer
Dim mBackgroundColorClicked As OLE_COLOR
Dim dBackgroundColorClicked As OLE_COLOR
Dim mBackgroundColor1 As OLE_COLOR
Dim dBackgroundColor1 As OLE_COLOR
Dim mBackgroundColor2 As OLE_COLOR
Dim dBackgroundColor2 As OLE_COLOR
Dim mBackgroundColorCommercial As OLE_COLOR
Dim dBackgroundColorCommercial As OLE_COLOR
Dim mForeColorResidential As OLE_COLOR
Dim dForeColorResidential As OLE_COLOR
Dim mForeColorClicked As OLE_COLOR
Dim dForeColorClicked As OLE_COLOR
Dim mForeColorCommercial As OLE_COLOR
Dim dForeColorCommercial As OLE_COLOR

Public Property Get LineHeight() As Integer
LineHeight = mLineHeight
End Property
Public Property Let LineHeight(val As Integer)
mLineHeight = val
PropertyChanged (“LineHeight”)
End Property

Public Property Get BackgroundColor1() As OLE_COLOR
BackgroundColor1 = mBackgroundColor1
End Property
Public Property Let BackgroundColor1(val As OLE_COLOR)
mBackgroundColor1 = val
PropertyChanged (“BackgroundColor1”)
End Property

Public Property Get BackgroundColor2() As OLE_COLOR
BackgroundColor2 = mBackgroundColor2
End Property
Public Property Let BackgroundColor2(val As OLE_COLOR)
mBackgroundColor2 = val
PropertyChanged (“BackgroundColor2”)
End Property

Public Property Get BackgroundColorCommercial() As OLE_COLOR
BackgroundColorCommercial = mBackgroundColorCommercial
End Property
Public Property Let BackgroundColorCommercial(val As OLE_COLOR)
mBackgroundColorCommercial = val
PropertyChanged (“BackgroundColorCommercial”)
End Property

Public Property Get BackgroundColorClicked() As OLE_COLOR
BackgroundColorClicked = mBackgroundColorClicked
End Property
Public Property Let BackgroundColorClicked(val As OLE_COLOR)
mBackgroundColorClicked = val
PropertyChanged (“BackgroundColorClicked”)
End Property

Public Property Get ForeColorResidential() As OLE_COLOR
ForeColorResidential = mForeColorResidential
End Property
Public Property Let ForeColorResidential(val As OLE_COLOR)
mForeColorResidential = val
PropertyChanged (“ForeColorResidential”)
End Property

Public Property Get ForeColorCommercial() As OLE_COLOR
ForeColorCommercial = mForeColorCommercial
End Property
Public Property Let ForeColorCommercial(val As OLE_COLOR)
mForeColorCommercial = val
PropertyChanged (“ForeColorCommercial”)
End Property

Public Property Get ForeColorClicked() As OLE_COLOR
ForeColorClicked = mForeColorClicked
End Property
Public Property Let ForeColorClicked(val As OLE_COLOR)
mForeColorClicked = val
PropertyChanged (“ForeColorClicked”)
End Property

Private Sub UserControl_InitProperties()

dLineHeight = 50
dBackgroundColor1 = &HC00000
dBackgroundColor2 = &H800000
dBackgroundColorCommercial = vbBlack
dBackgroundColorClicked = &HC0FFFF
dForeColorResidential = vbWhite
dForeColorCommercial = vbYellow
End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
mLineHeight = PropBag.ReadProperty(“LineHeight”, dLineHeight)
mBackgroundColor1 = PropBag.ReadProperty(“BackgroundColor1”, dBackgroundColor1)
mBackgroundColor2 = PropBag.ReadProperty(“BackgroundColor2”, dBackgroundColor2)
mBackgroundColorCommercial = PropBag.ReadProperty(“BackgroundColorCommercial”, dBackgroundColorCommercial)
mBackgroundColorClicked = PropBag.ReadProperty(“BackgroundColorClicked”, dBackgroundColorClicked)
mForeColorResidential = PropBag.ReadProperty(“ForeColorResidential”, dForeColorResidential)
mForeColorCommercial = PropBag.ReadProperty(“ForeColorCommercial”, dForeColorCommercial)
mForeColorClicked = PropBag.ReadProperty(“ForeColorClicked”, dForeColorClicked)
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
Call PropBag.WriteProperty(“LineHeight”, mLineHeight, dLineHeight)
Call PropBag.WriteProperty(“BackgroundColor1”, mBackgroundColor1, dBackgroundColor1)
Call PropBag.WriteProperty(“BackgroundColor2”, mBackgroundColor2, dBackgroundColor2)
Call PropBag.WriteProperty(“BackgroundColorCommercial”, mBackgroundColorCommercial, dBackgroundColorCommercial)
Call PropBag.WriteProperty(“BackgroundColorClicked”, mBackgroundColorClicked, dBackgroundColorClicked)
Call PropBag.WriteProperty(“ForeColorResidential”, mForeColorResidential, dForeColorResidential)
Call PropBag.WriteProperty(“ForeColorCommercial”, mForeColorCommercial, dForeColorCommercial)
Call PropBag.WriteProperty(“ForeColorClicked”, mForeColorClicked, dForeColorClicked)
End Sub

Freemon SandleWould MonsterID Icon Freemon SandleWould · February 26, 2009 at 9:46 am

Is this Visual Basic 6.0 or VisualBasic.Net ? I used VB6 tool. I can tell you with that that it does not write properties or retain properties. I had to write properties to a propertybag and retrieve them when appropriate to set properties I wanted to be persistant. If you are using VB.net you may want to check to see if the same applies to it.

I think its absolutely quackers that Microsoft did build in the ability to retain property / parameter settings of objects you create in VB6 but sure enough they did not! Its very inconvenient.

Jason MonsterID Icon Jason · February 26, 2009 at 3:00 pm

Hey, thanks for the reply! It is VB6 code. The settings are being maintained properly but what is happening is that when a new instance of the control is placed on a form, none of the default settings are being applied. (colors are all black, strings are all empty, numbers are all zero)..

It’s the weirdest thing….

Freemon SandleWould MonsterID Icon Freemon SandleWould · February 26, 2009 at 7:41 pm

I wrestled with the same general problem. I do not remember exact details now enough to argue much with you. However I can remember the solution. The solution was property bags for every property that I created for the control. Pretty awkward huh? Considering in a normal control you can set a property at design time and it just takes. No fussing around. You would think it would just default to this type of behavior. The only explanation I could come up with is that Microsoft wanted to release without waiting for this to be made right.

Any idea how VB.net is? I would think ( and HOPE!) that they would make user designed controls just act like a built in supplied by MS control. Or in other words….add apple sac by default and transparently from the coders perspective! ( property bag that is )

If I remember correctly there are some settings that seem to take but upon exiting the development system and restarting I could not get them to be recalled. Have you made sure to check in regards this scenario?

Leave a Reply

Your email address will not be published. Required fields are marked *