Here is an example of a simple dropdown list to display blocks. You have to make sure that the BlockTableRecord has a preview icon either by opening the Design Center or using the BLOCKICON command.
This is in no way complete and not a good library component, but it is a quick example of what can be done.
Your code works in a modal dialog but will probably crash AutoCAD or fail in some other way if you tried to use it in a modeless context (e.g., palette or a modeless form). You can't store BlockTableRecords in a control's items collections if you want the control to be usable in a modeless context.
I also don't like the idea of dedicated controls for things like block icons. They are just images. For example, my own controls are not dedicated to very specific AutoCAD objects, because there's quite a few cases where similar control functionality is needed (image and text), and I would not want to have to write a dedicated control for each specific use, so I use a generic combo box with support for an image/icon, which is easy to adapt to specific uses like block icons, linetype images, hatch patterns, etc. You can find lots of them on CodeProject.com.
Why would you not want to have a dedicated control for this?Because a dedicated control is not necessary, and doesn't promote separation of UI from business logic.
I'm sure there are generic controls out there that you can put images and text into them in all sorts of flexible ways, but would it not be easier to have a control that is designed to draw the Block, Linetype, or Layer exactly the way it should be?
Where do you put the implementation to gather up all of the images and text for the Symbol Table Record and give it to your generic control in just the right formatting?
Your code works in a modal dialog but will probably crash AutoCAD or fail in some other way if you tried to use it in a modeless context (e.g., palette or a modeless form). You can't store BlockTableRecords in a control's items collections if you want the control to be usable in a modeless context.
That's why this is a simple example.
I don't think I can agree that designing a control that can't be used on anything but a model form qualifies as 'simple'.
I don't think I can agree that designing a control that can't be used on anything but a model form qualifies as 'simple'.
Well, simple meaning that you just put it on a modal form, give it some BlockTableRecord or LayerTableRecord objects and it just works. Creating a control like this that would work in a modeless context would require some complex logic to monitor the database and update the controls as the table records changed or update the list when records were added or removed, or the active document changed. That implementation would be anything but simple.
I guess we just disagree on the definition of simple.
Maybe I should have used the word easy. To get something done quickly, using myBlockComboBox.Items.Add(someBlockTableRecord) would be a lot easier than going out to CodeProject.com and finding some complicated control that somebody has designed to be very powerful and flexible, or purchasing a commercial product. Then, reading all about how it works and what it does before creating a code layer for separating the logic of displaying the information on the control. And finally, creating a data binding between that control and some object which represents the data contained in the table records.
But I guess everybody's definition of easy is different.
I guess we just disagree on the definition of simple.
Maybe I should have used the word easy. To get something done quickly, using myBlockComboBox.Items.Add(someBlockTableRecord) would be a lot easier than going out to CodeProject.com and finding some complicated control that somebody has designed to be very powerful and flexible, or purchasing a commercial product. Then, reading all about how it works and what it does before creating a code layer for separating the logic of displaying the information on the control. And finally, creating a data binding between that control and some object which represents the data contained in the table records.
But I guess everybody's definition of easy is different.
Perhaps this little exercise might help you understand.
Perhaps this little exercise might help you understand.
Yes. I understand now. Can you show me how to make it display the preview image?
Here is a SIMPLE layer list. I would like to be able to make the controls inside the dropdown list be clickable and raise events, but that has proven to be pretty difficult in WinForms. A piece-of-cake in WPF, from what I've read.
(Yes, the icons are crap. I found them on the 'net. Feel free to replace them.)
Making the items clickable essentially requires that you handle the mouse events and use the location to determine what item the mouse was over, there's not much more to it than that. As long as you know the size of the images, and each one's origin in control coordinates, it shouldn't be hard to figure out which one was clicked.
Another thing you need to correct is that your custom combobox control
handles the DrawItem event, which is not how derived types implement
custom drawing. Events are meant to be handled by other consumers but
not by derived types. Derived types should override the corresponding
virtual member, which in this case is the OnDrawItem() method.
Making the items clickable essentially requires that you handle the mouse events and use the location to determine what item the mouse was over, there's not much more to it than that. As long as you know the size of the images, and each one's origin in control coordinates, it shouldn't be hard to figure out which one was clicked.
Yes, That was my idea too. I have tried it in a number of exhaustive ways. It turns out that the mouse events are only raised for the control when it is rolled up and there are no mouse events when the list is dropped down.
Are you sure? From looking at the framework code, it would appear that OnMouseDown(), OnMouseMove(), etc. are being called.
Am I missing something which is usually the case but for a combo box would'nt you just use a SelectionChange Event index or value?I see what your talking about.
Are you sure? From looking at the framework code, it would appear that OnMouseDown(), OnMouseMove(), etc. are being called.
Where are you looking in the framework?
I put this in the control:Code - C#: [Select]
protected override void OnMouseDown(MouseEventArgs e) { Debug.WriteLine(e.Location); base.OnMouseDown(e); }
It does not return a point when clicking on a dropdown list item. Are you seeing different behavior?
That is very cool, Jeff. I was about to make a ColorComboBox as well, but I got off track.
If you bind it to Autodesk.AutoCAD.Colors.Color, your ValueMember would be ColorValue and the DisplayMember property would be ColorName. It should work for ACI colors, True Color, and Color Book colors.
Another issue I noticed is if another control event, or just changing the color value of the object in the bound collection that is the SelectedValue or current item in combobox the color would update 1, 2, 3, or sometimes 4 seconds later but probably is a method that can be used to update it immediately.Not sure if best way but ComboBox.Refresh() seems to work