C# - Przesyłanie danych miedzy formami

0

Witam,

Pomału przypominam sobie podstawy programowania w C#. Mam taki problem, pobieram dane z bazy danych (firebird) całość pobierania trwa długo, około 30 sekund (długie zapytanie z kilkoma Joinami), żeby nie pobierać tych danych za każdym razem kiedy ich potrzebuje przypisałem je sobie do listy obiektów. W momencie gdy z głównego okna przechodzę do nowego w konstruktorze podaje mu tą listę i wszystko działa.

Pytanie czy mam możliwość (jeżeli tak to jak) odwoływania się do tej listy w metodach, np. chciałbym po zaznaczeniu wiersza w Datagridzie, pobrac nazwę Klienta z Datagrida, przefiltrować wcześniej przypisaną listę z bazy danych i wyświetlić w Textboxie obok opis Klienta .
Pobieram wartość z Datagrida i nie wiem jak w tym momencie mogę odwołać się do tej listy:

  private void DGdetailsvehicle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            DataGrid dataGrid = sender as DataGrid;
            DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(dataGrid.SelectedIndex);
            DataGridCell RowColumn = dataGrid.Columns[1].GetCellContent(row).Parent as DataGridCell;
            string Clientname = ((TextBlock)RowColumn.Content).Text;

}
0

Cześć,

Całkiem niedawno miałem podobny problem.

Nie wiem na ile moje rozwiązanie jest "czyste" ale zrobiłem to w ten sposób, że po pobraniu wartości z textboxa do zmiennej dopisałem do klasy metodę, która zwraca na zewnątrz jej wartość i wynik tej metody przypisałem do zmiennej na innej formie :D Może coś w tym kierunku ?

Pozdrawiam.

0

Nie wiem jak w WPF, ale w WindowsForms DataGridRow ma taką właściwość jak DataBoundItem. Przykład:

//tworzysz sobie jakąś klasę, np:
class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

//potem tworzysz listę obiektów tej klasy i dodajesz do grida:

dataGridView.DataSource = list; //list to lista obiektów klasy Person.

//potem w SelectionChanged np. tak:

DataGridViewSelectedRowCollection rows = dataGridView.SelectedRows;
if(rows.Count == 1)
{
    DataGridViewRow row = rows[0];
    Person p = (Person)row.DataBoundItem; //magia :)
    label1.Text = p.FirstName;
}

Nie wiem, czy o coś takiego Ci chodziło

0

Nie do końca o to, na Twoim przykładzie:
Mam gdzieś klasę w której tworze listę z osobami:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public DateTime birth_day { get; set; }
}

List<person> new_list = new List<pereson>(); 

new_list = Database.getdata() ;  // logika odpowiedzialna za wyfiltrowanie i pobranie danych z bazy danych w której jest kilka tysięcy osób.  

I teraz chciałbym żeby ta lista (new_list) była dostępna w całym programie, jest to lista na której chce pracować i wielokrotnie z niej pobierać dane w rożnych częściach kodu.

  • Otwieram nowe okno w którym wyświetla mi się tylko data urodzenia.

  • albo po zaznaczeniu danych w gridzie w zupełnie innym oknie:

    private void DGdetailsvehicle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // w tym miejscu chwiałbym wykorzystać już stworzoną listę - newlist         

        }
0

Poradziłem sobie, jak mam zadeklarowaną listę gdzieś mogę się do niej odwołać bez problemu, wystarczy podać najpierw nazwę klasy, soory za głupi temat :)

0

Nie za bardzo rozumiem Twój problem albo jest banalny.
Generalnie pobranie kilku tysięcy osób z bazy danych nie powinno być jakimś wyczynem. Nawet z joinami. Nawet na Firebirdzie ;) Przede wszystkim popatrzyłbym, co w bazie danych można by zoptymalizować, żeby zejść do normalnego czasu: 1, 2 sekundy.

Jeśli musisz mieć taką listę dostępną w całym programie, możesz to zrobić na kilka sposobów. Możesz wykorzystać do tego jakąś fabrykę. Możesz użyć singletona, który Ci to przechowa.

Najlepiej byłoby chyba stworzyć interfejs takiej fabryki, np:

interface IDataFeeder
{
    List<Person> GetData();
}

Potem w klasie, która ogarnia bazę danych (wykonuje tego selecta) zrobić tak, żeby implementowała ten interfejs:

List<Person> personData;

public List<Person> GetData()
{
    if(personData == null)
        personData = GetDataFromDatabase();

    return personData;
}

Nie wiem, jaką masz strukturę projektu, więc ciężko coś powiedzieć konkretnego. To takie najprostsze rozwiązania, które mi przyszły do głowy. Oczywiście nie jest idealne, bo tutaj dla ułatwienia założyłem, że lista się nigdy nie zmieni, co pewnie nie jest prawdą.

O coś takiego chodzi?

0

Z Firebirdem nie wiem co jest, strasznie zwalnia mi przy połączeniu sieciowym (serwer upload 300 mb/s ja siedzie na 40mb/s)
Wgrałem sobie bazę u siebie lokalnie i zapytanie śmiga Od razu mam odpowiedz, a ładowanie wszystkiego do listy to około 20 sekund. Po podłączeniu sieciowym wszystko znacznie zwalnia, ale nie jest to problemem. Zapisałem potrzebne dane z bazy do pliku i z niego odczytuje, a w tle działa wątek aktualizujący ten
plik.
Ale dzięki za pomoc i naprowadzenie z optymalizacją Firebirda, w tym kierunku będę szukał rozwiązania w przyszłości :)

A jeżeli chodzi o listę dostępną z całego projektu to jak wyżej napisałem poradziłem sobie deklarując ją w ten sposób

 internal static List<object> Object; 

Nie wiem czy jest to prawidłowe pod względem wydajności i estetyki, ale działa i nie zauważyłem jakoś długiego dostępu do listy.

0

Może podpasuje Ci takie rozwiązanie:

zamiast dane przetrzymywać w liscie klas, przechowuj go w statycznym obiekcie DataTable zadeklarowanym w Program.cs

    static class Program
    {
        public static DataTable listaOsob;

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }

wtedy w każdym miejscu kodu możesz się do tego obiektu odwołać.

metoda pobierająca dane wyglądałoby:

        public static DataTable PobierzListeOsob()
        {
            DataTable dataTable = null;
            try
            {
                StringBuilder queryString = new StringBuilder();
                queryString.Append(" tresc \n");
                queryString.Append(" zapytania \n");
                queryString.Append(" sql \n");
                using (FbDataAdapter adapter = new FbDataAdapter(queryString.ToString(), connection))
                {
                    adapter.Fill(dataTable = new DataTable("table"));
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.ToString());
            }
            return dataTable;
        }

wypełnienie grida danymi:

        void wypelnijGrida()
        {
            Program.listaOsob = PobierzListeOsob();
            dataGridView.DataSource = Program.listaOsob;
        }

odwołanie do zaznaczonego wiersza i do poszczególnych pól:

        private void dataGridView_SelectionChanged(object sender, EventArgs e)
        {
            if (dataGridView.SelectedRows.Count != 0 ) return
            DataRow zaznaczonyWiersz = ((DataRowView)dataGridView.SelectedRows[0].DataBoundItem).Row;

            string firstName = Covert.ToString(wiersz["nazwaKolumnyImie"]);
            string lastName  = Covert.ToString(wiersz["nazwaKolumnyNazwisko"]);
            int age = Covert.ToInt32(wiersz["nazwaKolumnyWiek"]);
            DateTime birth_day = Covert.ToDateTime(wiersz["nazwaKolumnyDataUrodzin"]);
        }

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