I've created an owner-draw user control that inherits from ComboBox.
The control stores specialized items, but the Items collection still accepts and returns items of type Object. Any tips on the best way to override this collection to be type-safe?
About the only way I can think of is to create my own collection class. The class wouldn't be a true collection--it would take an ObjectCollection as an argument to the constructor and simply extend the methods of that to.
The user control would pass the original Items collection to the constructor of the new class. And then override the Items property to return an instance of the new class instead.
This seems somewhat convoluted. Is there a better way?
You could do it a couple of different ways. First off, I'm a little confused about you creating a "user control" that inherits from ComboBox. You can create a custom control that inherits from ComboBox, but you cannot inherit from both UserControl (which is the usual definition of a "user control") and ComboBox.
If you define a true UserControl derivative, this gets a little easier. A UserControl, like I said, can't be a ComboBox, but it can have a ComboBox. So, you can drop and Dock a ComboBox to your UserControl surface, and then re-implement any properties you need to be able to use, such as Items. This will allow you to re-create Items as a collection of your choice, probably a strongly-typed List. The only problem will be knowing exactly what you'll want to re-implement; there's a lot of useful properties of a ComboBox that you won't be able to access in the Designer or in code unless you implement a "pass-through" property that modified the contained ComboBox within your UserControl.
If you inherit directly from ComboBox, it gets a little tricker in some ways, easier in others. You can hide the base class implementation of Items by defining your own and using the new keyword. You can change the visibility, type and other modifiers when you do this. This will prevent code that deals with your control as a CustomComboBox (or whatever you name it) from using the object array on the base class; they have to use your strongly-typed Items array. Your new property can still access the old one (which it will need to in order to make it work). You also get all the other public properties of a ComboBox for free; you only have to reimplement what you want to change. However, referring to your custom ComboBox as any base class will cause the runtime to use the version of Items that is valid for that class; that is, the object array, not your strongly-typed one.
Related
What's the elegant way of exposing ItemContainerGenerator from custom control?
I have ItemsSource property on my custom control and I would like to access UIElement corresponding to the bound item outside of it.
I don't have access to the ItemsControl nor ItemsContainerGenerator outside of my control. Should I expose ItemsControl or ItemContainerGenerator as a property, or maybe add a method for retrieving the UIElement?
I need to show the popup near the selected item. Maybe the popup should be a part of the control then I wouldn't have to do this?
If you want to be able to access the entire child ItemsControl, create a public read-only property that returns it.
If you only want to expose the ItemContainerGenerator, create a read-only property that returns it, e.g.:
public ChildItemContainerGenerator => childControl.ItemContainerGenerator;
If it makes no sense to expose the entire ItemContainerGenerator, create a public method that uses the ItemContainerGenerator internally to perform whatever you want to.
Which option to choose all comes down to your requirements actually.
I have a class that I will be using to bind to a grid. The grid columns will correspond to the public properties of my class, all of which are decimal?.
Right now, in order to display all of the required info, my class includes around 30 properties. I created these properties based off of a list that might change in the future.
It seems that hard-coding the properties and updating the class after any change is not the right way to do this but I am not sure how to create "properties" at run time (I have access to the list) and have them bind to the grid (Infragistics xamDataGrid in this case).
Any suggestions on what I can use?
ExpandoObjects allow dynamic assignment of properties (which are even bindable as the class implements INotifyPropertyChanged), if that helps. They are slower though in terms of performance.
I am using a property grid to edit, amongst other things, a collection of items:
The default behavior for a collection provides a + button to edit each member of the array.
I am using a Form to edit this field, which is already wired up but I want to remove the ability for the user to edit the array by using the 'expander'
So it would look like this:
UPDATE1: made ProductIds an IList property instead of int[ ]
Now does this:
-----------------!
UPDATE2: made ProductIds a custom class, eg
MyWrappedCollection : IEnumerable<int>
so it now looks like this:
Sure, it still shows [+] but it doesnt expand to anything (ie disappears when you click it)
The attribute that controls whether a property is expandable or not is it's TypeConverter. The ExpandableObjectConverter is a built in class that provides the ability to expand a property and look at it's own. I am guessing by default that arrays and collections use this converter to display what is in them.
You can write your own TypeConverter which does not inherit from ExpandableObjectConverter and set it as an attribute on your property to remove the +.
By default for a collection, it uses [...] method. May be you could use a collection (For example a List) instead of an array.
By the way, any specific reason you use arrays?
You need to implement and apply a UITypeEdtitor. See How to: Implement a UI Type Editor
Override GetEditStyle of your UITypeEditor to return Modal
I have a listbox which has all the names for a list of "Gesture" objects I have.
I want to make it so if I double click on a ListBox item I can then do something with its associated Gesture instance. What is the best way in C# to associate a ListBox item with an instance of a class of mine?
I'm using WPF.
I am not sure whether I understood your question, but typically, the best way to "associate a ListBox item with an instance of a class" is to simply put the instance itself into the ListBox. You only have to take care of what is displayed for the items. If you have a simple scenario, it might be sufficient to just override the class' ToString() method. If you need a more sophisticated display, you should consider to create DataTemplates for your classes.
If you do not have access to your Gesture classes, you should create a wrapper class for them (something like a ViewModel) and do the proposed adjustments for this wrapper class.
Moreover, you should make all those classes implement a common interface or base class, so that you can safely cast the currently selected item without adding an if-statement for every type that might be in the ListBox.
So what I am trying to do is to have a set UI with certain controls, and I want to have some class instance to fill in the values.
For instance:
Classes that can populate the UI:
Sharpen, Blur, Smear, ... : FilterBase
So whenever the user creates an instances of the above classes, I want to automatically fetch the values based on the UI controls, by using the class instance.
The UI has items like:
.Name (TextBox)
.Amount (NumericUpDown)
.Decay (NumericUpDown)
So if the current instance is s = new Sharpen(), I want to get s.Name to fill out UI.Name.
How do I do this in the best possible way? Elegancy, clarity, performance wise, etc.
I am gonna use reflection, but how do I store the instance of the object (Sharpen, ...) and be type safe? Should I use an System.Object instead? Or T?
public partial class ParamsUI
{
T CurrentFilter (?)
...
}
Also if I use T, how will I know what to cast it to?
Is there a better way?
Since this is using Windows Forms, the most flexible option would probably be to just use the Windows Forms PropertyGrid directly.
You can do a lot of work to customize the look and feel of this. See Getting the Most Out of the .NET Framework PropertyGrid Control for details.
Edit:
If you want to have a very flexible, easy option, and WPF is an option (hosted within an ElementHost), you could consider using WPF.
With this, you could host a UserControl containing nothing but a resource dictionary and a ContentControl.
You could then make a custom XAML file for each item you want to edit, and setup a data template in the resources specifying the mapping of which user control (xaml) to use for each element you want to edit. You can then just set the element to the user control's "DataContext" in code, and it will automatically wire everything up and "just work".