Usercontrol Property loses value at runtime - I don't get it?

J

Johnny Jörgensen

Hi y'all

I've got a custom control that is inherited from a normal TextBox. To that,
I've added a new property that I call "Units", Which is a collection class
containing members of a "Unit" class.

When I put my Textbox on the form, I can access the "Units" property from
the IDE's property grid, use the collection designer and add new "Unit"
members to the class.

So far, so good, but when I run my project and query the "Units" collection,
it's empty. Afterwards, I can see in the Collection editor that my "Unit"
members are still there.

If I add the "Unit" members programmatically at runtime, there's no problem.

It must be something I'm missing because I'm not good enough at OOP, but
what?

Can somebody give me a clue, please?

TIA,
Johnny J.
 
L

L.W.C. Nirosh

Probably the Unit collection get initialize by the time it run..

Static attribute for the Units Collection property would workout for you I
guess..

Nirosh.
 
L

L.W.C. Nirosh

Check where you have initialized the collection.. becos I think you are
initializin gthe collection as the application starts..

Nirosh.
 
J

Johnny Jörgensen

In Visual Basic, you normally have to save all the properties in the PropBag
using PropBag.ReadProperty & PropBag.WriteProperty for persistancy.

I don't know how you do in C#, though?

Cheers,

Johnny J.
 
R

Roman Wagner

Search for all References of your Units Property (search for the
private Units member too) and check for
assignment expressions or something like Clear(); Check the designer
generated code whether the serealized
unitscollection is loaded from the resourcefile.
 
J

Johnny Jörgensen

I Still haven't found the solution...

Surely, somebody out there must have experience in control creation and know
the answer... :)

/Johnny J.
 
P

Pete Kane

Johnny said:
I Still haven't found the solution...

Surely, somebody out there must have experience in control creation and know
the answer... :)

/Johnny J.
can you post some code ?
 
J

Johnny Jörgensen

can you post some code ?

Sure. Below is the complete code for my control this far - I'm almost done,
but I have this problem: My control contains a collection called Units that
consists of X number of Unit Members. I can see the collection in the
control's properties in the property explorer, and I can add the unit
elements to the unit property using the property explorers collection
editor. But when I run the project, the Unit members are gone.

I'm sure the answer lies in serialization, but I don't know how to do it. In
VB6, you used to use an object called a Property Bag to store properties
between design and runtime. But that's changed in .NET. I found the
following article on MSDN, but I haven't had a chance to look closer at it
(and apply it to C#) yet:

http://msdn2.microsoft.com/en-us/library/aa289514(vs.71,d=printer).aspx

Cheers,
Johnny J.




******** CODE BEGINS HERE:



using System;

using System.ComponentModel;

using System.Collections;

using System.Collections.Generic;

using System.Diagnostics;

using System.Text;

using System.Windows.Forms;

using System.Runtime.Serialization;

namespace UserControls

{

public delegate void UnitErrorDelegate(object sender, UnitErrorEventArgs e);


public partial class FoBNumericUnitTextBox : TextBox

{

public event UnitErrorDelegate ErrorEncountered;


private string m_FancyText = "";

private string m_SimpleText = "";


private bool m_Focused = false;

private bool m_NonNumberEntered = false;

static private Units m_Units = null;


public Units Units

{

get

{

if (m_Units == null)

{

m_Units = new Units();

}

return m_Units;

}

set

{

m_Units = value;

}

}

public string FancyText

{

get { return m_FancyText; }

set {

m_FancyText = value;

ConvertToSimpleText(m_FancyText);

if (m_Focused)

{ base.Text = m_SimpleText; }

else

{ base.Text = m_FancyText; }

}

}


public override string Text

{

get

{

return m_SimpleText;

}

set

{

m_SimpleText = value;

ConvertToFancyText(m_SimpleText);

if (m_Focused)

{ base.Text = m_SimpleText; }

else

{ base.Text = m_FancyText; }

}

}

public FoBNumericUnitTextBox()

{

InitializeComponent();

}

public FoBNumericUnitTextBox(IContainer container)

{

container.Add(this);

InitializeComponent();

}

private void OnFoBNumericUnitTextBox_Enter(object sender, EventArgs e)

{

m_Focused = true;

base.Text = m_SimpleText;

}

private void OnFoBNumericUnitTextBox_Leave(object sender, EventArgs e)

{

m_Focused = false;

ConvertToFancyText(base.Text);

base.Text = m_FancyText;

}


private void ConvertToFancyText(string simpleText)

{

// TODO: Convert

}

private void ConvertToSimpleText(string fancyText)

{

// TODO: Convert

}

private void OnFoBNumericUnitTextBox_KeyDown(object sender, KeyEventArgs e)

{

// Initialize the flag to false.

m_NonNumberEntered = false;

// Determine whether the keystroke is a number from the top of the keyboard.

if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)

{

// Determine whether the keystroke is a number from the keypad.

if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)

{

// Determine whether the keystroke is a backspace.

if (e.KeyCode != Keys.Back)

{

// TODO: Check för separatorchar


// A non-numerical keystroke was pressed.

// Set the flag to true and evaluate in KeyPress event.

m_NonNumberEntered = true;

}

}

}

}

private void OnFoBNumericUnitTextBox_KeyPress(object sender,
KeyPressEventArgs e)

{

// Check for the flag being set in the KeyDown event.

if (m_NonNumberEntered == true)

{

// Stop the character from being entered into the control since it is
non-numerical.

e.Handled = true;

}

}

}


public class Units : CollectionBase

{

private string m_DefaultSeparatorChar = ":";

public string DefaultSeparatorChar

{

get { return m_DefaultSeparatorChar; }

set { m_DefaultSeparatorChar = value; }

}


public Unit Add()

{

Unit newUnit = new Unit();

newUnit.SeparatorChar = m_DefaultSeparatorChar;

newUnit.UnitText= "Unit" + Convert.ToString(List.Count + 1);

List.Add(newUnit);

return newUnit;

}


new public void Clear()

{

List.Clear();

}


public void Remove(Unit oldUnit)

{

List.Remove(oldUnit);

}


public Units()

{

}


new public Int32 Count()

{

return List.Count;

}


public Unit this[int unitIndex]

{

get

{

try

{

return (Unit)List[unitIndex];

}

catch

{

//Ignore

return null;

}

}

set

{

List[unitIndex] = value;

}

}

}

public class UnitErrorEventArgs

{

private Int32 m_ErrorIndex;

private string m_ErrorText;

private Unit m_ErrorUnit;


public Int32 ErrorIndex

{

get { return m_ErrorIndex; }

set { m_ErrorIndex = value; }

}


public string ErrorText

{

get { return m_ErrorText; }

set { m_ErrorText = value; }

}


public Unit ErrorUnit

{

get { return m_ErrorUnit; }

set { m_ErrorUnit = value; }

}

}


public class Unit

{

private string m_UnitText = "UnitText";

private string m_SeparatorChar = ":";

private Int32 m_MaxValue = 0;

private Int32 m_MinValue = 0;

private bool m_CheckValueRange = false;

public bool CheckValueRange

{

get { return m_CheckValueRange; }

set { m_CheckValueRange = value; }

}


public string SeparatorChar

{

get { return m_SeparatorChar; }

set { m_SeparatorChar = value; }

}

public string UnitText

{

get { return m_UnitText; }

set { m_UnitText = value; }

}

public Int32 MinValue

{

get { return m_MinValue; }

set { m_MinValue = value; }

}


public Int32 MaxValue

{

get { return m_MaxValue; }

set { m_MaxValue = value; }

}

}


}
 
J

Johnny Jörgensen

As mentioned, I'm sure the answer lies in serialization. I've read up on
some articles on that, but there is a problem:

In VB6, I could save and retrieve control settings from within the control
using the PropBag object. According to MSDN, the PropBag is replaced by
serialization, but all the articles I've read shows how you save an instance
of your object from the application itself or from another class - not from
the object itself.

And I want to keep all code inside my control object and not have to do
anything from the outside.

How the heck does it work?

/Johnny J.



Johnny Jörgensen said:
can you post some code ?

Sure. Below is the complete code for my control this far - I'm almost
done, but I have this problem: My control contains a collection called
Units that consists of X number of Unit Members. I can see the collection
in the control's properties in the property explorer, and I can add the
unit elements to the unit property using the property explorers collection
editor. But when I run the project, the Unit members are gone.

I'm sure the answer lies in serialization, but I don't know how to do it.
In VB6, you used to use an object called a Property Bag to store
properties between design and runtime. But that's changed in .NET. I found
the following article on MSDN, but I haven't had a chance to look closer
at it (and apply it to C#) yet:

http://msdn2.microsoft.com/en-us/library/aa289514(vs.71,d=printer).aspx

Cheers,
Johnny J.




******** CODE BEGINS HERE:



using System;

using System.ComponentModel;

using System.Collections;

using System.Collections.Generic;

using System.Diagnostics;

using System.Text;

using System.Windows.Forms;

using System.Runtime.Serialization;

namespace UserControls

{

public delegate void UnitErrorDelegate(object sender, UnitErrorEventArgs
e);


public partial class FoBNumericUnitTextBox : TextBox

{

public event UnitErrorDelegate ErrorEncountered;


private string m_FancyText = "";

private string m_SimpleText = "";


private bool m_Focused = false;

private bool m_NonNumberEntered = false;

static private Units m_Units = null;


public Units Units

{

get

{

if (m_Units == null)

{

m_Units = new Units();

}

return m_Units;

}

set

{

m_Units = value;

}

}

public string FancyText

{

get { return m_FancyText; }

set {

m_FancyText = value;

ConvertToSimpleText(m_FancyText);

if (m_Focused)

{ base.Text = m_SimpleText; }

else

{ base.Text = m_FancyText; }

}

}


public override string Text

{

get

{

return m_SimpleText;

}

set

{

m_SimpleText = value;

ConvertToFancyText(m_SimpleText);

if (m_Focused)

{ base.Text = m_SimpleText; }

else

{ base.Text = m_FancyText; }

}

}

public FoBNumericUnitTextBox()

{

InitializeComponent();

}

public FoBNumericUnitTextBox(IContainer container)

{

container.Add(this);

InitializeComponent();

}

private void OnFoBNumericUnitTextBox_Enter(object sender, EventArgs e)

{

m_Focused = true;

base.Text = m_SimpleText;

}

private void OnFoBNumericUnitTextBox_Leave(object sender, EventArgs e)

{

m_Focused = false;

ConvertToFancyText(base.Text);

base.Text = m_FancyText;

}


private void ConvertToFancyText(string simpleText)

{

// TODO: Convert

}

private void ConvertToSimpleText(string fancyText)

{

// TODO: Convert

}

private void OnFoBNumericUnitTextBox_KeyDown(object sender, KeyEventArgs
e)

{

// Initialize the flag to false.

m_NonNumberEntered = false;

// Determine whether the keystroke is a number from the top of the
keyboard.

if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)

{

// Determine whether the keystroke is a number from the keypad.

if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)

{

// Determine whether the keystroke is a backspace.

if (e.KeyCode != Keys.Back)

{

// TODO: Check för separatorchar


// A non-numerical keystroke was pressed.

// Set the flag to true and evaluate in KeyPress event.

m_NonNumberEntered = true;

}

}

}

}

private void OnFoBNumericUnitTextBox_KeyPress(object sender,
KeyPressEventArgs e)

{

// Check for the flag being set in the KeyDown event.

if (m_NonNumberEntered == true)

{

// Stop the character from being entered into the control since it is
non-numerical.

e.Handled = true;

}

}

}


public class Units : CollectionBase

{

private string m_DefaultSeparatorChar = ":";

public string DefaultSeparatorChar

{

get { return m_DefaultSeparatorChar; }

set { m_DefaultSeparatorChar = value; }

}


public Unit Add()

{

Unit newUnit = new Unit();

newUnit.SeparatorChar = m_DefaultSeparatorChar;

newUnit.UnitText= "Unit" + Convert.ToString(List.Count + 1);

List.Add(newUnit);

return newUnit;

}


new public void Clear()

{

List.Clear();

}


public void Remove(Unit oldUnit)

{

List.Remove(oldUnit);

}


public Units()

{

}


new public Int32 Count()

{

return List.Count;

}


public Unit this[int unitIndex]

{

get

{

try

{

return (Unit)List[unitIndex];

}

catch

{

//Ignore

return null;

}

}

set

{

List[unitIndex] = value;

}

}

}

public class UnitErrorEventArgs

{

private Int32 m_ErrorIndex;

private string m_ErrorText;

private Unit m_ErrorUnit;


public Int32 ErrorIndex

{

get { return m_ErrorIndex; }

set { m_ErrorIndex = value; }

}


public string ErrorText

{

get { return m_ErrorText; }

set { m_ErrorText = value; }

}


public Unit ErrorUnit

{

get { return m_ErrorUnit; }

set { m_ErrorUnit = value; }

}

}


public class Unit

{

private string m_UnitText = "UnitText";

private string m_SeparatorChar = ":";

private Int32 m_MaxValue = 0;

private Int32 m_MinValue = 0;

private bool m_CheckValueRange = false;

public bool CheckValueRange

{

get { return m_CheckValueRange; }

set { m_CheckValueRange = value; }

}


public string SeparatorChar

{

get { return m_SeparatorChar; }

set { m_SeparatorChar = value; }

}

public string UnitText

{

get { return m_UnitText; }

set { m_UnitText = value; }

}

public Int32 MinValue

{

get { return m_MinValue; }

set { m_MinValue = value; }

}


public Int32 MaxValue

{

get { return m_MaxValue; }

set { m_MaxValue = value; }

}

}


}
 

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

Top