Difficulty saving a collection that references an internal property at design time in Winforms and .net

The easiest way to explain this problem is to show you the code:

Public Interface IAmAnnoyed End Interface Public Class IAmAnnoyedCollection Inherits ObjectModel.Collection(Of IAmAnnoyed) End Class Public Class Anger Implements IAmAnnoyed End Class Public Class MyButton Inherits Button Private _Annoyance As IAmAnnoyedCollection <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _ Public ReadOnly Property Annoyance() As IAmAnnoyedCollection Get Return _Annoyance End Get End Property Private _InternalAnger As Anger <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _ Public ReadOnly Property InternalAnger() As Anger Get Return Me._InternalAnger End Get End Property Public Sub New() Me._Annoyance = New IAmAnnoyedCollection Me._InternalAnger = New Anger Me._Annoyance.Add(Me._InternalAnger) End Sub End Class 

And this is the code that the developer creates:

 Private Sub InitializeComponent() Dim Anger1 As Anger = New Anger Me.MyButton1 = New MyButton ' 'MyButton1 ' Me.MyButton1.Annoyance.Add(Anger1) // Should be: Me.MyButton1.Annoyance.Add(Me.MyButton1.InternalAnger) ' 'Form1 ' Me.Controls.Add(Me.MyButton1) End Sub 

I added a comment to the above to show how the code should have been generated. Now, if I get around the interface and just have the Anger collection, it will be saved correctly.

Any ideas?

Update 1

I am tired of this. This problem was specifically related to saving the collection of interfaces, but now with further testing it does not work for a regular collection. Here is an even simpler code:

 Public Class Anger End Class Public Class MyButton Inherits Button Private _Annoyance As List(Of Anger) <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _ Public ReadOnly Property Annoyance() As List(Of Anger) Get Return _Annoyance End Get End Property Private _InternalAnger As Anger <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _ Public ReadOnly Property InternalAnger() As Anger Get Return Me._InternalAnger End Get End Property Public Sub New() Me._Annoyance = New List(Of Anger) Me._InternalAnger = New Anger Me._Annoyance.Add(Me._InternalAnger) End Sub End Class 

The designer spins the save code in the same way as the original problem.

Update 2

I worked out what was going on. I wondered why sometimes this works and not others. It comes down to the name I give to the home ownership and collection.

If I rename the "Annoyance" property to "WTF", it will serialize correctly, because "WTF" in alphabetical order after the collection name is "InternalAnger".

It appears that the serializer creates instances of objects in alphabetical order and requires that my internal property be created by the time the collection is created.

I can fix this by renaming, but itโ€™s a hack, and Iโ€™m afraid that writing my own serializer is a lot of work that Iโ€™ve never done before.

Any ideas?

Update 3

I answered the question with a hack. I am pretty sure of this if MS does not change the way the designer code serializers are encoded.

+4
source share
4 answers

As I said at OP, the problem boils down to the name that I pass to the internal property and collection.

Without going into your own serializer of encoded code, a simple solution is to make sure that the name of the internal property is in alphabetical order before any other property that will refer to it.

I do this by preserving the original name of the "InternalProperty" property, but I will disable serialization and refer to the proxy property, which is cleverly named and serialized.

 Private _InternalProperty Public ReadOnly Property InternalProperty Get Return Me._ProxyInternalProperty End Get End Property <Browsable(False), EditorBrowsable(Never), DesignerSerializationVisibility(Content)> _ Public ReadOnly Property _ProxyInternalProperty Get Return Me._InternalProperty End Get End Property 

This is a hack, but better than renaming my AInternalProperty property. In addition, the user will never see _ProxyInternalProperty because it is hidden, and even if they find it, there is no danger when linking to it.

0
source

I'm a bit out of my element here, but don't you have a private setter for this readonly property? I mean, he cannot serialize what he cannot install, fix?

0
source

Could the problem be that you add the item to the collection in the constructor of the control, which then serializes the constructor separately?

I think your comment "must be generated" is also incorrect. Since the management constructor adds an InternalAnger to the collection, why would you also want to see it in the InitializeComponent?

0
source

Take DesignerSerializationVisibility.Content using the InternalAnger property, and it should work as you expect.

For example (C #, but the idea is the same)

 public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); this.InternalAnger = new Anger(); this.InternalAnger.SomeValue = 2; this.Angers.Add(this.InternalAnger); } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public List<Anger> Angers { get { return this.list; } } public Anger InternalAnger { get; set; } private List<Anger> list = new List<Anger>(); private Anger _InternalAnger; } public class Anger { public Anger() { } public int SomeValue { get; set; } } 

generates:

 WindowsFormsApplication1.Anger anger1 = new WindowsFormsApplication1.Anger(); anger1.SomeValue = 2; this.userControl11.Angers.Add(anger1); this.userControl11.InternalAnger = anger1; 

which I think you need.

0
source

Source: https://habr.com/ru/post/1303838/


All Articles