Display specified text for listbox items - c#

I have a list that contains custom objects. These objects have different properties, and I have ~100 of them. I want to create a list of them in a listbox, but the listbox displays only
MyNamespace.MyClass
MyNamespace.MyClass
MyNamespace.MyClass
MyNamespace.MyClass
...
Is it possible to make the listbox display a certain value for each item? Lets say my objects have an ID string value. Can I display the ID for each item without discarding my objects' other properties?
I currently fill the listbox this way:
lbox.Items.Clear();
lbox.Items.AddRange(list.ToArray());

Set the DisplayMember to the property of your class that you'd like the user to see.
lbox.Items.Clear();
lbox.Items.AddRange(list.ToArray());
lbox.DisplayMember = "ID"; // ID is a public property in MyClass

Lets say you MyClass looks like this:
public class MyClass
{
public int Id { get; set; }
}
There are two options available.
You can use DataBinding for that.
Set the DisplayMember to the propertie of your MyClass which you would like to display
lbox.DisplayMember = "Id";
Set the items using the DataSource propertie of your ListBox
lbox.DataSource = list.ToArray();
You can simple override the ToString method of your MyClass object and return the text you would like to display.
Override the ToString method of your MyClass
public class MyClass
{
public int Id { get; set; }
public override string ToString()
{
return Id.ToString();
}
}
Set the items the same way as you mentioned
lbox.Items.AddRange(list.ToArray());
More Information
MSDN: ListControl.DisplayMember Property
MSDN: Object.ToString Method

Without discarding the object you can attach the object to the tag after.
list.ToList().ForEach(item => lbox.Items.Add(new ListItem(item.ID){Tag = item});
then to retreive it :
var myitem = ((ListItem)lbox.SelectedItem).Tag as MyClass;

Try using Linq.
lbox.Items.AddRange(list.Select(x => x.ID).ToArray());
Where ID is a property with the value you want to show.
You can also override ToString() in the class.

Related

Displaying individual element of objects in arraylist on combobox

I have an object with 2 element fields for C#, and I have inserted them into an arraylist. I am trying to get them to display on the combobox.
This is what I currently have
ArrayList mylist = new ArrayList();
mylist.Add(new myobject("name1", "value1"));
mylist.Add(new myobject("name2", "value2"))
mylist.Add(new myobject("name3", "value3"));
ComboBox1.ItemsSource = drinksArray;
The following code would just display 3 elements which are "ClassName.myobject" for my combobox.
I am trying to get it to display "name1", "name2" and "name3".
I have a getName() method for my object but I do not know how to implement it into the combobox.
You have to set the ComboBox.DisplayMemberPath.
https://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.displaymemberpath(v=vs.110).aspx
Call the getName() method in the ToString() method of the myobject class:
public class myobject
{
...
public override string ToString()
{
return getName();
}
}
Or set the DisplayMemberPath to the name of a public property of the myobject class that returns the value you want to display as suggested by #zambonee:
ComboBox1.DisplayMemberPath = "Name";
I would add a readonly property to your myobject class that returns getName(), then set DisplayMemberPath on the ComboBox to the name of that property.
If the name can ever change, you will want to implement INotifyPropertyChange and raise its event for the property whenever the value should be updated.

Deriving from ComboBox

I need to derive a class from ComboBox and change its Items property. Here is my code:
public class MyComboBox2 : ComboBox
{
private MyObjectCollection MyItems;
public MyComboBox2()
{
MyItems = new MyObjectCollection(this);
}
//new public ComboBox.ObjectCollection Items
new public MyObjectCollection Items
{
get {
return MyItems;
}
}
}
public class MyObjectCollection : ComboBox.ObjectCollection
{
public MyObjectCollection(ComboBox Owner) : base(Owner)
{
}
new public int Add(Object j)
{
base.Add(j);
return 0;
}
}
As you can see, I am creating a new class MyComboBox2 derived from ComboBox. This class is supposed to have a new Items property, which would be of type MyObjectCollection rather than ComboBox.ObjectCollection. I have a comboBox called myComboBox21 on the form of type MyComboBox2. When I want to add a new object to my ComboBox, I would execute code like this: myComboBox21.Items.Add("text");
In this case, I end up executing the Add method of MyObjectCollection that I implemented myself. However, the ComboBox on the form does not end up containing value 'text'. I am attaching screenshot of debugger showing ComboBox values. MyComboBox21 contains Items Property (which does contain "text", as shown in screenshot "2.png"), and it contains base.Items (which does not contain "text" as shown in "1.png"). So, apparently, MyComboBox21 contains its own Items property (which I can insert to), and its base class's Items property, which gets displayed in the Windows Form. What can I do so that I can successfully add to comboBox with my own method? Since my ComboBox has 2 Items properties, can I specify which Items property's values should be shown in ComboBox?
Just by looking very quickly on the code:
The original Item index is declared as
virtual Object this[int index] {...}
Does the new keyword maybe be exchanged by override in your implementation in order to make the runtime pick the intended code?

PropertyGrid with possibly-null List

I'm using a PropertyGrid class to edit objects within my application. These are the relevant classes (or rather, simplifications thereof):
public class Inner
{
public int A { get; set; }
public string B { get; set; }
}
public class Outer
{
public List<Inner> InnerData { get; set; }
public int Id { get; set; }
}
I will set an object of type Outer as the SelectedObject field of my property grid. The problem comes when an Outer object has it's InnerData property set to null. Null is considered an acceptable value for this property as the InnerData property represents "optional" data, and not having it specified is not the same thing as specifying an empty list. Ideally I'd like a user to be able to replace a null InnerData property with a real value by specifying the components of the new list, modify an existing non-null InnerData value, and replace an existing InnerData value with null.
Anybody know how to make this happen?
Have a look at creating a UITypeEditor, i think that if you use an editor you will have more control over the list and be able to tell if the current value is null and if so you can have the editor show a blank grid or something where list items can be added or removed, you could also add a checkbox to tell the editor to return null again and set null on the property, the editor is basically a WinForm so you can do almost anything in it.
internal class GenericTypeEditor : UITypeEditor
{
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
IWindowsFormsEditorService winFormEditorSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
using (MyForm editorForm = new MyForm())
{
if (winFormEditorSvc.ShowDialog(editorForm) == System.Windows.Forms.DialogResult.OK)
value = editorForm.ReturnObject;
}
return value; //this can be null if you wish
}
public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
}
Then just set the attribute on your property
[EditorAttribute(typeof(GenericTypeEditor), typeof(System.Drawing.Design.UITypeEditor))]
public List<Inner> InnerData { get; set; }
This article helped me in the past, maybe it is of help to you:
http://msdn.microsoft.com/en-us/library/ms171840(v=vs.100).aspx
The property grid tries to add new Inner items to the InnerData object, but since you have not initialized it, the property grid has no where to save the added items. You need a constructor in Outter that will initialize InnerData just as a new List. You dont have to put any items into it, the user can do this at runtime, and can empty them back out as well, but the InnerData list Object needs to be initialized.
If you just want an Inner as a property, add System.ComponentModel to your usings and try this
[TypeConverter(typeof(ExpandableTypeConverter))]
public Inner DefaultInner { get; set; }
This will make your object expandable in the property grid so that you can set its nested properties
Try handling the PropertyGrid.SelectedGridItemChanged event:
private void propertyGrid1_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
{
if ((e.NewSelection.Label == "InnerData") && (_outter.InnerData == null)) _outter.InnerData = new List<Inner>();
}
Then whenever the InnerData item is selected, if the collection is null, its initialized to a new list.

Override the Add method of a ComboBox

Is there a way to override the Add() method of Combobx?
The reason I ask this is that I want to Add the class objects to my combbox but for display I want it to show the Name of my objects.
so for example: combbox.Items.Add(myClassObject)
but what we actually see in the combbobx as the user will show as myClassObject.Name
If I right understood your request, you can do that using the binding:
Pseudocode:
comboBox.DataSource = collectionOfData;
comboBox.DisplayMember = "Name";
The data will be added to combo but visualized will be the Name property of the "data".
This all done using DisplayMember Property.
Because ComboBox uses ToString() method of object which is added in Items collections to display on the UI, so override ToString of myClassObject to return whatever you want, it is simple:
class myClassObject
{
public override string ToString()
{
return "whatever you want";
}
}
With this way you do not touch ComboBox Control
You can develop extension Method
public static class Extension
{
public static void Add(this ComboBox, myClassObject value)
{
...
}
}
Create a new control that extends combobox control. Then override Add method.

Using custom objects for (CheckedListBox).Items.Add()

When I add an item to the CheckedListBox list box I also want to store a reference to another object. I tried adding a new instance of this object to the CheckedListBox.
public class CheckedListBoxExtention : CheckedListBox
{
private ReferenceItem _referenceItem;
public ReferenceItem storedItem
{
get { return _referenceItem; }
set { _referenceItem = value; }
}
public CheckedListBoxExtention(ReferenceItem storedItem)
{
_referenceItem = storedItem;
}
}
This works in that later when I foreach though the items in CheckedListBox I have a reference to the _referenceItem object. However, when I add items like this, CheckedListBox shows up as blank (the list in the GUI itself). So I am trying to find a way to override the item text or something like that.
This is the code I used to fix the problem
class ReferenceItemWrapper
{
private ReferenceItem _item;
public ReferenceItemWrapper(ReferenceItem item)
{
_item = item;
}
public ReferenceItem getItem
{get {return _item;}}
public override string ToString()
{
return _item.ToString();
}
}
I am a bit new to wrappers. Why exactly did it work after it was wrapped when it did not work when I added the ReferenceItem directly to the CheckedListBox?
The CheckedListBox uses the ToString method of the objects in the list to populate the captions in the box. Rather than extend the CheckedListBox, just create a wrapper class that lets you store both your reference and a caption, and implements a ToString method which returns your caption. Just create one of your wrapper objects, stick the text in it, stick your reference in it, then add the wrapper object to the list box.

Categories

Resources