【问题标题】:Why overriden ToString() do not return what I want when item added to ComboBox?为什么在将项目添加到 ComboBox 时覆盖 ToString() 不返回我想要的内容?
【发布时间】:2013-04-08 18:00:21
【问题描述】:
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);
    }
}

加载表单时,我看到组合框有两个名称为空的项目,而不是“asd”:/
但是,如果我在公共类中覆盖 ToString(),而不是从任何东西派生,则此方法有效:

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);
    }
}

之后我在组合框中看到“bla bla bla”

【问题讨论】:

  • 你在哪里打电话ToString()看这个网站的例子/解释msdn.microsoft.com/en-us/library/ms173154%28VS.80%29.aspx
  • 添加项目时应该由组合框调用,就像它适用于普通类一样
  • 你可以做一个Protected override on one of the comboboxes properties, accessing it from the e.argument(s) params?
  • 对不起,我不明白你在说什么:(
  • 我看到了同样的行为。看起来System.Windows.Forms.ComboBox 的内部代码仅对不是System.Windows.Forms.UserControl 的对象使用ToString 覆盖。

标签: c# combobox overriding tostring


【解决方案1】:

在您的控件中创建一个属性并将组合框的 DisplayMember 映射到该属性,它应该可以工作。

【讨论】:

  • 谢谢,我尝试过...但是由于奇怪的原因,当我在属性列表中单击选择 DisplayingMember 时,它是空的,所以没有什么可以选择
  • 哦,我只需要在那里输入,而不是选择。现在可以了,谢谢!
  • 哦哦哦,但是 CheckedListBox 怎么办? :D 没有 DisplayingMember,但同样的问题
  • 奇怪,我在 PropertyList 中没有看到这个
【解决方案2】:

我试图理解源代码(!)。这不是对ToString() 的简单调用。

有一个 internalSystem.Windows.Forms.Formatter 在做一些事情。它最终创建了一个转换器。这大致相当于说:

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

tc1 是您问题中的TestContol。现在,如果我们使用没有实现任何接口的TestClass tcl,这将给我们一个最终调用ToString() 的转换器。

但是在这个例子中我们使用tc1,它是一个System.ComponentModel.IComponent。我们的conv 因此变成了System.ComponentModel.ComponentConverter。它使用IComponentSite。当我们说:

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

Site 为空,我们得到您在组合框中看到的空字符串""。如果有Site,它会使用它的Name

为了证明这一点,请将以下内容放入您的 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.
}

DummySite 类似于:

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;
    }
}

【讨论】:

  • 感谢您对此的解释。您的答案值得接受,因为它确实回答了“为什么要覆盖 ToString() ...”
  • 啊,我想这就是为什么他们在Component.ToStringdocumentation 中说它不应该被覆盖。
  • 感谢您的水平和理解。感谢您富有洞察力的回答!
【解决方案3】:

使用comboBox1.Items.Add(tc1.ToString()); 而不是comboBox1.Items.Add(tcl);

【讨论】:

  • 我有点希望能够将 comboBox1.SelectedItem 转换回类实例...... -1 不是我的:P 仍然感谢您的回答,如果新手提出问题,它会有所帮助
【解决方案4】:

这对我有用:

comboBox1.FormattingEnabled = false

【讨论】:

    【解决方案5】:

    在您的UserControl 中,添加一个属性,例如将其命名为FriendlyName,这样

    namespace project
    {
       public partial class CustomUserControl : UserControl
       {
          public CustomUserControl()
          {
             InitializeComponent();
          }
    
          public String FriendlyName { get => "Custom name"; }
       }
    }
    

    然后将你的ComboBoxDisplayMember 属性设置为“FriendlyName”,这样

    myComboBox.DisplayMember = "FriendlyName";
    

    对我来说,这是一个非常干净的解决方案,直觉告诉我这是预期的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-19
      • 1970-01-01
      相关资源
      最近更新 更多