c# błąd przy niewidocznym datagridview

0

Przepraszam jeśli źle ubieram w słowa moje zapytanie.

Mam formę 'ZlecenieLista' w którym znajduje się komponent dataGridView 'dataGridZlecenie', który odczytuje dane z bazy sql w określonych odstępach czasu 'timer_Tick'.

      private void ZlecenieLista_Load(object sender, EventArgs e)
        {
             wypelnienie_tabeli();
        }
       private void wypelnienie_tabeli()
        {
            string aa = "SELECT tb_zlecenie.id_zlecenie AS 'KT', ... jakieś zapytanie ...";
               SqlConnection con = new SqlConnection(Program.connectionString("")); //connection string - poprawny
                con.Open();

                using (SqlDataAdapter a = new SqlDataAdapter(connectionstring, con))
                {
                    DataTable t = new DataTable();
                    a.Fill(t);
                    dataGridZlecenie.DataSource = t;
                    dataGridZlecenie.AutoSizeColumnsMode =
                    DataGridViewAutoSizeColumnsMode.Fill;
                    dataGridZlecenie.Columns["KT"].Width = 40; // tu występuje błąd
                    dataGridZlecenie.Columns["KT"].Frozen = true;
                    ...
               }
             con.Close();
      }
      private void timer_Tick(object sender, EventArgs e)
        {
        ...
         wypelnienie_tabeli();
        ...
        }

Samodzielnie cały ten zestaw działa w pełni poprawnie.

Ale mam też drugą forme z zakladkami TabControl.
Na jednej z zakładek znajduje się dynamicznie utworzony obiekt 'ZlecenieLista':

       private void wczytanie_zlecen_klienta()
        {

            ZlecenieLista okno_Zlecenie = new ZlecenieLista("Klient", rekord);
            okno_Zlecenie.TopLevel = false;
            okno_Zlecenie.AutoScroll = true;
            this.panel_zlecenia_klienta.Controls.Add(okno_Zlecenie);
            okno_Zlecenie.Dock = DockStyle.Fill;
            okno_Zlecenie.Show();
        }

I teraz problem:
Wariant poprawny:
Otwieram formę główną i przechodzę na zakładkę z obiektem 'ZlecenieLista'. Oglądam go sobie: działa.
Wszystko działa cacy. Dane się odświeżają.

Wariant niepoprawny:
Otwieram formę główną i przechodzę na zakładkę z obiektem 'ZlecenieLista'. Oglądam go sobie: działa jak wcześniej, ale przełączam zakładkę na inną.
Program działa, ale czasami, po kilkunastu sekundach wyrzuca błąd:

System.NullReferenceException: Object reference not set to an instance of an object.
at System.Windows.Forms.DataGridViewBand.set_Thickness(Int32 value)
at System.Windows.Forms.DataGridViewColumn.set_Width(Int32 value)
at WindowsFormsApplication1.ZlecenieLista.wypelnienie_tabeli()
at WindowsFormsApplication1.ZlecenieLista.timer_Tick(Object sender, EventArgs e)
at System.Windows.Forms.Timer.OnTick(EventArgs e)
at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Debugger pokazuje że wszystkie zmienne formy 'ZlecenieLista' są NULL pomimo że chwilę wcześniej datagrid się wczytał i działał.

Nie jest to jedyny przypadek. Podobnie dzieje się też w innych miejscach tam, gdzie obiekty datagrid otwarte są jako dynamiczne obiekty i nie są widoczne w danej chwili na ekranie.

Nie wiem jak to ugryźć. Google nie wiedzą, albo nie potrafię sformułować zapytania.

0

Spróbuj robić tak że do grida binduj dane w momencie przełączenia zakładki, a nie w timerze. W timerze aktualizuj tylko dane które bindujesz. Najlepiej zrób sobie zmienną w klasie:

BindingSource bsDane = new BindingSource();

i w funkcji wypelnienie_tabeli:

bsDane.DataSource = t;

I w momencie przełączenia zakładki:

                dataGridZlecenie.DataSource = bsDane;
                dataGridZlecenie.AutoSizeColumnsMode =
                DataGridViewAutoSizeColumnsMode.Fill;
                dataGridZlecenie.Columns["KT"].Width = 40; // tu występuje błąd
                dataGridZlecenie.Columns["KT"].Frozen = true;
                ...
0

Problem ma drugie dno.
Okazuje się że grid nie jest tu raczej niczemu winien.
Przeleciałem cały kod debuggerem i zauważyłem takie coś:

Gdy w mojej formie z tabControlem tworzę dynamicznie na niewidocznej w danej chwili zakładce obiekt:

      private void wczytanie_zlecen_klienta()
        {
 
            ZlecenieLista okno_Zlecenie = new ZlecenieLista("Klient", rekord);
            okno_Zlecenie.TopLevel = false;
            okno_Zlecenie.AutoScroll = true;
            this.panel_zlecenia_klienta.Controls.Add(okno_Zlecenie);
            okno_Zlecenie.Dock = DockStyle.Fill;
            okno_Zlecenie.Show();
        }

a aktywną mam następną zakładkę to dopóki nie przejde na tą zakładkę z moim obiektem nie wykonuje się w nim zdażenie Load.

Wstawiłem w tym zdażeniu MessageBox więc widać, że dopóki nie wejde na tą zakładkę i nie pokaże się fizycznie na ekranie utworzony obiekt wiadomość się nie wyświetla.

       private void ZlecenieLista_Load(object sender, EventArgs e)
        {
MessageBox.Show("test zakładki");
}

Co więcej prześledziłem kod debuggerem i wynika że po utworzeniu obiektu wykonuje się tylko

       public KlientLista(string Nazwa, string Rekord)
        {
            InitializeComponent();
            nazwa = Nazwa;
            rekord = Rekord;
        }

nie inicjuje się żadna zmienna których tam kilka jest.

tak wygląda kod:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Common;

namespace WindowsFormsApplication1
{
    public partial class KlientLista : Form
    {
        public string nazwa;
        public string rekord;
        public string myLogin;

        public string upr_klient_detale;
        public string upr_klient_pole;
 ...

        public KlientLista(string Nazwa, string Rekord)
        {
            InitializeComponent();
            nazwa = Nazwa;
            rekord = Rekord;
        }

        private void KlienciLista_Load(object sender, EventArgs e)
        {
         MessageBox.Show("test zakładki");

...
        }

dlatego gdy zainicjował się Timer a zmienne nie, to po określonym czasie gdy Timer nakazuje wczytanie danych wyrzuca błąd.
Jeśli przed upływem tego czasu przełączę się na tą zakładkę to wykona się zdażenie load i zainicjują się zmienne i wszystko działa jak należy.

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