【问题标题】:How to set Display member of combobox to a string nested within list of objects?如何将组合框的显示成员设置为嵌套在对象列表中的字符串?
【发布时间】:2017-11-17 00:32:11
【问题描述】:

我应该补充一点,对象是在第 3 方.dll 中管理的,所以我的代码中实际上没有对象定义。

我有一个List<Foo>,我将其设置为ComboBox 的数据源。

假设 Foo 对象看起来像:

public class Foo
{
    Settings setting;
    public Foo(string title)
    {
        setting = new Settings();
        setting.Title = title;
    }
    //lots of other objects and values
}

public class Settings
{
    public Settings()
    {
    }
    public String Title {get; set;}
    //lot of other information
}

我在这里的实现:

private void LoadList() //edited for SO testing sake, this is called in constructor
                        //of the form
{
    var foo = new List<Foo> {
        new Foo("MASTER 5DAY"),
        new Foo("5 Day Reminder"),
        new Foo("MASTER Welcome"),
        new Foo("Welcome Letter")
    };

    var master = foo.Where(x => x.Settings.Title.Contains("MASTER")).ToList();
    this.ddlMasterType = master; //This is the combobox

    //Now here I would want the display member of the ddl to be the title of each Foo object
    //But I need the value member to still contain all the other information of the Foo object
}

正如我的实现 cmets 中列出的那样,我想在打开下拉列表时显示 Foo.Settings.Title,但稍后选择它时仍然需要完整的对象。

【问题讨论】:

  • 这是winforms吗? WPF? UWP? ASP.NET?
  • 糟糕,它是 winforms。

标签: c# winforms drop-down-menu combobox


【解决方案1】:

你有点吃不消了。如果你设置comboBox1.DataSource = foo;,通常你会设置comboBox1.DisplayMember = "SomePropertyName";,你会很好。但在您的情况下,您需要的是路径,而不是名称,comboBox1.DisplayMember = "settings.Title"; 将被忽略。

如果您可以更改Foo,您只需将只读包装属性添加到Foo

public String Title { get { return settings.Title; } }

但是你不能改变Foo

所以这里有一个选项:编写一个您可以更改的包装类。

public class FooCarrier
{
    public Foo Foo { get; set; }
    public String Title { get { return Foo.settings.Title; } }
}

...

public Form1()
{
    InitializeComponent();

    comboBox1.DataSource = new List<Foo> {
        new Foo("MASTER 5DAY"),
        new Foo("5 Day Reminder"),
        new Foo("MASTER Welcome"),
        new Foo("Welcome Letter")
    }.Select(f => new FooCarrier { Foo = f }).ToList();

    comboBox1.DisplayMember = "Title";
    comboBox1.ValueMember = "Foo";

    comboBox1.SelectedIndexChanged += ComboBox1_SelectedIndexChanged;
}

private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    //  comboBox1.SelectedItem will be FooCarrier, but since we set 
    //  ValueMember to "Foo", SelectedValue is the Foo property of the selected
    //  item. 
    Foo selectedFoo = (Foo)comboBox1.SelectedValue;
}

您也可以省略 FooCarrier 并使用匿名类型:

comboBox1.DataSource = new List<Foo> {
    new Foo("MASTER 5DAY"),
    new Foo("5 Day Reminder"),
    new Foo("MASTER Welcome"),
    new Foo("Welcome Letter")
}.Select(f => new { Foo = f, Title = f.Settings.Title }).ToList();

SelectedValue 仍然是Foo,因此您永远不需要转换为实际的项目类型。

【讨论】:

  • 工作就像一个魅力。包装我的包装类,谁知道!?
  • 听说你喜欢包装类。
  • 请注意,包装类使得在组合框上使用 SelectedItem 设置器变得更加困难。您需要将 SelectedItem 设置为包装类的实例,而不是原始数据。
  • @Gooseberry 但是,SelectedValue 设置器仍然有效,只要 ValueMember 设置得当。
  • @Gooseberry 是的,在这种情况下,非匿名 FooCarrier 解决方案将是首选。
【解决方案2】:

您可以将组合框的数据上下文设置为整个列表,并覆盖 Foo 类的 ToString 方法以准确显示您想要的内容。

    public override string ToString()
    {
        return /*information you want to display, for example*/setting.Title;
    }

【讨论】:

  • 我无权访问Foo 类。
【解决方案3】:

尝试将 displayMember 设置为 Title 属性:

  master.DataSource = fooList;
  master.DisplayMember = "Name"

使用以下方法获取整个对象:

  Foo foo = (Foo)master.SelectedItem;

  Foo foo = master.SelectedItem as Foo;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    相关资源
    最近更新 更多