How can I be certain that my rescued project has no residual corruption?

chris_asa

Active member
Joined
Sep 4, 2009
Messages
26
Location
Switzerland
Programming Experience
10+
I have a VS2008 VB Winforms project that is showing signs of corruption.

Opening one particular form ExampleForm in design view immediately shows ExampleForm* as though it had been edited.

ExampleForm includes Panel1 that holds six usercontrols.
I get "must not be null" warnings pointing to a line in ExampleForm.designer.vb that refers to Panel1
Sometimes all my usercontrols disappear from VS (not in the tools ...and obviously accompanied by many error messages).
Clean/Rebuild/Build all report "success", but sometimes Build does NOT reflect changes even though it reports "success".

The edits that were going on at the time the issue arose were with one of the six usercontrols: I changed ">" (U+003C) to "≥" (U+2265) both designtime (default text for a Label), and runtime (code to toggle < > changed to ≤ ≥ and other code checks ≤ or ≥ to set cmd.parameter correctly).

I have been able to copy all the controls/code from ExampleForm to RescueForm (RescueForm does not show the * issue) and that's where I am at the moment.

So now to the questions:

Could my unicode-code cause the corruption? (If SomeLabel.Text = "≥" Then ...etc)

I have RescueForm that seems to be OK
-- suggesting to me that ExampleForm.designer.vb is corrupt
-- suggesting the simple fix of deleting ExampleForm and adding a new ExampleForm and copy/pasting from RescueForm back to the new ExampleForm
Is this realistic?
How can I "know" that the resulting project is free from corruption?

My concern is that the project might show no symptoms and appear to be fixed, we continue to hammer in additional code, and a month down the road the old corruption rears it's ugly head again.

The same concern exists for the backups - I can restore to any point in time with worst-case two-hour granularity, but how do I **KNOW** I went back far enough to get an uncorrupted version?

Chris
 
Could my unicode-code cause the corruption?
If the source files including unicode chars aren't saved as unicode then yes, there could be corruption. Check the current encoding used for saving (File > Save ...vb As > click Save button dropdown), default for both project file and code files are Utf-8.

Also close the project and use Windows Explorer to delete the generated Bin and Obj folders, to make sure there aren't leftovers here that have been corrupted and locked up.
 
Thanks John.

The souce was saved as unicode.

I ended up recreating (copy/paste controls/code to dummy, delete, new, copy/paste from dummy) both ≤≥ usercontrol and ExampleForm (deleting bin/obj before each step and again at the end).

The project seems to be well again.
...I wish I had some way of "proving" that it is really OK.

Chris
 
:D and :(
I can reproduce the problem!

I have the following code in my usercontrol:
VB.NET:
        '// setup the Status combo from dictStatus

        '// this commented stuff causes the problem
        'cboStatus.DataSource = New BindingSource(dictStatus, Nothing)
        'cboStatus.DisplayMember = "Key"       'the String
        'cboStatus.ValueMember = "Value"       'the Byte

        '// this uncommented stuff is fine
        With Me.cboStatus
            .BeginUpdate()
            For Each x In dictStatus.Keys
                .Items.Add(x)
            Next
            .EndUpdate()
        End With
Swapping commented for uncomented kills the form holding the usercontrol holding this combo. Unswapping makes everything well again.

dictStatus is a Public Dictionary(Of String, Byte) populated with around 15 pairs.

I use **identical** code elsewhere in this application (regular forms, not user-controls) and it works without issue and provides a simple way to interact with the combo/dictionary:
VB.NET:
SomeString = Me.cboStatus.Text
SomeByte = Me.cboStatus.SelectedValue
Me.cboStatus.Text = SomeText
Me.cboStatus.SelectedValue = SomeByte

Why is this stuff not working when combo is in usercontrol?
Why does it kill the parent form but not the usercontrol?

:confused:

Chris
 
I don't see how that would affect anything, it also doesn't generate any related code in consumer project. Generally though, you should always set the 'Member' properties before assigning the datasource. I actually went to the length of creating a project in VB 2008 with a usercontrol and a combobox set up like that, and it didn't have any adverse effect that I could see.
 
OK, so it's me, I'm doing something wrong.
Here's how to reproduce my idiocy:

VB.NET:
Module Module1
    Public dictTest As New Dictionary(Of String, Byte)
End Module


Public Class UserControl1
    'UserControl1 contains comboUC, nothing else
    Private Sub UserControl1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ComboUC.DataSource = New BindingSource(dictTest, Nothing)
        ComboUC.DisplayMember = "Key"       'the String
        ComboUC.ValueMember = "Value"       'the Byte
    End Sub
End Class


Public Class Form1
    'Form1 contains Panel1 that contains UserControl1
    'it also has a similar combo on the form itself: comboForm
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        '// feed comboForm
        cboForm.DataSource = New BindingSource(dictTest, Nothing)
        cboForm.DisplayMember = "Key"       'the String
        cboForm.ValueMember = "Value"       'the Byte
    End Sub
End Class

Public NotInheritable Class SplashScreen1

    'TODO: This form can easily be set as the splash screen for the application by going to the "Application" tab
    '  of the Project Designer ("Properties" under the "Project" menu).


    Private Sub SplashScreen1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Set up the dialog text at runtime according to the application's assembly information.  

        'TODO: Customize the application's assembly information in the "Application" pane of the project 
        '  properties dialog (under the "Project" menu).

        'Application title
        If My.Application.Info.Title <> "" Then
            ApplicationTitle.Text = My.Application.Info.Title
        Else
            'If the application title is missing, use the application name, without the extension
            ApplicationTitle.Text = System.IO.Path.GetFileNameWithoutExtension(My.Application.Info.AssemblyName)
        End If

        'Format the version information using the text set into the Version control at design time as the
        '  formatting string.  This allows for effective localization if desired.
        '  Build and revision information could be included by using the following code and changing the 
        '  Version control's designtime text to "Version {0}.{1:00}.{2}.{3}" or something similar.  See
        '  String.Format() in Help for more information.
        '
        '    Version.Text = System.String.Format(Version.Text, My.Application.Info.Version.Major, My.Application.Info.Version.Minor, My.Application.Info.Version.Build, My.Application.Info.Version.Revision)

        Version.Text = System.String.Format(Version.Text, My.Application.Info.Version.Major, My.Application.Info.Version.Minor)

        'Copyright info
        Copyright.Text = My.Application.Info.Copyright

        ''//fake filling Public dictTest As New Dictionary(Of String, Byte)
        With dictTest
            .Add("Great", 220)
            .Add("Good", 200)
            .Add("Average", 180)
            .Add("Poor", 160)
            .Add("Awful", 140)
        End With
    End Sub

End Class

...it Cleans, Rebuilds, Builds, Runs!
Opening Form1 designview fails with:
VB.NET:
1 Warning:
Value cannot be null
Line 76
Form1.Designer.vb


70        'Form1
71        '
72        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
73        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
74        Me.ClientSize = New System.Drawing.Size(539, 264)
75        Me.Controls.Add(Me.Panel1)
[COLOR="red"]76        Me.Controls.Add(Me.cboForm)[/COLOR]
77        Me.Name = "Form1"
78        Me.Text = "Form1"
79        Me.Panel1.ResumeLayout(False)
80        Me.Panel1.PerformLayout()
81        Me.ResumeLayout(False)


at System.RuntimeType.MakeGenericType(Type[] instantiation)
at System.Windows.Forms.BindingSource.CreateBindingList(Type type)
at System.Windows.Forms.BindingSource.SetList(IList list, Boolean metaDataChanged, Boolean applySortAndFilter)
at System.Windows.Forms.BindingSource.ResetList()
at System.Windows.Forms.BindingSource..ctor(Object dataSource, String dataMember)
at BugTest.UserControl1.UserControl1_Load(Object sender, EventArgs e) in D:\Development\Projects\BugTest\BugTest\UserControl1.vb:line 3
at System.Windows.Forms.UserControl.OnLoad(EventArgs e)
at System.Windows.Forms.UserControl.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.ControlCollection.Add(Control value)
at System.Windows.Forms.Form.ControlCollection.Add(Control value)
at System.Windows.Forms.Design.ControlDesigner.DesignerControlCollection.Add(Control c)

Any suggestions how I get out of the hole I've dug?

Chris


PS:
Populating dictTest in _Startup shows the same disease.
VB.NET:
Namespace My
    Partial Friend Class MyApplication
        Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
            ''//fill Public dictTest As New Dictionary(Of String, Byte) "from server"
            With dictTest
                .Add("Great", 220)
                .Add("Good", 200)
                .Add("Average", 180)
                .Add("Poor", 160)
                .Add("Awful", 140)
            End With
        End Sub
    End Class
End Namespace
 
Last edited:
Apparently the internal list in dictionary is nothing at the time it set as datasource for the Bindingsource. What you can do is to initialize it before that.
 
Thanks for your patience, John.

The application RUNS and the combos populate correctly - there are zero runtime errors. The dictionary is therefore populated when usercontrol (and it's combo) instantiates at runtime.

The "error" is only at designtime - attempting to open a form(holding usercontrol(holding combo)) in designview fails when using Datasource/BindingSource to populate the combo from a dictionary in the load event of the usercontrol.

This error is specific to the combo in the usercontrol - an identical combo populated with the same code from the same dictionary but NOT in a usercontrol does not cause any designtime fuss.

VS is expecting the dictionary to be populated at designtime???? :eek:

Chris
 
Ugly workaround in place

This seems to have calmed it down.

VB.NET:
Public Class UserControl1
    Public WriteOnly Property Source() As Dictionary(Of String, Byte)
        Set(ByVal value As Dictionary(Of String, Byte))
            ComboUC.DataSource = New BindingSource(value, Nothing)
            ComboUC.DisplayMember = "Key"       'the String
            ComboUC.ValueMember = "Value"       'the Byte
        End Set
    End Property
End Class

Public Class Form1
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        '// init combo in usercontrol1
        Me.UserControl1.Source = dictTest
    End Sub
End Class

Now it both runs AND works AND opens in designview without error.

phew!

Chris

Generally though, you should always set the 'Member' properties before assigning the datasource.
...noted! I will have a look at that.
 
Yes, designer creates an instance of the usercontrol to be put on the form and loads it (the usercontrols Load event is raised also at design time). The usercontrol code sets up the Bindingsource, that requires the source list to be something. There is another option than initializing the source, you can in usercontrol code check the DesignMode property. Just make sure the dictionary is initialized before the form creates the usercontrol instance, no later than in forms constructor before the InitializeComponent call.
 
Ah yes, trapping DesignMode is much nicer: no need for bizarre code outside the usercontrol itself :)

In the real app, splashform is a regular form with a whole bunch of initialization tasks to perform: it populates the dictionaries before handing over to the "mother" form holding the usercontrols.

Thanks, Chris
 
Back
Top