comboBox from enum?

D

DanB

Say I want to add a comboBox to a form and have it populated with the
enum of an object. Is there a way to do this quickly? I've been creating
the list by hand.

Thanks, Dan.

Like for Markers:

namespace System.Windows.Forms.DataVisualization.Charting
{
// Summary:
// Specifies a style for markers.
public enum MarkerStyle
{
// Summary:
// No marker is displayed for the series or data point.
None = 0,
//
// Summary:
// A square marker is displayed.
Square = 1,
//
// Summary:
// A circular marker is displayed.
Circle = 2,
//
// Summary:
// A diamond-shaped marker is displayed.
Diamond = 3,
//
// Summary:
// A triangular marker is displayed.
Triangle = 4,
//
// Summary:
// A cross-shaped marker is displayed.
Cross = 5,
//
// Summary:
// A 4-point star-shaped marker is displayed.
Star4 = 6,
//
// Summary:
// A 5-point star-shaped marker is displayed.
Star5 = 7,
//
// Summary:
// A 6-point star-shaped marker is displayed.
Star6 = 8,
//
// Summary:
// A 10-point star-shaped marker is displayed.
Star10 = 9,
}
}
 
P

Peter Duniho

DanB said:
Say I want to add a comboBox to a form and have it populated with the
enum of an object. Is there a way to do this quickly? I've been creating
the list by hand.

What does "enum of an object" mean? Do you actually mean "values of an
enum"?

If so, this might work for you:

static void AddEnumValues<T>(this ComboBox combo)
{
combo.Items.AddRange(
Enum.GetValues(typeof(T)).Cast<object>().ToArray());
}

used like this (extension method syntax):

comboBox1.AddEnumValues<MarkerStyle>();

or if you don't use the extension method syntax (assuming the method is
in a class named "Util"):

Util.AddEnumValues<MarkerStyle>(comboBox1);

Pete
 
D

DanB

Peter said:
What does "enum of an object" mean? Do you actually mean "values of an
enum"?

Thanks Peter,
I meant the 'names' of the numeration. And at 'writing' time. Yes I see
I can get the names at run time. I do that to look up the string name in
the enum to get the value now.

I'm doing this kind of stuff:

To box:
tname= Enum.GetName( typeof( SeriesChartType ), curItem.seriesSet[ pos
].type );
comboBoxChartType1.SelectedIndex= comboBoxChartType.FindStringExact(
tname );;

From box:
curItem.seriesSet[ pos ].type= (SeriesChartType)Enum.Parse(
typeof(SeriesChartType), comboBoxChartType.Text, true );

And because my .type is of type SeriesChartType, it parses out to the
xml by name without the need of my creating an interface, I like that.

This is way different thinking than in c++, I'm still in the deep
learning curve.

Best, Dan.
 
P

Peter Duniho

DanB said:
[...]
To box:
tname= Enum.GetName( typeof( SeriesChartType ), curItem.seriesSet[ pos
].type );
comboBoxChartType1.SelectedIndex= comboBoxChartType.FindStringExact(
tname );;

If you initialize the items in the ComboBox to the actual enum values
(e.g. as in the code I posted earlier), then you can simply set the
SelectedItem property to the enum value in question. The ComboBox class
will handle the rest, without you having to explicitly call something
like FindStringExact().

So, when the ComboBox is properly initialized, you get something more
like this for the above code:

comboBoxChartType1.SelectedItem = cutItem.seriesSet[pos].type;

Likewise, this:
From box:
curItem.seriesSet[ pos ].type= (SeriesChartType)Enum.Parse(
typeof(SeriesChartType), comboBoxChartType.Text, true );

…becomes this:

curItem.seriesSet[pos].type =
(SeriesChartType)comboBoxChartType1.SelectedItem;

Pete
 
D

DanB

Peter said:
If you initialize the items in the ComboBox to the actual enum values
(e.g. as in the code I posted earlier), then you can simply set the
SelectedItem property to the enum value in question. The ComboBox class
will handle the rest, without you having to explicitly call something
like FindStringExact().

So, when the ComboBox is properly initialized, you get something more
like this for the above code:

comboBoxChartType1.SelectedItem = cutItem.seriesSet[pos].type;

Likewise, this:
From box:
curItem.seriesSet[ pos ].type= (SeriesChartType)Enum.Parse(
typeof(SeriesChartType), comboBoxChartType.Text, true );

…becomes this:

curItem.seriesSet[pos].type =
(SeriesChartType)comboBoxChartType1.SelectedItem;

Hi Peter,
Old habits. I would avoid storing data as an index whenever possible.
Now my 'type' would be a plain old int rather than a type with
appropriate baggage. What if there were a revision and a new name where
put in at position 3? If stored by name versioning is automatic. I can
change the order in my combo, add delete stuff without maintinance of
the database.

But then I see that XmlSerialize is rather non forgiving. My xml lib
doesn't care if stuff comes and goes. I have not had to version my
product xml databases ever for small structural changes, additions,
deletions. In fact, if I don't explicitly delete and rewrite a set of
elements, legacy elements will ride along forever. Where as one little
thing out of place and XmlSerialize completly fails on me. It doesn't
return any of my data. It means I'll have to run a backup utility and
preserve/reload if a read fails I guess. Here is a snip from one database:

<VirtualFileTable>
<VirtualItem>
<vName>DEFAULT_PROJECT_NAME</vName>
<path>Default.ars</path>
<flags>SYSTEM,PERMANENT,EXFROMREPORT</flags>
....

The flags are an enum in the program and I can mess with it anytime I'd
like without affecting previous use.

Best, Dan.
 
P

Peter Duniho

DanB said:
Peter said:
If you initialize the items in the ComboBox to the actual enum values
(e.g. as in the code I posted earlier), then you can simply set the
SelectedItem property to the enum value in question. The ComboBox class
will handle the rest, without you having to explicitly call something
like FindStringExact().

So, when the ComboBox is properly initialized, you get something more
like this for the above code:

comboBoxChartType1.SelectedItem = cutItem.seriesSet[pos].type;

Likewise, this:
From box:
curItem.seriesSet[ pos ].type= (SeriesChartType)Enum.Parse(
typeof(SeriesChartType), comboBoxChartType.Text, true );

…becomes this:

curItem.seriesSet[pos].type =
(SeriesChartType)comboBoxChartType1.SelectedItem;

Hi Peter,
Old habits. I would avoid storing data as an index whenever possible.
Now my 'type' would be a plain old int rather than a type with
appropriate baggage. What if there were a revision and a new name where
put in at position 3? If stored by name versioning is automatic. I can
change the order in my combo, add delete stuff without maintinance of
the database.

Look again at the code I posted. It does not store the data "as an
index". In fact, it doesn't change your design at all. It simply
implements your design without all the extra, unnecessary code you were
using before.

As for your serialization problems, well…type safety, versioning, and
data consistency requirements are a double-edged sword. It's true, you
can write your own serialization that doesn't impose the same
requirements on the data. But that serialization method also will fail
silently if and when the data is corrupted or otherwise incorrect for
your given scenario.

For low-priority, low-value data that's probably fine. But hopefully
you can see why a library like .NET is only going to provide
serialization techniques that are more robust (albeit with their own
imperfections, of course).

Pete
 
D

DanB

Peter said:
DanB said:
Peter said:
So, when the ComboBox is properly initialized, you get something more
like this for the above code:

comboBoxChartType1.SelectedItem = cutItem.seriesSet[pos].type;

Likewise, this:

From box:
curItem.seriesSet[ pos ].type= (SeriesChartType)Enum.Parse(
typeof(SeriesChartType), comboBoxChartType.Text, true );

…becomes this:

curItem.seriesSet[pos].type =
(SeriesChartType)comboBoxChartType1.SelectedItem;

Hi Peter,
Old habits. I would avoid storing data as an index whenever possible.

Look again at the code I posted. It does not store the data "as an
index". In fact, it doesn't change your design at all. It simply
implements your design without all the extra, unnecessary code you were
using before.

I see what you mean, but you threw me as you didn't cast in the top example.

But this means I'd have to use the enum as is, I can't set which items
and what order in the dropdown, which is what I'm after. So if I
populate the comboBox by hand, I'll still have to use my code it seems.
As for your serialization problems, well…type safety, versioning, and
data consistency requirements are a double-edged sword. It's true, you
can write your own serialization that doesn't impose the same
requirements on the data. But that serialization method also will fail
silently if and when the data is corrupted or otherwise incorrect for
your given scenario.

For low-priority, low-value data that's probably fine. But hopefully you
can see why a library like .NET is only going to provide serialization
techniques that are more robust (albeit with their own imperfections, of
course).

If I change:
<type>Line</type>
to:
<type>Lines</type>

It completely fails to load. My lib would return the default. I'm not
sure what the trade off is, i.e., what do I gain by this kind of
crankiness? I'd think robust includes forgiveness.

I consider my app data very high value, it is my clients work at risk.
In all the years I've been using my lib I have yet to have a problem
like loosing client data unless the file is grosly corrupted, and that
is very rare.

I'm figuring the easiest way to handle this is a running back up for now
and if I catch in the load, let the client use the previous file. Yea,
once the data is settled in, it should not really be a problem. I'm a
pretty simple minded xml user as I primarily use it as a DOM database in
my stuff. I'll have to see what XmlDocument is like to use instead of
serialization some day. (And if this sounds like I don't know what I'm
talking about, sure, I've been doing c# for less than a week. :)
<http://msdn.microsoft.com/en-us/magazine/cc302158.aspx>

This is so far an exercise to learn c# and this app will be a helper in
my product. And that I'm using it I'll have to provide a 3.5 .NET
installer for those who don't have it. But I'm trying to move into the
new world.

This morning I've tried an experiment by copying the exe to my wife's
computer. She has a year old Vista with .NET 3.5 installed. But it fails
to run on her machine. I have put a MessageBox right at the start so I
don't have to worry about other why's further in the program. More
TODOs! I can drop a c++ exe on her machine and it runs fine. Is this
because c# programs have to be installed, or something else? Not sure as
I can run it from anyplace on my machine.

Best, Dan.
 
P

Peter Duniho

DanB said:
[...]
Look again at the code I posted. It does not store the data "as an
index". In fact, it doesn't change your design at all. It simply
implements your design without all the extra, unnecessary code you were
using before.

I see what you mean, but you threw me as you didn't cast in the top
example.

No cast is needed going from the more-derived type to the less-derived
type. But, as always, you need a cast going the other way.
But this means I'd have to use the enum as is, I can't set which items
and what order in the dropdown, which is what I'm after.

It doesn't mean that at all. It's true that the code I posted populates
the list in order of appearance in the enum. But nothing is stopping
you from imposing your own order on the list.
So if I
populate the comboBox by hand, I'll still have to use my code it seems.

Probably not true. But until you provide specific information,
including what "your code" looks like, impossible to know for sure from
this end.
If I change:
<type>Line</type>
to:
<type>Lines</type>

It completely fails to load. My lib would return the default. I'm not
sure what the trade off is, i.e., what do I gain by this kind of
crankiness? I'd think robust includes forgiveness.

Why in the world would the content of the element ever be "Lines"
instead of "Line"? What value is there in allowing the latter, when the
former is the only correct, expected output from your serialization code?

"Robust" can mean whatever you want. But usually, "robust" means the
code is hardened against bad input, not that it makes guesses as to what
bad input is intended to mean.
I consider my app data very high value, it is my clients work at risk.
In all the years I've been using my lib I have yet to have a problem
like loosing client data unless the file is grosly corrupted, and that
is very rare. [...]

All due respect, with a serialization technique that makes guesses as to
the intent of bad input, you have no idea whatsoever whether there has
been an actual problem or not. All you know is that if there has been a
problem, it hasn't been obvious enough for anyone to notice.

Pete
 
T

Tim Roberts

DanB said:
This morning I've tried an experiment by copying the exe to my wife's
computer. She has a year old Vista with .NET 3.5 installed.

Are you sure? HOW are you sure?
But it fails
to run on her machine. I have put a MessageBox right at the start so I
don't have to worry about other why's further in the program.

Release build? Debug build?
I can drop a c++ exe on her machine and it runs fine.

Not always. Try to do that with a DEBUG build, for example. Unless you
were foresighted enough to statically link the CRT, you'd be screwed.
 
D

DanB

Tim said:
Are you sure? HOW are you sure?

I looked at her installed, control panel->programs and features. 3.5 and
sp1 are there.
Release build? Debug build?

Absolutely Release, I would not expect the debug to work.
Not always. Try to do that with a DEBUG build, for example. Unless you
were foresighted enough to statically link the CRT, you'd be screwed.

I didn't try the debug. But in c++ I could drop the debug exe anywhere
on my machine. I don't know poop about c#. So is it your opinion that a
c# (release)executable should run on another machine as long as the
appropreate .NET is installed? Might it be an issue of a missing xxx
because I'm running with (dundas) MScharts? All I get is a simple 'has
stopped working' message, not the missing dll message I'd expect if that
were the case. (Would you get that with .NET as you would with native code?)

Thanks, Dan.

P.S. I'm going to get a book. But for now I'm just looking to get the
new charting working.
 
D

DanB

I built a console app that writes a file. When I drop that on her
computer it works fine.

Best, Dan.
 
T

Tim Roberts

DanB said:
I didn't try the debug. But in c++ I could drop the debug exe anywhere
on my machine.

**IF** you have statically linked with the C runtime library. If you link
with the DLL CRT, then the EXE will only work on a machine where Visual
Studio has already been installed.
I don't know poop about c#. So is it your opinion that a
c# (release)executable should run on another machine as long as the
appropreate .NET is installed?
Yes.

Might it be an issue of a missing xxx
because I'm running with (dundas) MScharts? All I get is a simple 'has
stopped working' message, not the missing dll message I'd expect if that
were the case. (Would you get that with .NET as you would with native code?)

You should get a cryptic error when you launch the application, but not the
"stopped working" error.
 
D

DanB

Tim said:
**IF** you have statically linked with the C runtime library. If you link
with the DLL CRT, then the EXE will only work on a machine where Visual
Studio has already been installed.

Actually, I never use static linking. On my machine, all my dlls and
mfcx90, sysx, dlls are available, and it works fine. But I'm comfortable
with native, and on 'my' machine this is what I expect, debug or
release. I have never had a problem with release, and I offer patches,
sometimes more than daily, to my clients. I just moved to 9 from 7.1,
the patches are atill flawless, and without a release to back it. The
real impetus to move to 9.0 were the MSCharts and an escape from excel
charting.

Thanks. And I took it one step further. I had the console app run
through enums from System.Windows.Forms.DataVisualization.Charting...
And it works on my wife's machine, dumping the data. The .Form app
doesn't work. (I'm starting to think I have to do a binary search on why
through implementations, gads I hate that thought.)
You should get a cryptic error when you launch the application, but not the
"stopped working" error.

But it did, is 'that it should not' be some kind of clue? I'm going to
hate that I'm spending time on this but can't release it for some
'unknown' reason.... (End of April for me...)

I'm thinking the next proper step is remote debugging so I can see why
it fails. (That should eat some time up...) Does .NET debug dump, like
native, so I can see it on my machine?

Thanks, Dan.
 
D

DanB

Update...

So I learned how to do managed c++ this morning. Even more interesting,
I learned about the new 'reference handles'. % ^

So I got the MSChart up and running in an MFC dialog.

Anyway, said and done, it still crashes on my wifes machine, just
uncomment this line and it won't run. So it has something to do with
'Charting' as other dot net object in my MFC app don't cause a problem.
CWinFormsControl<System::Windows::Forms::DataVisualization::Charting::Chart> theChart;

I even tried uninstalling and reinstalling .NET, it did not fix it...

Best, Dan. :(
 

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