none
Как правильно создать вычисляемый столбец у таблицы DataSet RRS feed

  • Вопрос

  • Задача не стандартная. Есть в проекте WinForms строго типизированный DataSet сгенерированный на основе возвращаемого результата от веб-службы. То есть дизайнера нету, так же как и табличных адаптеров, есть возможность через партиал добавить проперти, в котором и реализовать логику вычислений. Проблема в том, что проперти не связываются в форме, bindingSource работает с DataView таблицы, который видит только DataColumn записи и не видит никаких пропертей. В DataGridView можно обрабатывать событие CellFormating в котором получать привязываемой запись строго типизированного DataSet и уже у нее извлечь значение этотого самого проперти, но тута новая проблема (не считая того что метод не айсный) - изменения значений столбцов записи через грид не обновляет значения вычисляемого проперти.

    Кароче, как по науке реализовать этот самый вычисляемый столбец с таблице, без дизайнера?

    17 февраля 2011 г. 17:02

Все ответы

  • не вижу проблемы( и нестандартности тоже),

    1. создал типизированный датасет, табличку, в ней 3 столбца ID(key), Price1,Price2

    2. в коде динамически добавил к нему вычисляемый столбец

    вот код

     

    static void Main(string[] args)
     {
    
     MyTypedDataset ds = new MyTypedDataset();
     MyTypedDataset.MyTypedTableRow row = ds.MyTypedTable.NewMyTypedTableRow();
     row.ID=1;
     row.Price1 = 20;
     row.Price2 = 15;
     ds.MyTypedTable.Rows.Add(row);
    
     
     DataColumn extPriceColumn = new DataColumn(
     "ExtPrice", typeof(int),"Price1 * Price2", MappingType.Attribute);
     extPriceColumn.AutoIncrement = false;
     extPriceColumn.ReadOnly = true;
     ds.MyTypedTable.Columns.Add(extPriceColumn);
     PrintData(ds.MyTypedTable);
    
     Console.Read();
     }
    
     private static void PrintData(DataTable dt)
     {
     foreach (DataRow row in dt.Rows)
     {
     foreach (DataColumn col in dt.Columns)
     {
      Console.Write(string.Format("{0} ",row[col].ToString()));
     }
     Console.WriteLine();
     }
     }
    

    3. добавил строчку втаблицу

    4. вывел результат - все посчиталось

    17 февраля 2011 г. 20:26
  • Вы не правильно поняли. Мне нужно создать не экспрешион столбец, а имено вычисляемый кодом C# столбец и чтобы он был как обычный столбец таблицы.

    18 февраля 2011 г. 10:43
  • ок. код приводится как есть, тут очень возможны ошибки и не только в логике(особенно где отписываюсь приписываюсь - лень думать))

    1. расширяем датасет

     

     public partial class MyTypedDataset
     {
     public partial class MyTypedTableDataTable
     {
      private DataColumn columnExtPrice;
    
      public override void EndInit()
      {
      base.EndInit();
    
      DataColumn extPriceColumn = new DataColumn("ExtPrice", typeof(int));
      extPriceColumn.AutoIncrement = false;
      this.Columns.Add(extPriceColumn);
    
      this.columnExtPrice = base.Columns["ExtPrice"];
    
      //обработчик изменеия строки
      this.RowChanged += new DataRowChangeEventHandler(MyTypedTable_RowChanged);
      }
    
      //тут реализация вашей хитрой функции
      private void MyTypedTable_RowChanged(object sender, DataRowChangeEventArgs e)
      {
      MyTypedDataset.MyTypedTableRow row = e.Row as MyTypedDataset.MyTypedTableRow;
      if (row != null)
      {
       this.RowChanged -= new DataRowChangeEventHandler(MyTypedTable_RowChanged);
       row.ExtPrice = row.Price1 * row.Price2;
       this.RowChanged += new DataRowChangeEventHandler(MyTypedTable_RowChanged);
      }
      }
    
      public DataColumn ExtPriceColumn
      {
      get
      {
       return this.columnExtPrice;
      }
      }
     }
     public partial class MyTypedTableRow
     {
      public int ExtPrice
      {
      get
      {
       try
       {
       return ((int)(this[this.tableMyTypedTable.ExtPriceColumn]));
       }
       catch (global::System.InvalidCastException e)
       {
       throw new global::System.Data.StrongTypingException("The value for column \'ExtPrice\' in table \'MyTypedTable\' is DBNull.", e);
       }
      }
      set
      {
       this[this.tableMyTypedTable.ExtPriceColumn] = value;
      }
      }
     }
     }
    

     

    2. добавляем строчку, проверяем

     

     static void Main(string[] args)
     {
    
      MyTypedDataset ds = new MyTypedDataset();
    
      MyTypedDataset.MyTypedTableRow row = ds.MyTypedTable.NewMyTypedTableRow();
      row = ds.MyTypedTable.NewMyTypedTableRow();
      row.ID = 2;
      row.Price1 = 10;
      row.Price2 = 10;
      ds.MyTypedTable.Rows.Add(row);
      PrintData(ds.MyTypedTable);
    
      Console.Read();
     }
    

     

    все

    фокус в том что помимо проперти - добавляется и сам DataColumn

     

    18 февраля 2011 г. 11:42
  • Я понял идею, но что-то не получается. Начну с самого столбца, добавляю по вашему рецепту:

     public partial class OpraDataSet
     {
    
      public partial class OrdersDataTable
      {
       private DataColumn statusStringColumn;
       public DataColumn StatusStringColumn
       {
        get { return this.statusStringColumn; }
       }
    
       public override void EndInit()
       {
        base.EndInit();
        DataColumn _statusStringColumn = new DataColumn("StatusString", typeof(string));
        _statusStringColumn.AutoIncrement = false;
        _statusStringColumn.ReadOnly = true;
        this.Columns.Add(_statusStringColumn);
        this.statusStringColumn = base.Columns["StatusString"];
       }
      }
    }
    

    Но этого нового стобца не видно в дизайнере форм, когда редактируются стоблцы привязки у DataGridView. Что не так у меня?

    Теперь на счет значения добавленного столбца. судя по вешему примеру оно расчитывается в момент создания или изменения записи. У меня же такого вообще не будет, записи в таблице не создаются и не меняются, они приходят от веб-службы вместе с DataSet.

    18 февраля 2011 г. 12:25
  • сделайте как в примере - модифицируйте и таблицу и строку

    если данные не изменяются - просто при получении форычем пробегаетесь по всем строкам и устанавливаете значение

    уберите ридонли с колонки, а то не сможете менять

    18 февраля 2011 г. 12:33
  • Строку тоже можифицировал, не помогло:

     public partial class OrdersRow
     {
      public string StatusString
      {
      get
      {
       if (this.Status == 0) return "не обработана";
       else if (this.Status == 10) return "закреплена за менеджером";
       else if (this.Status == 100) return "отправлена в 1С";
       else if (this.Status == 200) return "обработана в 1С";
       return this.Status.ToString();
      }
      }
    }
    
    ЗЫ мне менять не нужно, мне просто значения нужно вычислять.
    18 февраля 2011 г. 12:37
  • ну значит не работает мой подход, надо в другу сторону копать)

    кстати ваша функция вроде может быть выражена экспрешеном, там есть IIF

    модифицированные вариант с экспрешеном и если вы привели реальный рабочий пример со статусом

    то делать надо так как показано ниже (проблема с дизайнером остается)

     

     DataColumn extPriceColumn = new DataColumn(
     "ExtPrice2", typeof(string), "IIF(Price1=20, 'first',IIF(Price1=30,'second','third'))", MappingType.Attribute);
     

    если вам нужна функциональность дизайнера, мне кажется это простым способом не сделать

     

    сейчас проверил, функциональность дизайнера доступна, если добавить этот код

    в сгенеррованный клас)) это очень очень плохой подход, особенно

    если перегенерация происходит постоянно (так делать не нужно)

    • Помечено в качестве ответа Abolmasov Dmitry 25 февраля 2011 г. 8:14
    • Снята пометка об ответе Radu2000 14 марта 2011 г. 8:09
    18 февраля 2011 г. 13:02
  • Уважаемый пользователь, вы решили свою проблему? Если да, и решением являлся один из ответов, то отметьте его. Если решили сами, то было бы отлично, если бы вы описали решение. Спасибо.


    Для связи [mail]
    20 февраля 2011 г. 22:29
  • Нет, проблема не решена и не видится возможности ее нормально решить. Можно воспользоваться вызовом метода Refresh у GridView всякий раз как меняется шота в источнике данных, но за такое даже индусам из микрософта платить зарплату нельзя, а уж мне предлагать подобное публике еще стыднее. В общем, решение не найдено и буду раз если кто его найдет и подскажет тута.


    14 марта 2011 г. 8:10