design time property persistence

J

Jiho Han

I have a control that inherits from WebControl.
In it, I have a property of a collection type. Basically it's similar to
how DataGrid works in design-time.
See the code below. Basically, when I add a DataGridColumn through the
collection editor in the designer, the correct tags are persisted inside my
control as I can see them when I switch to the HTML view. However, the
opposite is not true - when I add the tags manually in the HTML view and
switch to the design view, the control reports error "Columns could not be
initialized"?

<custom:DataGrid>
<Columns>
<custom:DataGridColumn></custom:DataGridColumn>
</Columns>
</custom:/DataGrid>
(the above generates an error if edited in the HTML view)

Anyone know what's going on? Am I missing some attributes somewhere?

// ParseChildren(true) defined in WebControl
public class DataGrid : WebControl, INamingContainer
{
private DataGridColumnCollection _columns;
...

[
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty)
]
public DataGridColumnCollection Columns
{
get
{
if (_columns == null)
return _columns = new DataGridColumnCollection();
return _columns;
}
}
}

public class DataGridColumnCollection : CollectionBase
{
public DataGridColumn this[int index]
{
get
{
return (DataGridColumn) List[index];
}
}
}

public class DataGridColumn
{
public DataGridColumn()
{
}
}
 
T

Teemu Keiski

Hi,

is this just a typo but your opening tag for the grid is:

<custom:DataGrid>

And the end tag is:

</custom:/DataGrid>

I.e they do not match.('/' before the D in the end tag)
 
J

Jiho Han

Yes, it is a typo. There isn't supposed to be that second / in there.

This whole thing is kind of tricky to me. What are the things that
affect design-time persistence/parsing anyway?

ParseChildren attribute is for the asp.net to parse the tags I enter
manually right? And PersistChildren and PersistenceMode is for the
already parsed object or the objects modified through property
builders to be written out in HTML? For my needs,
DesignSerializationVisibility should be Content I think.
Am I missing anything else?

I have another control that is almost the same in behavior but it's
configured for InnerDefaultProperty persistence and somewhat works
both ways. There are a lot of examples out there that deals with
InnerProperty persistence with things like Templates, etc. But none
exists that deals with having a collection property that is not a
default property. For example, out-of-the-box DataGrid contains
Columns, ItemStyle, HeaderStyle, etc. properties and you can specify
them all under <asp:DataGrid> tag. That means Columns - which is a
collection - cannot be a default property as far as ParseChildren is
concerned. In fact, I'm sure Columns is just set to
PersistenceMode.InnerProperty not InnerDefaultProperty.

Kothari's book is great but I wish there were a more detailed
explanation for how the design time environment works out there
somewhere, as I think that's where it falls a little short although
it's one of the only books that's useful out there.

Anyway, I'd appreciate any help you can provide.
Thanks much!

Jiho

Teemu Keiski said:
Hi,

is this just a typo but your opening tag for the grid is:

<custom:DataGrid>

And the end tag is:

</custom:/DataGrid>

I.e they do not match.('/' before the D in the end tag)


--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist


Jiho Han said:
I have a control that inherits from WebControl.
In it, I have a property of a collection type. Basically it's similar to
how DataGrid works in design-time.
See the code below. Basically, when I add a DataGridColumn through the
collection editor in the designer, the correct tags are persisted inside
my
control as I can see them when I switch to the HTML view. However, the
opposite is not true - when I add the tags manually in the HTML view and
switch to the design view, the control reports error "Columns could not be
initialized"?

<custom:DataGrid>
<Columns>
<custom:DataGridColumn></custom:DataGridColumn>
</Columns>
</custom:/DataGrid>
(the above generates an error if edited in the HTML view)

Anyone know what's going on? Am I missing some attributes somewhere?

// ParseChildren(true) defined in WebControl
public class DataGrid : WebControl, INamingContainer
{
private DataGridColumnCollection _columns;
...

[
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty)
]
public DataGridColumnCollection Columns
{
get
{
if (_columns == null)
return _columns = new DataGridColumnCollection();
return _columns;
}
}
}

public class DataGridColumnCollection : CollectionBase
{
public DataGridColumn this[int index]
{
get
{
return (DataGridColumn) List[index];
}
}
}

public class DataGridColumn
{
public DataGridColumn()
{
}
}
 
T

Teemu Keiski

Yes,

you should have
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
attribute applied. And yes it is specified with
PersistenceMode.InnerProperty.

Also in your code you have DataGridColumn but are you inheriting from the
built-in DataGridColumn?

--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Jiho Han said:
Yes, it is a typo. There isn't supposed to be that second / in there.

This whole thing is kind of tricky to me. What are the things that
affect design-time persistence/parsing anyway?

ParseChildren attribute is for the asp.net to parse the tags I enter
manually right? And PersistChildren and PersistenceMode is for the
already parsed object or the objects modified through property
builders to be written out in HTML? For my needs,
DesignSerializationVisibility should be Content I think.
Am I missing anything else?

I have another control that is almost the same in behavior but it's
configured for InnerDefaultProperty persistence and somewhat works
both ways. There are a lot of examples out there that deals with
InnerProperty persistence with things like Templates, etc. But none
exists that deals with having a collection property that is not a
default property. For example, out-of-the-box DataGrid contains
Columns, ItemStyle, HeaderStyle, etc. properties and you can specify
them all under <asp:DataGrid> tag. That means Columns - which is a
collection - cannot be a default property as far as ParseChildren is
concerned. In fact, I'm sure Columns is just set to
PersistenceMode.InnerProperty not InnerDefaultProperty.

Kothari's book is great but I wish there were a more detailed
explanation for how the design time environment works out there
somewhere, as I think that's where it falls a little short although
it's one of the only books that's useful out there.

Anyway, I'd appreciate any help you can provide.
Thanks much!

Jiho

Teemu Keiski said:
Hi,

is this just a typo but your opening tag for the grid is:

<custom:DataGrid>

And the end tag is:

</custom:/DataGrid>

I.e they do not match.('/' before the D in the end tag)


--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist


Jiho Han said:
I have a control that inherits from WebControl.
In it, I have a property of a collection type. Basically it's similar
to
how DataGrid works in design-time.
See the code below. Basically, when I add a DataGridColumn through the
collection editor in the designer, the correct tags are persisted
inside
my
control as I can see them when I switch to the HTML view. However, the
opposite is not true - when I add the tags manually in the HTML view
and
switch to the design view, the control reports error "Columns could not
be
initialized"?

<custom:DataGrid>
<Columns>
<custom:DataGridColumn></custom:DataGridColumn>
</Columns>
</custom:/DataGrid>
(the above generates an error if edited in the HTML view)

Anyone know what's going on? Am I missing some attributes somewhere?

// ParseChildren(true) defined in WebControl
public class DataGrid : WebControl, INamingContainer
{
private DataGridColumnCollection _columns;
...

[
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty)
]
public DataGridColumnCollection Columns
{
get
{
if (_columns == null)
return _columns = new DataGridColumnCollection();
return _columns;
}
}
}

public class DataGridColumnCollection : CollectionBase
{
public DataGridColumn this[int index]
{
get
{
return (DataGridColumn) List[index];
}
}
}

public class DataGridColumn
{
public DataGridColumn()
{
}
}
 
J

Jiho Han

Well, all that blah for nothing. It turns out that all it is was that
I had no public add method in my custom collection class. I just
extended the CollectionBase class and only had indexer defined and no
other public methods. Better error message other than 'Could not
initialize' would have been nice though. Now my question is then why
does it work through the collection editor(UI), adding and persisting
fine but not the other way around as in when parsing from modified
HTML? Does the collection editor use different mechanism to add items
to the collection?

I do have one other fine detail left to iron out. Although the
parsing and the persisting works, the collection editor, when adding
an item, adds each item using the full name of the class. In other
examples I have don't do that. They only add as the class name and
not the full name including namespace and all. I don't think this is
really affecting the normal design process but it's sure annoying and
since I'm so nitpicky about these things, it bothers me a lot. What
could be causing this?

Thanks Teemu for your responses. Just the fact that someone is
responding to my messages is giving me the strength to go on!

Teemu Keiski said:
Yes,

you should have
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
attribute applied. And yes it is specified with
PersistenceMode.InnerProperty.

Also in your code you have DataGridColumn but are you inheriting from the
built-in DataGridColumn?

--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Jiho Han said:
Yes, it is a typo. There isn't supposed to be that second / in there.

This whole thing is kind of tricky to me. What are the things that
affect design-time persistence/parsing anyway?

ParseChildren attribute is for the asp.net to parse the tags I enter
manually right? And PersistChildren and PersistenceMode is for the
already parsed object or the objects modified through property
builders to be written out in HTML? For my needs,
DesignSerializationVisibility should be Content I think.
Am I missing anything else?

I have another control that is almost the same in behavior but it's
configured for InnerDefaultProperty persistence and somewhat works
both ways. There are a lot of examples out there that deals with
InnerProperty persistence with things like Templates, etc. But none
exists that deals with having a collection property that is not a
default property. For example, out-of-the-box DataGrid contains
Columns, ItemStyle, HeaderStyle, etc. properties and you can specify
them all under <asp:DataGrid> tag. That means Columns - which is a
collection - cannot be a default property as far as ParseChildren is
concerned. In fact, I'm sure Columns is just set to
PersistenceMode.InnerProperty not InnerDefaultProperty.

Kothari's book is great but I wish there were a more detailed
explanation for how the design time environment works out there
somewhere, as I think that's where it falls a little short although
it's one of the only books that's useful out there.

Anyway, I'd appreciate any help you can provide.
Thanks much!

Jiho

Teemu Keiski said:
Hi,

is this just a typo but your opening tag for the grid is:

<custom:DataGrid>

And the end tag is:

</custom:/DataGrid>

I.e they do not match.('/' before the D in the end tag)


--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist


I have a control that inherits from WebControl.
In it, I have a property of a collection type. Basically it's similar
to
how DataGrid works in design-time.
See the code below. Basically, when I add a DataGridColumn through the
collection editor in the designer, the correct tags are persisted
inside
my
control as I can see them when I switch to the HTML view. However, the
opposite is not true - when I add the tags manually in the HTML view
and
switch to the design view, the control reports error "Columns could not
be
initialized"?

<custom:DataGrid>
<Columns>
<custom:DataGridColumn></custom:DataGridColumn>
</Columns>
</custom:/DataGrid>
(the above generates an error if edited in the HTML view)

Anyone know what's going on? Am I missing some attributes somewhere?

// ParseChildren(true) defined in WebControl
public class DataGrid : WebControl, INamingContainer
{
private DataGridColumnCollection _columns;
...

[
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty)
]
public DataGridColumnCollection Columns
{
get
{
if (_columns == null)
return _columns = new DataGridColumnCollection();
return _columns;
}
}
}

public class DataGridColumnCollection : CollectionBase
{
public DataGridColumn this[int index]
{
get
{
return (DataGridColumn) List[index];
}
}
}

public class DataGridColumn
{
public DataGridColumn()
{
}
}
 
T

Teemu Keiski

That is indeed hard to track.Good that you got it solved.

When you use collection editor and add the items it uses the getter of your
property for sure (that manages the instantiation of the collection). I am
not sure how it works when you switch from HTML to design view, perhaps it
tries to access the DataGridColumnCollection via reflection or something and
therefore doesn't work (might want custom typeconverter as well) . By the
way, DataGrid provides the collection editor in its Columns property (not in
the DataGridColumnCollectuon type), so do you use the built-in editor or do
you have your own, custom one?

Post some code, it gets hard to guess that persisting behavior otherwise.

--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist




Jiho Han said:
Well, all that blah for nothing. It turns out that all it is was that
I had no public add method in my custom collection class. I just
extended the CollectionBase class and only had indexer defined and no
other public methods. Better error message other than 'Could not
initialize' would have been nice though. Now my question is then why
does it work through the collection editor(UI), adding and persisting
fine but not the other way around as in when parsing from modified
HTML? Does the collection editor use different mechanism to add items
to the collection?

I do have one other fine detail left to iron out. Although the
parsing and the persisting works, the collection editor, when adding
an item, adds each item using the full name of the class. In other
examples I have don't do that. They only add as the class name and
not the full name including namespace and all. I don't think this is
really affecting the normal design process but it's sure annoying and
since I'm so nitpicky about these things, it bothers me a lot. What
could be causing this?

Thanks Teemu for your responses. Just the fact that someone is
responding to my messages is giving me the strength to go on!

Teemu Keiski said:
Yes,

you should have
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
attribute applied. And yes it is specified with
PersistenceMode.InnerProperty.

Also in your code you have DataGridColumn but are you inheriting from the
built-in DataGridColumn?

--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Jiho Han said:
Yes, it is a typo. There isn't supposed to be that second / in there.

This whole thing is kind of tricky to me. What are the things that
affect design-time persistence/parsing anyway?

ParseChildren attribute is for the asp.net to parse the tags I enter
manually right? And PersistChildren and PersistenceMode is for the
already parsed object or the objects modified through property
builders to be written out in HTML? For my needs,
DesignSerializationVisibility should be Content I think.
Am I missing anything else?

I have another control that is almost the same in behavior but it's
configured for InnerDefaultProperty persistence and somewhat works
both ways. There are a lot of examples out there that deals with
InnerProperty persistence with things like Templates, etc. But none
exists that deals with having a collection property that is not a
default property. For example, out-of-the-box DataGrid contains
Columns, ItemStyle, HeaderStyle, etc. properties and you can specify
them all under <asp:DataGrid> tag. That means Columns - which is a
collection - cannot be a default property as far as ParseChildren is
concerned. In fact, I'm sure Columns is just set to
PersistenceMode.InnerProperty not InnerDefaultProperty.

Kothari's book is great but I wish there were a more detailed
explanation for how the design time environment works out there
somewhere, as I think that's where it falls a little short although
it's one of the only books that's useful out there.

Anyway, I'd appreciate any help you can provide.
Thanks much!

Jiho

Hi,

is this just a typo but your opening tag for the grid is:

<custom:DataGrid>

And the end tag is:

</custom:/DataGrid>

I.e they do not match.('/' before the D in the end tag)


--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist


I have a control that inherits from WebControl.
In it, I have a property of a collection type. Basically it's
similar
to
how DataGrid works in design-time.
See the code below. Basically, when I add a DataGridColumn through
the
collection editor in the designer, the correct tags are persisted
inside
my
control as I can see them when I switch to the HTML view. However,
the
opposite is not true - when I add the tags manually in the HTML view
and
switch to the design view, the control reports error "Columns could
not
be
initialized"?

<custom:DataGrid>
<Columns>
<custom:DataGridColumn></custom:DataGridColumn>
</Columns>
</custom:/DataGrid>
(the above generates an error if edited in the HTML view)

Anyone know what's going on? Am I missing some attributes
somewhere?

// ParseChildren(true) defined in WebControl
public class DataGrid : WebControl, INamingContainer
{
private DataGridColumnCollection _columns;
...

[
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty)
]
public DataGridColumnCollection Columns
{
get
{
if (_columns == null)
return _columns = new DataGridColumnCollection();
return _columns;
}
}
}

public class DataGridColumnCollection : CollectionBase
{
public DataGridColumn this[int index]
{
get
{
return (DataGridColumn) List[index];
}
}
}

public class DataGridColumn
{
public DataGridColumn()
{
}
}
 
J

Jiho Han

@#$%! All I needed to do for my class name to appear in the collection
editor instead of the full package + class name is to override ToString() in
the collection item class. For example, in my DataGridColumn I defined:

public override string ToString()
{
return GetType().Name;
}

I guess if you don't define it, the Object.ToString() is called and maybe
that returns the type's full name.
I think the collection editor instead of relying on ToString(), should maybe
invoke Type.Name explicitly. Maybe I don't want to return the short name
from my ToString(). I guess all this could be avoided if I implemented my
own collection editor.

That sucked.
Thanks though Teemu.

Teemu Keiski said:
That is indeed hard to track.Good that you got it solved.

When you use collection editor and add the items it uses the getter of your
property for sure (that manages the instantiation of the collection). I am
not sure how it works when you switch from HTML to design view, perhaps it
tries to access the DataGridColumnCollection via reflection or something and
therefore doesn't work (might want custom typeconverter as well) . By the
way, DataGrid provides the collection editor in its Columns property (not in
the DataGridColumnCollectuon type), so do you use the built-in editor or do
you have your own, custom one?

Post some code, it gets hard to guess that persisting behavior otherwise.

--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist




Jiho Han said:
Well, all that blah for nothing. It turns out that all it is was that
I had no public add method in my custom collection class. I just
extended the CollectionBase class and only had indexer defined and no
other public methods. Better error message other than 'Could not
initialize' would have been nice though. Now my question is then why
does it work through the collection editor(UI), adding and persisting
fine but not the other way around as in when parsing from modified
HTML? Does the collection editor use different mechanism to add items
to the collection?

I do have one other fine detail left to iron out. Although the
parsing and the persisting works, the collection editor, when adding
an item, adds each item using the full name of the class. In other
examples I have don't do that. They only add as the class name and
not the full name including namespace and all. I don't think this is
really affecting the normal design process but it's sure annoying and
since I'm so nitpicky about these things, it bothers me a lot. What
could be causing this?

Thanks Teemu for your responses. Just the fact that someone is
responding to my messages is giving me the strength to go on!

Teemu Keiski said:
Yes,

you should have
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
attribute applied. And yes it is specified with
PersistenceMode.InnerProperty.

Also in your code you have DataGridColumn but are you inheriting from the
built-in DataGridColumn?

--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Yes, it is a typo. There isn't supposed to be that second / in there.

This whole thing is kind of tricky to me. What are the things that
affect design-time persistence/parsing anyway?

ParseChildren attribute is for the asp.net to parse the tags I enter
manually right? And PersistChildren and PersistenceMode is for the
already parsed object or the objects modified through property
builders to be written out in HTML? For my needs,
DesignSerializationVisibility should be Content I think.
Am I missing anything else?

I have another control that is almost the same in behavior but it's
configured for InnerDefaultProperty persistence and somewhat works
both ways. There are a lot of examples out there that deals with
InnerProperty persistence with things like Templates, etc. But none
exists that deals with having a collection property that is not a
default property. For example, out-of-the-box DataGrid contains
Columns, ItemStyle, HeaderStyle, etc. properties and you can specify
them all under <asp:DataGrid> tag. That means Columns - which is a
collection - cannot be a default property as far as ParseChildren is
concerned. In fact, I'm sure Columns is just set to
PersistenceMode.InnerProperty not InnerDefaultProperty.

Kothari's book is great but I wish there were a more detailed
explanation for how the design time environment works out there
somewhere, as I think that's where it falls a little short although
it's one of the only books that's useful out there.

Anyway, I'd appreciate any help you can provide.
Thanks much!

Jiho

Hi,

is this just a typo but your opening tag for the grid is:

<custom:DataGrid>

And the end tag is:

</custom:/DataGrid>

I.e they do not match.('/' before the D in the end tag)


--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist


I have a control that inherits from WebControl.
In it, I have a property of a collection type. Basically it's
similar
to
how DataGrid works in design-time.
See the code below. Basically, when I add a DataGridColumn through
the
collection editor in the designer, the correct tags are persisted
inside
my
control as I can see them when I switch to the HTML view. However,
the
opposite is not true - when I add the tags manually in the HTML view
and
switch to the design view, the control reports error "Columns could
not
be
initialized"?

<custom:DataGrid>
<Columns>
<custom:DataGridColumn></custom:DataGridColumn>
</Columns>
</custom:/DataGrid>
(the above generates an error if edited in the HTML view)

Anyone know what's going on? Am I missing some attributes
somewhere?

// ParseChildren(true) defined in WebControl
public class DataGrid : WebControl, INamingContainer
{
private DataGridColumnCollection _columns;
...

[
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty)
]
public DataGridColumnCollection Columns
{
get
{
if (_columns == null)
return _columns = new DataGridColumnCollection();
return _columns;
}
}
}

public class DataGridColumnCollection : CollectionBase
{
public DataGridColumn this[int index]
{
get
{
return (DataGridColumn) List[index];
}
}
}

public class DataGridColumn
{
public DataGridColumn()
{
}
}
 

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

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top