c # WPF DataGrid - запись значений ячеек построчно в файл xml

Описание проблемы:

У меня есть DataGrid. Он заполняется списком. Код для этого следующий:

List<SomeClass> someClassList = new List<SomeClass>();
//Fill somClassList with data (omited for brevity)
myDataGrid.ItemsSource = someClassList;

Это работает, и все значения отображаются правильно. Теперь пользователь может редактировать все ячейки и создавать новые строки. После того, как пользователь нажмет какую-либо кнопку, я хочу сохранить значения внутри этой DataGrid в XML-файл следующую структуру:

<Root>
    <a>
        <b>val1</b>
        <c>val2</c>
        <d>
            <e>
                <f>val3</f>
                <g>val4</g>
                <h>val5</h>
                <i>val6</i>
            </e>
            <!--variable number of 'e'- tags with inner structure as above-->
        </d>
     </a>
     <!--variable number of 'a'-tags with inner structure as above-->
</Root>

По этой причине я решил, что будет разумно перебирать DataGrid построчно. Поэтому Button-Click-event-Handler содержит код, который выполняет итерацию (каждое значение воспроизводится методом WriteLine()):

foreach (SomeClass someClassElement in myDataGrid.ItemsSource)
{
    Trace.WriteLine(someClassElement.b+ ", " + someClassElement.c+ ", " +
                    someClassElement.f + ", " + someClassElement.g + ", " +
                    someClassElement.h + ", " + someClassElement.i);
}

Теперь мне нужно записать каждую строку в XML-файл. К сожалению, это не кажется тривиальной задачей, потому что есть два внутренних тега с переменным количеством вхождений.

На данный момент я получил следующий код, который создает аналогично добавленный XML-файл из примера DataGrid, который я добавил для целей ясность.

//Button click code
XmlDocument doc = new XmlDocument();
XmlNode myRoot = doc.CreateElement("Root");
XmlNode a,b,c,d,e;
String last_b_value = "0";
foreach (SomeClass someClassElement in myDataGrid.ItemsSource)
{
    String current_b_value = someClassElement.b;
    if (last_b_value != current_b_value)
    {
        //Creating XML-elements and setting text
        a = doc.CreateElement("a");
        b = doc.CreateElement("b");
        b.InnerText = someClassElement.b;
        c = doc.CreateElement("c");
        c.InnerText = someClassElement.c;
        d = doc.CreateElement("d");
        e = doc.CreateElement("e");

        a.AppendChild(b);
        a.AppendChild(c);
        a.AppendChild(d);
        d.AppendChild(e);
    }
}
doc.AppendChild(myRoot);
// Save document
string filename = dlg.FileName;
doc.Save(@filename);

Вот выведенный XML-файл:

<root>
  <a>
    <b>val_1_1</b>
    <c>val_1_2</c>
    <d>
      <e />
      <!-- the varying number of 'e'-tags is not created correctly -->
    </d>
  </a>
  <a>
    <b>val_2_1</b>
    <c>val_2_2</c>
    <d>
      <e />
      <!-- the varying number of 'e'-tags is not created correctly -->
    </d>
  </a>
  <a>
     <b>val_3_1</b>
     <c>val_3_2</c>
     <d>
       <e />
       <!-- the varying number of 'e'-tags is not created correctly -->
     </d>
  </a>
  <!-- number of varying 'a'-tags is created correctly -->
</root>

А вот пример-DataGrid, из которого XML-файл создается после того, как пользователь нажимает кнопку:

example-Datagrid

Код правильно обрабатывает переменное количество тегов 'a', но не имеет функциональности для записи также переменного количества e-теги внутри каждого a-тега.

Вместо этого выходной XML-файл должен выглядеть так:

<Root>
  <a>
    <b>val_1_1</b>
    <c>val_1_2</c>
    <d>
          <e>
          <f>x1</f>
          <g>x1</g>
          <h>x1</h>
          <i>x1</i>
      </e>
      <e>
          <f>x2</f>
          <g>x2</g>
          <h>x2</h>
          <i>x2</i>
      </e>
      <e>
          <f>x3</f>
          <g>x3</g>
          <h>x3</h>
          <i>x3</i>
      </e>
    </d>
  </a>
  <a>
    <b>val_2_1</b>
    <c>val_2_2</c>
    <d>
      <e>
          <f>x4</f>
          <g>x4</g>
          <h>x4</h>
          <i>x4</i>
      </e>
      <e>
          <f>x5</f>
          <g>x5</g>
          <h>x5</h>
          <i>x5</i>
      </e>
    </d>
  </a>
  <a>
    <b>val_3_1</b>
    <c>val_3_2</c>
    <d>
      <e>
          <f>x6</f>
          <g>x6</g>
          <h>x6</h>
          <i>x6</i>
      </e>
    </d>
  </a>
</Root>

Вопросы:

  1. Как я могу адаптировать код для создания отсутствующих электронных тегов?
  2. Есть ли более разумный способ прочитать DataGrid и сохранить его значения в тот же структурированный XML-файл?

person kiltek    schedule 21.10.2013    source источник
comment
Сериализуйте свои объекты с помощью XMLSerializer. Я настоятельно рекомендую вам не пытаться изобретать велосипед.   -  person Federico Berasategui    schedule 21.10.2013
comment
Что касается вашего вопроса № 2, в C# In-Depth Джона Скита есть хорошее описание того, как использовать Linq для написания XML. Я читал ее только прошлой ночью. Я не помню подробностей на данный момент и нахожусь вдали от книги - таким образом, комментарий, но не фактический ответ.   -  person philologon    schedule 21.10.2013
comment
Проблема с XMLSerializer заключается в том, что переменная длина e-тегов внутри a-тегов также не обрабатывается.   -  person kiltek    schedule 21.10.2013


Ответы (1)


На Вопрос 1 есть простой ответ:

Мне пришлось адаптировать предложение if к следующему, чтобы XML-вывод был правильно структурирован:

  //Button click code
  XmlDocument doc = new XmlDocument();
  XmlNode myRoot = doc.CreateElement("Root");
  XmlNode a,b,c,d,e;
  String last_b_value = "0";
  foreach (SomeClass someClassElement in myDataGrid.ItemsSource)
  {
   String current_b_value = someClassElement.b;
   if (last_b_value != current_b_value)
   {
       //Creating XML-elements and setting text
       a = doc.CreateElement("a");
       b = doc.CreateElement("b");
       b.InnerText = someClassElement.b;
       c = doc.CreateElement("c");
       c.InnerText = someClassElement.c;
       d = doc.CreateElement("d");
       e = doc.CreateElement("e");


   }else if(last_b_value == current_b_value){
       e = doc.CreateElement("e");
   }
       a.AppendChild(b);
       a.AppendChild(c);
       a.AppendChild(d);
       d.AppendChild(e);
  }
  doc.AppendChild(myRoot);
  // Save document
  string filename = dlg.FileName;
  doc.Save(@filename);

При такой структуре предложения if теги abcd опускаются.

person kiltek    schedule 21.10.2013