Zapisywanie danych z wielu DataGridView do pliku XML

0

Witam
Mam na formie TabPage z dwoma zakładkami. W każdej zakładce jest DataGridView, który ma jedną kolumnę i dwa wiersze. W tych tabelkach zapisuję sobie dane, i chce po zamknięciu formy to zapisać do pliku xml.
Z pierwszą zakładką i tabelką nie było problemu, ale jak utworzę drugą zakładkę i w niej tabelkę, to po pierwsze w drugiej nie mam w Headerze nazw wierszy, a po drugie czy jest jakiś sposób aby to zapisać do jednego pliku, a nie do dwóch tak jak w moim przypadku.

 public partial class Form1 : Form
    {
        private const string Plik1 = "Założenia1.xml";
        private const string Plik2 = "Założenia2.xml";
        static DataTable dt1 = new DataTable("Tabela1"); //Create a datatable to store XML data
        static DataSet ds1 = new DataSet();//Create a dataset
        static DataTable dt2 = new DataTable("Tabela2"); //Create a datatable to store XML data
        static DataSet ds2 = new DataSet();//Create a dataset
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            if (File.Exists(Plik1))
            {
                ds1.ReadXml(Plik1);
                dGv1.DataSource = ds1;
                dGv1.DataMember = "Tabela1";
            }
            else
            {
                dt1.Columns.Add("Założenia1");
                dt1.Rows.Add("1");
                dt1.Rows.Add("2");
                ds1.Tables.Add(dt1);
                dGv1.DataSource = ds1;
                dGv1.DataMember = "Tabela1";
            }
            dGv1.TopLeftHeaderCell.Value = "PRODUKT1";
            dGv1.Rows[0].HeaderCell.Value = "Wiersz1";
            dGv1.Rows[1].HeaderCell.Value = "Wiersz2";
            
            if (File.Exists(Plik2))
            {
                ds2.ReadXml(Plik2);
                dGv2.DataSource = ds2;
                dGv2.DataMember = "Tabela2";
            }
            else
            {
                dt2.Columns.Add("Założenia2");
                dt2.Rows.Add("3");
                dt2.Rows.Add("4");
                ds2.Tables.Add(dt2);
                dGv2.DataSource = ds2;
                dGv2.DataMember = "Tabela2";
            }
            dGv2.TopLeftHeaderCell.Value = "PRODUKT2";
            dGv2.Rows[0].HeaderCell.Value = "Wiersz3";
            dGv2.Rows[1].HeaderCell.Value = "Wiersz4";
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            ds1.WriteXml(Plik1);
            ds2.WriteXml(Plik2);
        }
    }

Problemem jest to, że tam będzie więcej zakładek.
Dzięki za wskazówki i pozdrawiam.

1

Pierwsze: Header się nie eksportuje, ponieważ nie masz go w datasecie. Podczas tworzenia tabeli dodaj do niej kolumnę z wartościami dla headera i na podstawie niej ustawiaj to samo na gridzie.
np:

dt1.Columns.Add("PRODUKT1");
dt1.Columns.Add("Założenia1");
dt1.Rows.Add("Wiersz1","1");
dt1.Rows.Add("Wiersz1","2");

a potem gdy przepisać z DataTable do grida:

foreach (DataGridViewRow row in dGv1.Rows)
{
	var rowView = row.DataBoundItem as DataRowView;
	if (rowView != null)
	{
		row.HeaderCell.Value = rowView.Row["PRODUKT1"];

	}
} 

Drugie pytanie: żeby zapisać to w w jednym pliku obydwie tabele zapisuj w jednym z datasetów, który potem wyeksportujesz.
W kodzie będzie coś takiego:

ds1.Tables.Add(dt1);
ds1.Tables.Add(dt2);
...
dGv1.DataSource = ds1;
dGv1.DataMember = "Tabela1";
dGv2.DataSource = ds1;
dGv2.DataMember = "Tabela2";
0

Nie zupełnie o to chodzi.
Powyższy sposób zapisuje mi nazwy w zwykłych komórkach.
Ja potrzebuję wpisać nazwy wierszy w HeaderCell, i o ile w pierwszej zakładce te nazwy wyświetlają się prawidłowo:

dataGridView1.TopLeftHeaderCell.Value = "PRODUKT1";     // to jest
dataGridView1.Rows[0].HeaderCell.Value = "Wiersz 1.1";  // to jest
dataGridView1.Rows[1].HeaderCell.Value = "Wiersz 1.2";  // to jest

to w drugiej już się nie wyświetlają

dataGridView2.TopLeftHeaderCell.Value = "PRODUKT2";     // to jest
dataGridView2.Rows[0].HeaderCell.Value = "Wiersz 2.1";  // tego nie ma
dataGridView2.Rows[1].HeaderCell.Value = "Wiersz 2.2";  // tego nie ma

Próbowałem już różnych sposobów i ręce mi już opadają.

usunięcie cytowania całego poprzedniego posta - @furious programming

1

Hm.. nie zauważyłem tego wczesniej :)
W takim razie ustaw HeaderCell.Value w evencie DataGridView.DataBindingComplete: http://msdn.microsoft.com/pl-pl/library/system.windows.forms.datagridview.databindingcomplete%28v=vs.110%29.aspx

0

Dalej nic. A w dodatku mam wyjątek:

private void dataGridView2_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            dataGridView2.TopLeftHeaderCell.Value = "PRODUKT2"; 
            dataGridView2.Rows[0].HeaderCell.Value = "Wiersz 2.1";  // Additional information: Indeks był spoza zakresu. Musi mieć wartość nieujemną i mniejszą niż rozmiar kolekcji.
            dataGridView2.Rows[1].HeaderCell.Value = "Wiersz 2.2";
        } 

To zdarzenie "dataGridView1_DataBindingComplete" zdaje się dotyczy kolumn, a ja chcę umieścić nazwy wierszy w HeaderCell.
Nie wiem dlaczego w pierwszej zakładce z dataGridView1 wszystko jest cacy, a w drugiej z dataGridView2 mam tylko nazwy kolumn, a nazwy w HeaderCell już się nie wyświetlają, tak jak to zaznaczyłem w komentarzach powyżej. Pewnie problem jest błahy, ale wykracza poza moją wiedzę.

Edit:
Taka ciekawostka.
Tworzę dwie metody do wywołania tych nieszczęsnych napisów, i wywołuję je w zdarzeniu RowsAdded, i po walce z wyjątkami okazało się że jeden ten sam napis pojawia się w trzech wierszach danego Grida, to samo w drugiej zakładce w drugim Gridzie.

private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            MetdGv1(dataGridView1);
        }
        private void dataGridView2_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            MetdGv2(dataGridView2);
        }
        public void MetdGv1(DataGridView dataGridView1)
        {
            dataGridView1.TopLeftHeaderCell.Value = "PRODUKT1";     // 
            dataGridView1.Rows[0].HeaderCell.Value = "Wiersz 1.1";  // Nazwa - Wiersz 1.1 - jest w trzech wierszach
            //dataGridView1.Rows[1].HeaderCell.Value = "Wiersz 1.2";  // 
        }
        public void MetdGv2(DataGridView dataGridView2)
        {
            dataGridView2.TopLeftHeaderCell.Value = "PRODUKT2";
            dataGridView2.Rows[0].HeaderCell.Value = "Wiersz 2.1"; // Nazwa - Wiersz 2.1 - jest w trzech wierszach
            //dataGridView2.Rows[1].HeaderCell.Value = "Wiersz 2.2"; //
        } 
0

dokumentacja TabPage:
http://msdn.microsoft.com/pl-pl/library/system.windows.forms.tabpage%28v=vs.110%29.aspx
"Controls contained in a TabPage are not created until the tab page is shown, and any data bindings in these controls are not activated until the tab page is shown."

Czyli wiersze zostaja stworzone dopiero w momencie przełączenia się na drugą zakładkę, dlatego znikają Ci ustawione wartości w row headerach.
Event DataBindingCompleted pozwoli Ci wyłapać moment kiedy już są stworzone, oprócz tego mógłbyś sprawdzać czy jakiekolwiek wiersze są w gridzie i czy jest to ListChangedType.Reset(z argumentu eventu).

Dalej proponuje, żeby zrobić te headery jako część danych(kolumna do DataTable i odpowiadająca kolumna w gridzie, dla której mógłbyś zmodyfikować wygląd, tak, żeby Ci pasowało). Te wyświetlane teraz ukryć za pomocą DataGridView.RowHeadersVisible=false albo nie zmieniać wcale.

1 użytkowników online, w tym zalogowanych: 0, gości: 1