WPF DataGrid i kolumna z ComboBox.

0

Witam wszystkich serdecznie. Mam nastepujacy problem w aplikacji WPF. Otoz mam DataGrid. Mam dwie tabele w bazie, tabela1 i tabela2. W tabela2 mam pole id_tabela1, ktorym odpowiada id rekordu z tabela1. Jedna pozycja z tabela1, moze wiazac sie z kilkoma rekordami z tabela2. Teraz w DataGrid chcialbym wyswietlic w pierwszej kolumnie pole "nazwa" z tabela1, w drugiej chcialbym miec mozliwosc wybrania w polu z ComboBox (zawartosc ComboBox to pole z tabela2 o nazwie "nazwa" dla wszystkich tabela1.id=tabela2.id_tabela1). Mam nadzieje ze za bardzo nie zamieszalem. Jakbyscie mieli pytania to prosze. Natomiast pytanie brzmi jak to ladnie zbindowac (chyba ;)) zeby w tym ComboBox mial te rekordy powiazane z dugiej tabeli. DataGrid wypelniam w ten sposob:

dataGridMain.ItemsSource = set.Tables[0].DefaultView;

0

Nie ma prostego i bezkosztowego rozwiazania.

Najbardziej 'eleganckim' z punktu widzenia platformy jest przyjecie czegos a'la MVVM i dołożenie jeszcze jednej warstwy pomiedzy "dane", a "ekran". Nie wypychaj jako ItemsSource oryginalnych danych, tylko opakuj te dane w obiekty, które będą udostępniac property "FilteredTabela2Items", ktore będzie dostarczac listę obiektów pasujących do 'nazwa' danego wiersza. Do takiego pola bez problemu zbindujesz ItemSource ComboBoxa. Przykre jest to, że każdy wiersz bedzie musial byc przepakowany w sztuczny obiekt.

Alternatywą jest ohandlerowanie wszytkiego recznie i reagowanie na open comboboxa, i wtedy przeladowywanie mu zawartosci.. Przykre, bo sporo makaroniastego kodu, a i kruche to.

Alternatywą, jest napisanie wlasnego comboboxa lub innego fragmentu kolumny, doszlifowanego pod katem TEGO akurat typu wiersza i tabeli, ktory zbindujesz do wiersza zamiast do pola tego wiersza, i ten obiekt widzac caly wiersz zajmie się ladowaniem odpowiednich danych comboxowi.. Brzydkie, bo sie napiszesz, natrudzisz, a dostaniesz kontrolke pod ten jeden konkretny przypadek. Mozesz to potem rozwijac i abstrahowac/konfigurowac, ale to jest jeszcze wiecej pracy i a'la MVVM jest prostsze.. acz niekoniecznie 'wydajniejsze' w sensie pamieci/czasu

Kolejna alternatywą jest sprobowanie napisania konwertera, ktory doczepisz do bindingu i ktory bedzie tlumaczyc wiersz -> liste elementow. Podejscie podobne jak ze szlifowaniem calej kontrolki, ale "krotsze" i bardziej zwiezle. Minus - binding będzie w zapisie dużo dłuższy, konwerter jest wywoływany czesto, napisanie tego dobrze łatwe nie bedzie.

i kombinowac jeszcze mozna dalej.. np. jezeli w Twojej aplikacji wiersze sa edytowalne nie "natychmiast" albo dopiero po kliknieciu na nie, tzn. dopiero po focusie na danym konkretnym wierszu mozesz go edytowac, to wtedy wystarczy na formatce/kontrolce dorobic pole FilteredTabela2Items, wszystkie comboxy spinac na to, lapac event zmiany wybranego wiersza, i wtedy przeladowywac zestaw podpowiedzi.. ale to ma DUŻY minus, ze wtedy musisz BARDZO ostroznie kontrolowac co pokazujesz na ekranie i które zmiany faktycznie zapisujesz do bazy, gdyz wszystkie comboxy sa spiete na to samo property i wszystkie naraz zmienia listy oraz swoje selectedvalue's.. w efekcie jest to trudniejsze i bardziej upierdliwe niz alternatywa numer 1 ktora napisalem zaraz po a'la MVVM..

0

Dzieki za odpowiedz, masz moze jakies linki do materialow gdzie mogl bym to znalezc, ewentualnie jakies kawalki kodu ?

Poszperalem troche i wypocilem troche :) lecz nadal mi nie dziala tak jakbym chcial. Wkleje kod moze cos pomozecie.

 
public class Tag
    {
        public string tag { get; set; }
        public Tag(string tag1)
        {
            tag = tag1;
        }
    }

class ItemObrazki
    {
        public ItemObrazki(string sciezka1, System.Collections.ObjectModel.ObservableCollection<Tag> tagi1)
        {
            sciezka = sciezka1;
            tagi = tagi1;
        }
        public string sciezka { get; set; }
        public System.Collections.ObjectModel.ObservableCollection<Tag> tagi { get; set; }
    }


 string commandText = "select id, sciezka from obrazki";
            
            System.Data.SQLite.SQLiteDataAdapter adapter = new System.Data.SQLite.SQLiteDataAdapter(commandText, m_connection);

            System.Data.DataSet set = new System.Data.DataSet();

            adapter.Fill(set);

            System.Collections.ObjectModel.ObservableCollection<ItemObrazki> list = new System.Collections.ObjectModel.ObservableCollection<ItemObrazki>();

            for (int i = 0; i < set.Tables[0].Rows.Count; i++)
            {
                System.Collections.ObjectModel.ObservableCollection<Tag> tagi = new System.Collections.ObjectModel.ObservableCollection<Tag>();

                long id = set.Tables[0].Rows[i].Field<long>("id");

                commandText = string.Format("select tag from tagi where id_obrazki = {0}", id);

                System.Data.SQLite.SQLiteDataAdapter adapterTagi = new System.Data.SQLite.SQLiteDataAdapter(commandText, m_connection);

                System.Data.DataSet setTagi = new System.Data.DataSet();

                adapterTagi.Fill(setTagi);

                for (int j = 0; j < setTagi.Tables[0].Rows.Count; j++)
                {
                    tagi.Add(new Tag(setTagi.Tables[0].Rows[j].Field<string>("tag")));
                }
                list.Add(new ItemObrazki(set.Tables[0].Rows[i].Field<string>("sciezka"), tagi));
            }

            ((DataGridComboBoxColumn)dataGridMain.Columns[1]).SelectedItemBinding = new Binding("tagi");
            ((DataGridComboBoxColumn)dataGridMain.Columns[1]).DisplayMemberPath = "tag";
            dataGridMain.ItemsSource = list;

Cos na pewno namieszalem z tymi bindingami, ale nie wiem co za bardzo. Mamy dwie kolekcje w jedna jest wlasciwoscia drugiej. Widze to tak ze z pierwszej kolekcji wrzucaja mi sie sciezki i dla tego samego wiersza w combobox w kolumnie w datagrid pokazuja nam sie tagi.

Moze cos Wam pomoze ten kod abyscie mogli mnie pomoc ;)

0

Moze sie uda ;)

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