Showing different properties in design/run mode - user controls

A

ajk

Hi

I was wondering how to show different properties in design and
run-mode for a user control? Is it possible to do this when
implementing the System.ComponentModel.ICustomTypeDescriptor
interface?

e.g. when selecting the control from a toolbox with controls other
properties show up when the program is in design mode than in run
mode.

BR/ajk
 
M

Marc Gravell

Well, yes it probably is, but I wouldn't recommend it; remember that
the designer is typically simply writing code based on the properties,
so keeping it normal (i.e. the same, regular properties exist at both
run- and design-time) is the best approach. Otherwise you'd have to
override the designer serializer to get it to write the correct code
to setup your object, and that isn't always easy.

However! What is it you want to do? If you simply want to filter the
lists, then you can do this by setting appropriate [Browsable] and
[EditorBrowsable] attributes; setting [Browsable(false)] on a property
will remove it from the PropertyGrid (warning: this will also
generally make it non-bindable at run-time); setting
[EditorBrowsable(EditorBrowsableState.Never)] will hide it in the
editor (although it still exists and can be used).

Of course, another option is to write a custom UITypeEditor for your
object, and set the [Editor] against the class; you can then provide
your own UI for the designer to use - but note that it *still* needs
to be understandable by the designer-serializer, so keep it simple...

Is this sufficient?

Marc
 
A

ajk

Well, yes it probably is, but I wouldn't recommend it; remember that
the designer is typically simply writing code based on the properties,
so keeping it normal (i.e. the same, regular properties exist at both
run- and design-time) is the best approach. Otherwise you'd have to
override the designer serializer to get it to write the correct code
to setup your object, and that isn't always easy.

However! What is it you want to do? If you simply want to filter the
lists, then you can do this by setting appropriate [Browsable] and
[EditorBrowsable] attributes; setting [Browsable(false)] on a property
will remove it from the PropertyGrid (warning: this will also
generally make it non-bindable at run-time); setting
[EditorBrowsable(EditorBrowsableState.Never)] will hide it in the
editor (although it still exists and can be used).

Of course, another option is to write a custom UITypeEditor for your
object, and set the [Editor] against the class; you can then provide
your own UI for the designer to use - but note that it *still* needs
to be understandable by the designer-serializer, so keep it simple...

Is this sufficient?

Marc

thanks for your help Marc!

The reason for having different properties in design and run-mode is
that we have a client that allows users to create displays, the person
creating the displays - the designer - is not the same who is going to
use them and therefore they need to be simpler for the end-user.

So when the display is switched to design mode more detailed
properties should show up and when in run-mode just basic ones should
show up like colors.

/ajk
 
M

Marc Gravell

So I assume you are using PropertyGrid on your user-facing UI?

The quickest option here is probably to use BrowsableAttributes on the
PropertyGrid (below)

Marc

using System;
using System.ComponentModel;
using System.Windows.Forms;

static class Program {
static void Main() {
Application.EnableVisualStyles();
using(Form f = new Form())
using (PropertyGrid grid = new PropertyGrid()) {
f.Text = "BrowsableAttributes demo";
grid.Dock = DockStyle.Fill;
grid.SelectedObject = new SomeData();
grid.BrowsableAttributes = new AttributeCollection(new
BrowsableAttribute(true), new UserFacingAttribute());
f.Controls.Add(grid);
Application.Run(f);
}
}
}
sealed class SomeData {

private bool someBool;
[Description("I'm something complex; unsuitable for the users")]
public bool SomeBool { get { return someBool; } set { someBool =
value; } }

private string someString, someComplexString;
[UserFacing, Description("I'm a friendly cuddly string")]
public string SomeString { get { return someString; } set {
someString = value; } }

[Description("Eek!")]
public string SomeComplexString { get { return
someComplexString; } set { someComplexString = value; } }

private DateTime someDate;
[UserFacing, Description("Simple, me")]
public DateTime SomeWhen { get { return someDate; } set { someDate
= value; } }
}

[ImmutableObject(true)]
sealed class UserFacingAttribute : Attribute {}
 
A

ajk

So I assume you are using PropertyGrid on your user-facing UI?

The quickest option here is probably to use BrowsableAttributes on the
PropertyGrid (below)

Marc

using System;
using System.ComponentModel;
using System.Windows.Forms;

static class Program {
static void Main() {
Application.EnableVisualStyles();
using(Form f = new Form())
using (PropertyGrid grid = new PropertyGrid()) {
f.Text = "BrowsableAttributes demo";
grid.Dock = DockStyle.Fill;
grid.SelectedObject = new SomeData();
grid.BrowsableAttributes = new AttributeCollection(new
BrowsableAttribute(true), new UserFacingAttribute());
f.Controls.Add(grid);
Application.Run(f);
}
}
}

well no i am not using the property grid, this program is designed
like this (not my design, som q&d vb6 programmer did it):

user control
communication class : user control
baseclass : communication class
my control : base class (from base class new controls are derived)

then in "my control" there are a number of properties like the normal
location, autosize etc. and some custom ones

e.g.

[Description("String to display instead of the value if the value is
above high range or below low range."), Category("Appearance")]
public string OutOfRangeString
{
get { return this.outOfRangeString; }
set
{
this.outOfRangeString = value;
...
}
}
[DisplayName("Numeric Items"), Browsable(false)]
public NumericValueColorWrapperCollection NumericItems
{
get { return this.numNumValColorWrapCol; }
}

so far that works, however having it like this makes for a lot for
similar coding in each control and it feels as if one can do it better
than this? saving/loading the properties calls a method in the base
class.

i still want to force users to implement the communication methods but
in the base class there are a lot of other gonk which makes each "my
control" quite version sensitive, my idea was to separate the library
stuff from the communication making the comm an interface and the lib
stuff a member instance in the "my control's", then using reflection
to get hold of the methods that way making it more resilient against
versioning.

i appreciate a lot your input! I hope I have expressed myself clearly
even though i went slightly off-topic :)


br/ajk
 
M

Marc Gravell

OK, I'm still slightly confused as to what you want to achive, and
what *exactly* you are calling run- and design- time. If you want some
common properties to be provided automatically, then a base-class
seems in order. There are more complex solutions like
TypeDescriptionProvider, but I'm /really/ not clear what you are
trying to do. Sorry.

I know it might be frustrating, but if you try and re-phase it I'll
have another go?

If it is just a case of declaring properties, then yup; not very
interesting... but prop[tab][tab] can help, as can using the visual
class designer.

Marc
 
A

ajk

OK, I'm still slightly confused as to what you want to achive, and
what *exactly* you are calling run- and design- time. If you want some
common properties to be provided automatically, then a base-class
seems in order. There are more complex solutions like
TypeDescriptionProvider, but I'm /really/ not clear what you are
trying to do. Sorry.

I know it might be frustrating, but if you try and re-phase it I'll
have another go?

If it is just a case of declaring properties, then yup; not very
interesting... but prop[tab][tab] can help, as can using the visual
class designer.

Marc

thanks for being so patient :)

here is another go:

we have a client, it allows the user to create displays. these
displays consist of .net user controls.

the .net user controls communicate with data providers (i.e. data
sources) showing real-time values.

ok so in order to implement the communication in all controls we have
a base class containing virtual methods for the communication.

the client has a design and run mode. in design mode the user can
create the displays by drag and drop from a toolbox similar to visual
studio's tool box. he can also configure the control

in run mode, the displays just show values

in both modes there are properties on the controls, in design mode the
focus is on configuration. in run mode, the focus is on showing
various values i.e. a numeric control shows a temperature,
right-clicking on the control gives an option to show last 10 values
or a trend for them (the controls also show values in design mode).

....

with regard to properties now: until now we have just put those
keywords (Browsable) on each and every property to hide/show the
properties depending on our run/design mode. the question was if there
is another better way to this? the reason i ask is because later when
more and more controls are done everyone of them should have similar
properties in design mode so that handling controls are done in a
similar fashion. however, with the current scheme it is difficult to
enforce, depending on who is doing the control he may decide to show
one property that other controls don't even though he shouldn't

hrmph hopefully this was clearer, although i am not sure :)

tia
ajk
 
M

Marc Gravell

hrmph hopefully this was clearer, although i am not sure :)

OK - so *how* are you currently showing these properties? If this is
via a PropertyGrid (similar to Visual Studio) then a variant on my
earlier post should suffice. If you are showing them in some other,
bespoke way, then you'll need to mention how you are showing them.

As for having similar properties in design mode... put them on the
base-class, then... or if this is not possible, use something like
IExtenderProvider or TypeDescriptionProvider to supplement the
properties on the fly - but the problem here is that you need
somewhere concrete to put the data (the base-class doesn't have this
issue since you can use direct fields storage in the base-class). Any
use?

Marc
 
A

ajk

OK - so *how* are you currently showing these properties? If this is
via a PropertyGrid (similar to Visual Studio) then a variant on my
earlier post should suffice. If you are showing them in some other,
bespoke way, then you'll need to mention how you are showing them.

yep you are right, not having written that piece of code I did some
research and found it. thanks for your help and patience Marc

br/ajk
 

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