Requiring values for properties of custom controls

H

Harlan Messinger

I've created a custom control for a Windows Forms application that has
several non-optional properties that should be set in design mode.

a) Is there an attribute that can be used to indicate that a particular
custom property of the control must be given a (non-empty) value?

b) Otherwise, I figure that I will put code in the control's
OnParentChanged event that, at runtime, will throw an exception if
values haven't been assigned to the properties in question. Is this the
best way to handle this? Is there an existing exception that's
appropriate for this?
 
P

Peter Duniho

I've created a custom control for a Windows Forms application that has
several non-optional properties that should be set in design mode.

a) Is there an attribute that can be used to indicate that a particular
custom property of the control must be given a (non-empty) value?

Not that I know of. All Component properties always have _some_ value,
and there's nothing to indicate to the Designer that the user should
always change the value from its default to something else.
b) Otherwise, I figure that I will put code in the control's
OnParentChanged event that, at runtime, will throw an exception if
values haven't been assigned to the properties in question. Is this the
best way to handle this? Is there an existing exception that's
appropriate for this?

I'm not sure why you want to put it in the OnParentChanged() method; seems
like it would be better to do it in OnLoad() or OnShown(), to give client
code the opportunity to change the values programmatically, in the
constructor after the call to InitializeComponent(), for example.

There are lots of exceptions, and probably more than one that might be
appropriate in this situation. But I think I might use the
InvalidOperationException exception for this particular case. If you
like, you can sub-class that exception to provide a more detailed one of
your own specific type.

Pete
 
H

Harlan Messinger

Peter said:
Not that I know of. All Component properties always have _some_ value,
and there's nothing to indicate to the Designer that the user should
always change the value from its default to something else.


I'm not sure why you want to put it in the OnParentChanged() method;
seems like it would be better to do it in OnLoad() or OnShown(), to give
client code the opportunity to change the values programmatically, in
the constructor after the call to InitializeComponent(), for example.

An OnLoad is what I originally intended to override, but I'm not finding
an OnLoad or OnShown in the list of overrideable methods I get when I
type "protected override void ". The list goes from OnLeave to
OnLocationChanged and from OnRightToLeftChanged to OnSizeChanged. Though
my experiencing in sub- or super-classing controls goes all the way back
to Win16, this is the first time I've written a custom control in .NET,
so I'm just first discovering the absence of these hooks and I'm
surprised by it.

The code for my class is below. Have I done something wrong? The
Persister and DataName properties both need non-empty values for the
control to make any sense; I'm going to be adding code to handle an
empty ConfigName as a special case, so the client developer won't have
to set that property unless he wants to.

public partial class PersistingTextBox : TextBox
{
private Persister persister;
private PersistHandler persistHandler;

public string ConfigName { get; set; }
public string DataName { get; set; }

public Persister Persister
{
get
{
return persister;
}
set
{
if (persister != null) persister.Persist -= persistHandler;
persister = value;
persister.Persist += persistHandler;
}
}

public PersistingTextBox()
{
InitializeComponent();
persistHandler = new PersistHandler(Persister_Persist);
}

protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
if (!DesignMode)
{
this.Text = persister.GetValue(DataName);
}
}

protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}

void Persister_Persist()
{
persister.SetValue(DataName, this.Text);
}

}
There are lots of exceptions, and probably more than one that might be
appropriate in this situation. But I think I might use the
InvalidOperationException exception for this particular case. If you
like, you can sub-class that exception to provide a more detailed one of
your own specific type.

Thanks for the suggestion.
 
P

Peter Duniho

An OnLoad is what I originally intended to override, but I'm not finding
an OnLoad or OnShown in the list of overrideable methods I get when I
type "protected override void ". The list goes from OnLeave to
OnLocationChanged and from OnRightToLeftChanged to OnSizeChanged. [...]

Sorry, I "misspoke". OnLoad() and OnShown() are declared in Form, not
Control. They wouldn't be applicable here. Off the top of my head,
possibly OnHandleCreated() might be an equivalent approach for Control
(handle creation is generally deferred until the Control instance has to
actually do some GUI thing). That said, IMHO it would probably be best if
you simply not bother to check until you actually _need_ the values for
the properties. This provides maximum flexibility for any client code
using the control.

Pete
 
H

Harlan Messinger

Peter said:
An OnLoad is what I originally intended to override, but I'm not
finding an OnLoad or OnShown in the list of overrideable methods I get
when I type "protected override void ". The list goes from OnLeave to
OnLocationChanged and from OnRightToLeftChanged to OnSizeChanged. [...]

Sorry, I "misspoke". OnLoad() and OnShown() are declared in Form, not
Control. They wouldn't be applicable here. Off the top of my head,
possibly OnHandleCreated() might be an equivalent approach for Control
(handle creation is generally deferred until the Control instance has to
actually do some GUI thing). That said, IMHO it would probably be best
if you simply not bother to check until you actually _need_ the values
for the properties. This provides maximum flexibility for any client
code using the control.

That's a good point. I guess I can dispense with the convenience of {
get; set; } in exchange for doing the check inside the property itself.
 

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