Why overriden ToString() do not return what I want when item added to ComboBox?

c#, combobox, overriding, tostring

Solution

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

There's an `internal` class `System.Windows.Forms.Formatter` doing some stuff. It eventually creates a converter. This is roughly equivalent to saying:

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

where `tc1` is the `TestContol` from your question. Now, had we used the `TestClass` `tcl` which doesn't implement any interfaces, this would have given us a converter which would eventually call `ToString()`.

But in this example we use `tc1`, and it is a `System.ComponentModel.IComponent`. Our `conv` therefore becomes a `System.ComponentModel.ComponentConverter`. It uses the `Site` of the `IComponent`. When we say:

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

and the `Site` is null, we get the empty string `""` you saw in your combo box. Had there been a `Site` it would have used its `Name` instead.

To demonstrate that, put the following into your `TestControl` instance constructor:

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'S YOUR TEXT
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public object GetService(Type serviceType)
    {
        return null;
    }
}

Problem

``` 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 form loaded, I see combobox has two items with empty names, instead of "asd" :/ But this work if I override ToString() in common 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 combobox "bla bla bla"

Original source