Windows Develop Bookmark and Share   
 index > Windows Forms General > Designer Serialization ordering?
 

Designer Serialization ordering?

given the code below; i have 2 collections that are serialized, and in the designer the user is able to click on the tabs etc to adjust properties as well as set the default selected item.

the problem is that the selected item property is being written before the addrange for the collections thus on form initialization, it'strying to seta selected item before the collection items have been added..

this may sound stupid (it's late and i'm tired), but is there a way to control the order of serialization without having to write a custom serializer?

//designer code..

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

public StaticButtonCollection Buttons

{

get { return buttons; }

}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

public CustomTabStripItemCollection Tabs

{

get { return tabs; }

}

[DefaultValue(null)]

[RefreshProperties(RefreshProperties.All)]

[Browsable(true)]

public CustomTabStripItem SelectedItem

{

get { return selectedItem; }

set

{ ...

//consumer code (form)

...

this.customTabStrip1.SelectedItem = this.customTabStripItem1; // offending line

this.customTabStrip1.Size = new System.Drawing.Size(527, 238);

this.customTabStrip1.TabIndex = 0;

this.customTabStrip1.Tabs.AddRange(new CustomControlLibrary.CustomTabStripItem[] {

this.customTabStripItem1,

this.customTabStripItem2}); // this needs to be written before SelectedItem

...

help?

SDKCodeMonkey  Friday, September 14, 2007 6:11 AM

The order in which properties are set is undefined. It might be the order in which reflection returns the properties to the designer or it could be alphabetically. The only ordering guarantee that the designer gives is that all controls will be created before any property values are assigned. Nevertheless this is a common issue.

Enter ISupportInitialize. This interface's sole purpose in life is to allow components to delay initialization until all properties have been set. If a component implements this interface then you'll see a call to BeginInit after the component is created. This is a single to the component that a bunch of properties are about to be set and the component should wait until later to do any work against the properties. When EndInit is called (after all components' properties have been set) then the component can react to the property changes.

To be honest though this interface is really designed for more complex scenarios then the one you describe. In a case like yours the problem is that you are assuming that the selected item is in the list of items. Does it really matter whether it is nor not? All you're likely to do is set an internal field and then perhaps raise an event. However it doesn't make any sense to raise an event while you are initializing.

Most controls (in this situation) will use the HandleCreated property to determine if the control has actually been created yet. Controls aren't technically created (on the Windows side) until after initialization is complete. If HandleCreated is true then you can assume that all initialization is complete and the specified item should be available. If it isn't then just set the internal field. Later when you actually create the control OnHandleCreated you can look at the selected item property and, if set, raise the appropriate event. This is how controls like the treeview work and is a little more efficient then using ISupportInitialize.

public CustomTabStrip SelectedItem
{
get { return m_SelectedItem; }

set
{

if (HandleCreated && (m_SelectedItem != value))
{

//Confirm the item is in the list

m_SelectedItem = value;

//Raise an event
} else

m_SelectedItem = value;

}
}

protected override void OnHandleCreated ( )
{

base.OnHandleCreated();

if (m_SelectedItem != null)

{

//Confirm item in list

//Raise an event

};

}

Michael Taylor - 9/14/07

http://p3net.mvps.org

TaylorMichaelL  Friday, September 14, 2007 11:56 AM
That's what ISupportInitialize was designed to solve. The forms designer automatically calls your EndInit() method after all the properties are assigned. That's the time to do your selection stuff.

public class CustomTabStrip : Something, ISupportInitialize {
private bool mInitializing;
public void BeginInit() {
mInitializing = true;
}
public void EndInit() {
mInitializing = false;
// Do it now
//...
}
}
nobugz  Friday, September 14, 2007 3:05 PM

The order in which properties are set is undefined. It might be the order in which reflection returns the properties to the designer or it could be alphabetically. The only ordering guarantee that the designer gives is that all controls will be created before any property values are assigned. Nevertheless this is a common issue.

Enter ISupportInitialize. This interface's sole purpose in life is to allow components to delay initialization until all properties have been set. If a component implements this interface then you'll see a call to BeginInit after the component is created. This is a single to the component that a bunch of properties are about to be set and the component should wait until later to do any work against the properties. When EndInit is called (after all components' properties have been set) then the component can react to the property changes.

To be honest though this interface is really designed for more complex scenarios then the one you describe. In a case like yours the problem is that you are assuming that the selected item is in the list of items. Does it really matter whether it is nor not? All you're likely to do is set an internal field and then perhaps raise an event. However it doesn't make any sense to raise an event while you are initializing.

Most controls (in this situation) will use the HandleCreated property to determine if the control has actually been created yet. Controls aren't technically created (on the Windows side) until after initialization is complete. If HandleCreated is true then you can assume that all initialization is complete and the specified item should be available. If it isn't then just set the internal field. Later when you actually create the control OnHandleCreated you can look at the selected item property and, if set, raise the appropriate event. This is how controls like the treeview work and is a little more efficient then using ISupportInitialize.

public CustomTabStrip SelectedItem
{
get { return m_SelectedItem; }

set
{

if (HandleCreated && (m_SelectedItem != value))
{

//Confirm the item is in the list

m_SelectedItem = value;

//Raise an event
} else

m_SelectedItem = value;

}
}

protected override void OnHandleCreated ( )
{

base.OnHandleCreated();

if (m_SelectedItem != null)

{

//Confirm item in list

//Raise an event

};

}

Michael Taylor - 9/14/07

http://p3net.mvps.org

TaylorMichaelL  Friday, September 14, 2007 11:56 AM
That's what ISupportInitialize was designed to solve. The forms designer automatically calls your EndInit() method after all the properties are assigned. That's the time to do your selection stuff.

public class CustomTabStrip : Something, ISupportInitialize {
private bool mInitializing;
public void BeginInit() {
mInitializing = true;
}
public void EndInit() {
mInitializing = false;
// Do it now
//...
}
}
nobugz  Friday, September 14, 2007 3:05 PM

thnx fellas Wink

actually in the light of day (morning) it all seems a bit clearer and i got it worked out. thnx for the responses, they pointed me in the right direction.

woot!

SDKCodeMonkey  Friday, September 14, 2007 4:56 PM

You can use google to search for other answers

Custom Search

More Threads

• PrintPreviewDialog
• Beginner Question - SQL Server and Crystal Reports
• Shortcut key for a button
• How to list all users on a network and send a message
• The destination thread no longer exists.
• Changing the background color of a disabled control
• Listbox comparision + removal?
• Custom controls - How should I organise them?
• How can i pass values to a precompiled 3rd party app ?
• Getting / Passing Drag and Drop in Webcontrol