С# DataGridView привязан к элементу List‹DataTable› внутри объекта

У меня есть следующий бизнес-объект:

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 к элементу управления DataGridView. Таблица для привязки должна быть выбрана элементом управления NumericUpDown, а затем будет простая кнопка «Добавить», чтобы создать новую таблицу и добавить ее в MeasurementErrors (и кнопку удаления, если необходимо). Как настроить свойства DataSource и DataMember DataGridView для привязки к MeasurementErrors [значение UpDownControl]?

Я не зациклен на использовании DataTables, но из того, что я прочитал, это предпочтительный способ привязки к DataGridView.


person JJS    schedule 19.11.2010    source источник


Ответы (1)


List<T> нельзя связать. Вместо этого используйте IList<T> в качестве возвращаемого типа свойства.

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<T> является List<T> под капотом, то я предлагаю вам преобразовать ваш IList<T> в List<T> ради сериализации. И если это не удается, то создайте новый список из его содержимого.

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

Я надеюсь, что эта информация не больше сбивает с толку, чем помогает.

person Will Marcouiller    schedule 19.11.2010
comment
Я реализовал свой список DataTables с помощью IList, и, похоже, он работает, но это добавило еще один недостаток в проект. До этого, когда у меня была только одна DataTable, я использовал XmlSerializer для сохранения MyObject в файл. IList, похоже, не сериализуем, поэтому он просто исключен из результирующего xml-файла. Есть ли простой способ сделать этот IList сериализуемым? - person JJS; 19.11.2010
comment
Re: РЕДАКТИРОВАТЬ № 1. Спасибо, создание отдельного общедоступного свойства, которое я не собираюсь фактически использовать с _measurementErrors, преобразованным в список, работало для сериализации MyObject со всеми данными. Теперь мне просто нужно решить, как связать свойство IList с DataGridView при указании индекса. - person JJS; 20.11.2010
comment
На самом деле вам не нужно создавать другое свойство, а просто введите тип MeasurementErrors при его сериализации. Я мало работал с Serialization, поэтому, возможно, я что-то упустил. Тем не менее, я не понимаю вашей точки привязки IList к DataGridView при указании индекса. Разве ты не можешь просто сделать DataGridView.DataSource = IList<DataTable>? - person Will Marcouiller; 20.11.2010
comment
Я запускаю XmlSerialize для экземпляра MyObject, поэтому в то время у меня действительно нет возможности приводить свойство IList к типу. Что касается DataSource = IList, я хочу отображать/редактировать содержимое только одного DataTable в этом IList, поэтому мне нужно выбрать, какой из этих DataTable активен в DataGridView. - person JJS; 21.11.2010
comment
Я, видимо, недостаточно обдумал это, прежде чем помчался реализовывать. Почему бы мне просто не добавить еще один столбец в одну таблицу данных с моим индексом, а не создавать массив таблиц данных? Использование IList определенно пригодится в будущих ситуациях привязки данных, поэтому я очень ценю вашу помощь. - person JJS; 22.11.2010
comment
Я рад, что смог помочь! И спасибо, что дали мне знать. знак равно - person Will Marcouiller; 22.11.2010