Why does overriding ToString () not return what I want when an item is added to a ComboBox?

public partial class TestConrol : UserControl { public TestConrol() { InitializeComponent(); } public override string ToString() { return "asd"; } } public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { TestConrol tc1 = new TestConrol(); comboBox1.Items.Add(tc1); TestConrol tc2 = new TestConrol(); comboBox1.Items.Add(tc2); } } 

When the form is loaded, I see that the combobox has two elements with empty names, instead of "asd": /
But this work, if I redefine ToString () in a general class, not derived from anything:

 public class TestClass { public override string ToString() { return "bla bla bla"; } } public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { TestClass tcl = new TestClass(); comboBox1.Items.Add(tcl); } } 

After that I see in the combobox "bla bla bla"

+4
source share
4 answers

I tried to understand the source code (!). This is not a simple call to ToString() .

There a internal class System.Windows.Forms.Formatter does some things. As a result, he creates a converter. This is roughly equivalent to:

 var conv = System.ComponentModel.TypeDescriptor.GetConverter(tc1.GetType()); 

where tc1 is TestContol from your question. Now, if we used TestClass tcl , which does not implement any interfaces, this would give us a converter that will eventually call ToString() .

But in this example, we use tc1 , and this is System.ComponentModel.IComponent . Therefore, our conv becomes a System.ComponentModel.ComponentConverter . It uses Site for IComponent . When we speak:

 string result = conv.ConvertTo(tc1, typeof(string)); 

and Site is null, we get the empty string "" that you saw in your combo box. If there was a Site , he would use his Name .

To demonstrate this, put the following in your TestControl instance TestControl :

 public TestConrol() { InitializeComponent(); Site = new DummySite(); // note: Site is public, so you can also // write to it from outside the class. // It is also virtual, so you can override // its getter and setter. } 

where DummySite is something like:

 class DummySite : ISite { public IComponent Component { get { throw new NotImplementedException(); } } public IContainer Container { get { throw new NotImplementedException(); } } public bool DesignMode { get { throw new NotImplementedException(); } } public string Name { get { return "asd"; // HERE YOUR TEXT } set { throw new NotImplementedException(); } } public object GetService(Type serviceType) { return null; } } 
+3
source

Create a property in which you are managing, and map the DisplayMember of this character to this property, it should work.

+5
source

Use comboBox1.Items.Add(tc1.ToString()); instead of comboBox1.Items.Add(tcl);

+1
source

This worked for me:

 comboBox1.FormattingEnabled = false 
0
source

All Articles