Sign in to follow this  
Barguast

[.net] UserControls - Overriding the Text property

Recommended Posts

I've made a UserControl which is a simple button. I know want to override the Text property of the UserControl class so this can be used to modify what text is displayed on the button. I'm using the following code to do this:
public override string Text
{
	get { return lblText.Text; }
	set { lblText.Text = value; }
}

I can't see what is wrong with this, but whenever I draw the control on a form, the Text property doesn't show up in the list of properties (In the Form designer). Am I doing something wrong?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You need to add an attribute to your property ( most likely this is already set to false in the baseclass, so you need to reset it to true for your derived class ).


[Browsable(true)]
public override string Text
{
get { return lblText.Text; }
set { lblText.Text = value; }
}


Share this post


Link to post
Share on other sites
EDIT: Although it worked (the property does show up in the list) the value reverts back to the default value whenever I compile the program. Originally, the text just says 'Flat Button' (the name of the control), I can change this to 'OK' in the properties list but when I compile it changes back to 'Flat Button' again. I notice that when I change the property the appropriate code is not inserted into the InitializeComponent function like it does with the other properties. Any idea what the problem might be this time?

Can anyone recommend a good online resource where I can read up on attributes? MSDN's a given, but I use that mostly for reference.

Thanks!



[Edited by - Barguast on August 4, 2004 7:28:05 AM]

Share this post


Link to post
Share on other sites
My latest problem seems to be caused by overriding the Text property. For example, if I use a property called caption instead:

public string Caption
{
get { return this.Text; }
set { this.Text = value; this.Invalidate (); }
}

Then everything works fine. Notice that this is just accessing the Text property. But if I overload the Text property (which I should, and want to do) as demonstrated by the following then the Text property won't retain its value.

[Browsable(true)]
public string override Text
{
get { return this.Text; }
set { this.Text = value; this.Invalidate (); }
}


Does anyone know how I can solve this problem?

Share this post


Link to post
Share on other sites
Ha, this just gets worse and worse. As I was changing the property back from 'Caption' to 'Text' I got some StackOverflow error when it tried to draw the control - I managed to solve it by using base.Text instead of this.text, as shown.

[Browsable(true)]
public override string Text
{
get { return base.Text; }
set { base.Text = value; this.Invalidate (); }
}

HOWEVER, this hasn't got anything (I think?) to do with my problem, I just a little curious why it happened.

The code is:


using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;

namespace Custom.Windows.Forms
{
// CLASS : FlatButton
// ==================
// A custom button control
public class FlatButton : UserControl
{
private Container components = null;
private int m_ColourTint = 0;
private Color m_Colour1 = Color.WhiteSmoke;
private Color m_Colour2 = Color.FromArgb (220, 220, 220);
private Color m_BorderColour = Color.DarkGray;

// Default Constructor
public FlatButton ()
{
InitializeComponent();
this.Text = "Flat Button";
}

// Dispose
protected override void Dispose (bool bDisposing)
{
if (bDisposing)
{
if (components != null)
components.Dispose ();
}
base.Dispose (bDisposing);
}

#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// FlatButton
//
this.Name = "FlatButton";
this.Size = new System.Drawing.Size(88, 24);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FlatButton_MouseUp);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.FlatButton_Paint);
this.MouseEnter += new System.EventHandler(this.FlatButton_MouseEnter);
this.MouseLeave += new System.EventHandler(this.FlatButton_MouseLeave);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FlatButton_MouseDown);
this.Layout += new System.Windows.Forms.LayoutEventHandler(this.FlatButton_Layout);

}
#endregion

// *** EVENTS ***

// Paint Events
private void FlatButton_Paint (object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;

// Define the gradient colour
int R1, G1, B1, R2, G2, B2;
R1 = ValidateColourComponent (TopColour.R + ColourTint);
G1 = ValidateColourComponent (TopColour.G + ColourTint);
B1 = ValidateColourComponent (TopColour.B + ColourTint);
R2 = ValidateColourComponent (BottomColour.R + ColourTint);
G2 = ValidateColourComponent (BottomColour.G + ColourTint);
B2 = ValidateColourComponent (BottomColour.B + ColourTint);

Color Colour1 = Color.FromArgb (R1, G1, B1);
Color Colour2 = Color.FromArgb (R2, G2, B2);;

// Draw the gradient
g.FillRectangle (new LinearGradientBrush
(this.ClientRectangle, Colour1, Colour2, LinearGradientMode.Vertical),
this.ClientRectangle);

// Measure the text string
SizeF StringSize = new SizeF ();
StringSize = g.MeasureString (Text, this.Font);

// Calculate the position of the string
int X, Y;
X = (int)(this.ClientSize.Width - StringSize.Width) / 2;
Y = (int)(this.ClientSize.Height - StringSize.Height) / 2;

// Draw the string
g.DrawString (Text, this.Font, new SolidBrush (this.ForeColor), X, Y);

// Draw the border
g.DrawRectangle (new Pen (this.BorderColour, 1),
new Rectangle (0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1));
}

// This function is used by FlatButton_Paint
private int ValidateColourComponent (int val)
{
if (val < 0)
val = 0;
else if (val > 255)
val = 255;
return val;
}

// Mouse Enter events
private void FlatButton_MouseEnter(object sender, System.EventArgs e)
{
ColourTint = 10;
}

// Mouse Leave events
private void FlatButton_MouseLeave(object sender, System.EventArgs e)
{
ColourTint = 0;
}

// Mouse Down events
private void FlatButton_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
ColourTint = -10;
}

// Mouse Up events
private void FlatButton_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
ColourTint = 0;
}

// Layout events
private void FlatButton_Layout(object sender, System.Windows.Forms.LayoutEventArgs e)
{
this.Invalidate ();
}

// *** PROPERTIES ***
[Browsable(true)]
public override string Text
{
get { return base.Text; }
set { base.Text = value; this.Invalidate (); }
}

[Browsable(true)]
public Color TopColour
{
get { return m_Colour1; }
set { m_Colour1 = value; this.Invalidate (); }
}

[Browsable(true)]
public Color BottomColour
{
get { return m_Colour2; }
set { m_Colour2 = value; this.Invalidate (); }
}

[Browsable(true)]
public Color BorderColour
{
get { return m_BorderColour; }
set { m_BorderColour = value; this.Invalidate (); }
}

private int ColourTint
{
get { return m_ColourTint; }
set { m_ColourTint = value; this.Invalidate (); }
}
}
}




To demonstrate my problem:
- Draw the control onto a Form (The text should initially say 'flatButton1' for some reason - it should say 'Flat Button')
- Edit the Text property so it says something else (e.g. "OK")
- Compile the project

Now the text property should change to 'Flat Button'. This doesn't happen if I create a property myself called 'Caption' which does the exact same thing.

Thanks!

EDIT: Nevermind the first half of this post - I worked it out and I really should have realised in the first place!
EDIT AGAIN: I should point out that working the first part out has -not- solved my problem!

[Edited by - Barguast on August 4, 2004 4:17:35 PM]

Share this post


Link to post
Share on other sites
Are you sure that it stays the same even if you change the Text property to, for example, 'OK' and THEN recompile? It's at that point that the property changes back to 'Flat Button' as shown in your screenshot...

Share this post


Link to post
Share on other sites
Ok, fixed it

You need to change it to:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), Bindable(true), Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
public override string Text {
get { return base.Text; }
set { base.Text = value; this.Invalidate (); }
}




Because by default it is:


[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Bindable(false), Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
}
}


Share this post


Link to post
Share on other sites
THOSE DAMNED ATTRIBUTES. AGAIN!

I really do need to read up on those because all of my problems with C# have been down to these. Can you tell me of any good places I can read up on them?

And thank you, thank you, thank you for solving this problem!

Share this post


Link to post
Share on other sites
rofl, simple problem, I just had to look at the UserControl source.

anyways, MSDN is a great source... it's what i use 99% of the time. the other 1% is me poking around their source code.

Share this post


Link to post
Share on other sites
This is a really minor problem, but I'd like to know why it's happening (just out of curiousity).

As you can see in the code, the Text property is meant to be set to 'Flat Button' during the control's construction. However, whenever I create a control, the text defaults to 'flatButton#' where # is a number that makes the text unique. It seems to be setting the Text property to the name of the control.

This, again, is something that goes away if I use a custom property name instead of the Text property. I've looked on MSDN, and through those fricken attributes, but I can't see why this is happening. I also tried putting the 'this.Text = "Flat Button";' line in the InitializeComponent function, but this didn't work either. Anyone?

Also, Washu said that you looked through the UserControl source - did you download this from somewhere?

Thanks

Share this post


Link to post
Share on other sites
Ahh, that's VS default method for naming items. You can't override it, so...you're stuck with it.

As far as the source goes, no. I actually used a disassembler called Reflector

Share this post


Link to post
Share on other sites
Answers to the questions that were left unanswered...

Q: Why is it working with a new property Caption and not with an overriden Text ?

A: Because the existing Text caption has attributes which prevent it to work. The new Caption property has no attributes, and the default values are what you need.

Q: Why is my property not visible ?

A: The attribute Browsable allows public properties to be visible in the property grid. It is true by default, but Text has it set to false so you have to change it explicitly.

Q: Why aren't my property changes persisted in the code ?

A: DesignerSerializationVisibility lets you decide if a property should be persisted or not (i.e. is just for viewing and side-effects of assignment). By default it's 'Visible', which means that it's persisted in the initialization code. But again, the Text property has it set to 'Hidden', which means it's not persisted. Note there's a third possibility: 'Content'. Check it on MSDN.

Q: What was that funny name then ?

A: the name you saw was the default value given in the class constructor. It goes away with a new property because the new property not assigned in the class constructor.

Q: Why didn't putting 'this.Text = "Flat Button";' in the InitializeComponent function solve the problem ?

A: The InitializeComponent function is overwritten by the IDE every time it saves your form in the code. Don't make any change there, it will be lost next time the form designer saves its work.

Q: One last piece of advice ?

A: Yes, if you want to do other stuff concerning design time, you really should dig into attributes, since they control lots of design time things. By the way, the other mentionned attributes (Bindable and EditorBrowsable) should not be related to your problem. You should be able to just ignore them.

Have a nice day,
jods

Share this post


Link to post
Share on other sites
Quote:
Original post by jods
Answers to the questions that were left unanswered...

Q: One last piece of advice ?

A: Yes, if you want to do other stuff concerning design time, you really should dig into attributes, since they control lots of design time things. By the way, the other mentionned attributes (Bindable and EditorBrowsable) should not be related to your problem. You should be able to just ignore them.

Have a nice day,
jods


While they are not directly related, all of the non-user controls have those properties set to values set to true. And if he decides to get into more advanced things (like DB queries) he will need to be able to bind them.

The EditorBrowsable attribute affects Intellisense.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this