【问题标题】:Windows Forms Databinding DisplayMember a Custom Class's Child PropertyWindows 窗体数据绑定 DisplayMember 自定义类子属性
【发布时间】:2009-01-13 20:24:37
【问题描述】:

我正在尝试将 Windows 窗体项目中我的 ListBox 的 DisplayMember 属性设置为我绑定到的通用列表内的嵌套类的属性。

这是一个简单的例子:

 public class Security
{
    public int SecurityId { get; set;}
    public SecurityInfo Info { get; set;}
}
public class SecurityInfo
{        
    public string Description { get; set;}
}
//........//
public void DoIt()
{
    List<Security> securities = new List<Security>();
    //add securities to list
    lstSecurities.DataSource = securities;
    lstSecurities.DisplayMember = "Info.Description";
}

这可以通过一个简单的 ListBox 实现吗,还是我必须创建一个子类 ListBox 来处理这个问题?

编辑:

我试图不修改这些类,因为它们是通过 WSDL 文档生成的。

【问题讨论】:

    标签: .net winforms data-binding


    【解决方案1】:

    不,大多数 winforms 绑定不支持这样的子属性。

    您可以直接使用自定义类型描述符来完成此操作,但这是大量的工作,不值得。

    检查生成的代码;它应该(使用任何最新版本的工具)是partial class;这意味着您可以在 second 类文件中添加额外的成员,因此您不会破坏 wsdl 生成的代码 - 即

    namespace MyWsdlNamespace {
        partial class MyClass {
            public string InfoDescription {
                get { return Info.Description; }
                // and a set if you want
            }
        }
    }
    

    您现在应该可以相当轻松地绑定到“InfoDescription”了。

    【讨论】:

    • “不,大多数 winforms 绑定不支持这样的子属性。”自从发表这篇文章以来,情况是否发生了变化?我知道,至少在绑定到控件时,可以按如下方式绑定到子属性:txtDesc.DataBindings.Add("Text", new BindingSource(security, null), "Info.Description");
    【解决方案2】:

    您可以添加一个映射到 Info.Description 的新属性。

    类似这样的:

    public string InfoDescription
    {
      get { return Info.Description; }
      set { Info.Description = value; }
    }
    

    这会奏效。但我认为你的例子也应该有效

    【讨论】:

      【解决方案3】:

      我知道已经发布了几个可能对您有用的答案,而且这个问题已经存在 3 年了,但我想添加另一个选项,因为我在与实体框架中的对象进行数据绑定时遇到了这个问题。

      我正在绑定到一个 ListBox,但想显示来自子对象的文本。我所做的只是处理ListBox.Format 事件,并更改ListControlConvertEventArgs.Value。我可以得到我的子对象,因为我为 ListBox 选择的 DisplayMember 是父对象本身,它可以在事件中由ListControlConvertEventArgs.ListItem 访问。

      例如,ListBox 被数据绑定到具有 objA 列表的绑定源。 objA 具有子对象 objB 的属性。 ListBox 的 DisplayMember(在设计时设置)是 objB。但是,由于ToString() 方法没有返回我想要的objB,我处理ListBox 的Format 事件并将e.ValueeListControlConvertEventArgs)设置为我正在寻找的对象:

      CType(e.ListItem, objA).objB.DisplayText
      

      【讨论】:

      • 虽然公认的答案很好,但这要好得多。对于那些对他所说的内容感到困惑的人...这是您在ListBox.Format event method 中放置的代码示例:e.Value = ((Loan)e.ListItem).Resource.Title; Loan 是我的自定义类,我将BindingList&lt;Loan&gt; 分配给我的ListBox.DataSource
      【解决方案4】:

      只需覆盖 SecurityInfo ToString 方法以返回描述并执行:

      lstSecurities.DisplayMember = "Info";
      

      如果您无法修改类,最好的选择是使用 ViewModel。一个接受 Security 并公开您要查看的属性的类。

      【讨论】:

        【解决方案5】:
        【解决方案6】:

        是的,可以通过 BindingSource 绑定到嵌套属性。 Dan 在 1 月 25 日的评论显示了如何为“简单绑定”完成此操作,即绑定到单个对象的嵌套属性。对于集合的“复杂绑定”,它应该是这样的:

        public void DoIt()
        {
            List<Security> securities = new List<Security>();
        
            var securitiesBindingSource = new BindingSource();
            securitiesBindingSource.DataSource = securities;
        
            //add securities to list
            lstSecurities.DataSource = securitiesBindingSource;
            lstSecurities.DisplayMember = "Info.Description";
        }
        

        微妙的警告:集合的对象应该是同一类型的后代,因此 Info 应该是同一类型。当 Info 属性依赖于类型参数时,即使它是协变的,接口协变也不会使其工作,因为这将使 Info 成为协变但不同的类型,例如,当 Info 的类型为 Information&lt;out P&gt; 时。

        【讨论】:

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