【问题标题】:C# DataGridView bound to member of List<DataTable> inside objectC# DataGridView 绑定到对象内部 List<DataTable> 的成员
【发布时间】:2010-11-19 16:18:24
【问题描述】:

我有以下业务对象:

public class MyObject
{
  // Some public properties that are bound to text boxes, etc on the form
  public string Customer { get; set; }
  public int JobNumber { get; set; }

  // Each DataTable in this list consists of a single column of doubles
  // representing the error in a series of measurements (ex. -.0002, -.0003, .0002, etc)
  public List<DataTable> MeasurementErrors {get; set; }

  public MyObject
  {
    // Code in here creates the first DataTable with the first measurement (always zero)
    // and adds it to the MeasurementErrors list
    errors = new DataTable();
    errors.TableName = "MeasurementErrors";
    errors.Columns.Add("Error", typeof(double));
    errors.Rows.Add(0.0);
    MeasurementErrors.Add(errors); // initial table added to the list
  }
}

我将 Customer 和 JobNumber 以及所有其他基本属性绑定到输入表单上的文本框没有问题(VS 生成了一个 BindingSource 并为我设置了所有这些控件)。

我遇到的问题是将MeasurementErrors 中的一个DataTables 绑定到DataGridView 控件。要绑定的表应该由 NumericUpDown 控件选择,然后将有一个简单的“添加”按钮来生成一个新表并将其添加到 MeasurementErrors(如果需要,还有一个删除按钮)。如何设置 DataGridView 的 DataSource 和 DataMember 属性以绑定到 MeasurementErrors[UpDownControl 的值]?

我并没有固定使用 DataTables,但从我所读到的内容来看,这是绑定到 DataGridView 的首选方式。

【问题讨论】:

    标签: c# datagridview bindingsource


    【解决方案1】:

    List&lt;T&gt; 不可绑定。请改用IList&lt;T&gt; 作为属性返回类型。

    public IList<DataTable> MeasurementErrors { get; set; }
    

    另外,根据您的需要,最好始终为列表成员使用内部列表并将其设为只读属性。

    public class MyObject {
        private IList<DataTable> _measurementErrors;
    
        public MyObject() {
            _measurementErrors = new List<DataTable>();
        }
    
        // This way you make sure to never have a null reference, and don't give 
        // out the control over your list to the user.
        public IList<DataTable> MeasurementErrors {
            get {
                return _measurementErrors;
            }
        }
    }
    

    编辑#1

    IList 似乎不是可序列化的,因此它被简单地排除在生成的 xml 文件之外。有没有一种简单的方法可以使这个 IList 可序列化?

    如果您的IList&lt;T&gt; 实例在后台是List&lt;T&gt;,那么为了序列化,我建议您将IList&lt;T&gt; 类型转换为List&lt;T&gt;。如果失败,则根据其内容创建一个新列表。

    var list = myObject1.MeasurementErrors as List<DataTable> ?? new List<DataTable>(myObject1.MeasurementErrors);
    

    更多关于?? Operator的信息,请参考MSDN:?? Operator (C# Reference)

    简单来说就是写的等价:

    var list = (myObject1.MeasurementErrors as List<DataTable>) == null ? 
                new List<DataTable>(myObject1.MeasurementErrors) : 
                myObject1.MeasurementErrors as List<DataTable>;
    

    或者,如果您愿意:

    var list = myObject1.MeasurementErrors as List<DataTable>;
    
    if (list == null)
        list = new List<DataTable>(myObject1.MeasurementErrors);
    

    我希望这些信息不会比帮助更令人困惑。

    【讨论】:

    • 我已经使用 IList 实现了我的 DataTables 列表,它似乎可以工作,但这给项目增加了另一个问题。在此之前我只有一个 DataTable,我使用 XmlSerializer 将 MyObject 保存到文件中。 IList 似乎不是可序列化的,因此它被简单地排除在生成的 xml 文件之外。有没有一种简单的方法可以使这个 IList 可序列化?
    • Re: EDIT #1 - 谢谢,创建一个单独的公共属性,我无意实际使用 _measurementErrors 类型转换为 List 用于序列化 MyObject 的所有数据。现在我只需要弄清楚如何在指定索引的同时将 IList 属性绑定到 DataGridView。
    • 您实际上不需要创建另一个属性,而只需在序列化时对您的MeasurementErrors 进行类型转换。我与Serialization 的合作不多,所以也许我在这里遗漏了一些东西。但是,我不明白您在指定索引时将IList 绑定到DataGridView 的意义。你就不能DataGridView.DataSource = IList&lt;DataTable&gt;吗?
    • 我在 MyObject 的一个实例上运行 XmlSerialize,所以当时我真的没有机会对 IList 属性进行类型转换。关于 DataSource = IList,我只想显示/编辑该 IList 中单个 DataTable 的内容,因此我需要选择 DataGridView 中哪些 DataTables 处于活动状态。
    • 在开始实施之前,我显然没有充分考虑这一点。为什么不使用索引将另一列添加到单个 DataTable,而不是创建 DataTables 数组?使用 IList 肯定会在未来的数据绑定情况下派上用场,因此非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2013-05-28
    • 2013-01-01
    • 1970-01-01
    • 2016-11-04
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    相关资源
    最近更新 更多