【问题标题】:C#, WinForms ListBox - Programatically setting DisplayMember property - can text be added?C#,WinForms ListBox - 以编程方式设置 DisplayMember 属性 - 可以添加文本吗?
【发布时间】:2015-02-24 07:33:18
【问题描述】:

我在 WinForms 中使用 ListBox。我对DisplayMember 属性有疑问。

如果我理解正确 - 如果我不提供 DisplayMember 属性,则 ListBox 使用对象 ToString() 方法。但是,如果我指定 DisplayMember,那么 ListBox 将显示集合中对象的指定属性。

但是,是否可以添加一些静态文本?

我的意思是,如果我的属性返回一个名字,例如“Dave”,我有没有办法通过使用 DisplayMember 属性或其他方式在这个名字前面加上“名字:Dave”?

我问是因为我正在使用的对象集合来自我无法控制的类 - 因此我无法轻松创建新属性或覆盖 ToString() 方法。

我简单地考虑过扩展类并提供我自己的重写ToString() 方法。但是在我的情况下,我需要能够将父类转换为子类(这是不可能的)。我很快就考虑编写一个静态方法,该方法接受父类作为参数,复制其内容并返回子类,但我只是不知道这是否被认为是干净和最佳实践。

有什么想法吗?

【问题讨论】:

  • 你尝试了什么?给我们一些代码。
  • 除了阅读文档之外,我还没有尝试过任何其他方法。此时真的没有任何代码可以显示或共享。我确实分享了一些其他可能的方法,但表示不确定它们是否是最佳实践。这是一个关于如何在绑定发生后更改 ListBox 中显示的行为的一般问题。

标签: c# winforms listbox


【解决方案1】:

最好的方法是创建一个您将使用的单独的包装对象。您可以使该对象具有通用性,并在遇到相同问题的每个地方使用它。我要做的就是这样。

namespace Demo
{
    using System;

    public class Person
    {
        public string FirstName { get; set;}
        public string LastName { get; set; }
    }

    public class ItemWrapper<T>
    {
        public T Item { get; private set; }
        public string DisplayMember { get; private set; }

        public ItemWrapper(T item, Func<T, string> displayFactory) {
            if (item == null) {
                throw new ArgumentNullException("item");
            }

            if (displayFactory == null) {
                throw new ArgumentNullException("displayFactory");
            }

            this.Item = item;
            this.DisplayMember = displayFactory(item);
        }

        public override string ToString() {
            return this.DisplayMember;
        }

        /// <summary>
        /// This method is just an example and should be removed
        /// </summary>
        public static void Example() {
            var person1 = new Person() { FirstName = "Johny", LastName = "Bravo" };
            var person2 = new Person() { FirstName = "Johny2", LastName = "Bravo" };
            var person3 = new Person() { FirstName = "Johny3", LastName = "Bravo" };

            var item1 = new ItemWrapper<Person>(person1, p => "First Name: " + p.FirstName);
            var item2 = new ItemWrapper<Person>(person2, delegate(Person p) { return "First Name: " + p.FirstName; });
            var item3 = new ItemWrapper<Person>(person3, DisplayFactory);
        }

        private static string DisplayFactory(Person p) {
            return "First Name" + p.FirstName;
        }
    }
}

假设您有一个带有 ListBox 的表单。然后你可以这样使用它:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var p1 = new Person() {FirstName = "Johny", LastName = "Bravo"};
            var p2 = new Person() {FirstName = "Alex", LastName = "Flo"};
            var list = new List<ItemWrapper<Person>>
            {
                new ItemWrapper<Person>(p1, p => p.FirstName),
                new ItemWrapper<Person>(p2, p => p.FirstName)
            };
            var bs = new BindingSource(list, "Item");
            this.listBox1.DataSource = bs;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var person = this.listBox1.SelectedValue as Person;
        }
    }
}

【讨论】:

  • mcl,这很有帮助。在进行一些测试和文档阅读之后,我将有一些后续问题。我对委托或 lambda 表达式没有太多经验,想在接受您的回答之前阅读一些官方文档。
  • 你能给我解释一下var item = new ItemWrapper&lt;Person&gt;(p, p =&gt; "First Name: " + p.FirstName);的语法吗?特别是当我执行Person p = new Person("Dave"); 然后var item = new ItemWrapper&lt;Person&gt;(p, p =&gt; "First Name: " + p.Name); 时收到编译错误,无法在此范围内声明名为 p 的局部变量,因为它会给 p 赋予不同的含义,它已在父级或当前级中使用范围来表示其他东西。如果我将其更改为 var item = new ItemWrapper&lt;Person&gt;(p, Person =&gt; "First Name: " + p.Name); 它可以工作,但我不明白为什么。
  • 好吧,我错了,那是因为我在没有实际编译的情况下编写了脚本。我将编辑我的答案。
  • Lambda 是内联定义和使用的方法。这就像定义一个方法并将它(该方法不是它的返回值)传递给某个消费者。如需更好的解释,请查看msdn.microsoft.com/en-us/library/bb397687.aspx
  • 再次感谢,从阅读和您的示例/说明中学到了很多东西。对于额外的信用 - 我可以使用myListBox.ValueMember 以便myListBox.SelectedItem 返回的项目是T?在我的测试中,当我使用一个集合并将ItemWrapper&lt;Person&gt; 的对象添加到集合中时,即使我设置了myListBox.ValueMember = 'Item'(包含T 的ItemWrapper 类的属性),我仍然返回一个ItemWrapper&lt;Person&gt; 对象。我可以做一些事情只返回 Person 对象吗?
猜你喜欢
  • 2021-04-22
  • 2011-02-24
  • 1970-01-01
  • 2018-04-14
  • 2012-08-20
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
  • 2017-08-05
相关资源
最近更新 更多