ComboBox - wybór z tabeli i filtrowanie

0

Witam

Posiadam dwa comboboxy - jeden zawiera Markę samochodu, drugi Model - dane do odpowiednich comboboxów pobieram z bazy.

Tabela Auta zawiera id, marka, model itd; osobne tabele z marką i modelem służą do wstawiania wartości do bazy.

Na podstawie wyżej wymienionych comboboxów chciałbym zrobić wyszukiwanie w tabeli Auta, w taki sposób, że w comboboxach byłyby do wybrania tylko wartości, które już są w tabeli Auta - czyli w ComboBoxMarka wybieram jakąkolwiek wartość z już wprowadzonych danych do tabeli, do ComboBoxModel wybieram model zależny od wybranej marki, tylko jak to zrobić ? Co mi przychodzi do głowy to sprawdzic jaka jest wartosc w ComboBoxMarka i zrobic SELECTA z warunkiem, gdzie dana marka = ... Tylko też nie wiem w jaki sposób sprawdzić która wartość jest wybrana w ComboBoxMarka?

Bede wdzieczny za jakąkolwiek pomoc w tej sprawie, najlepiej z przykładowym kodem :)

0

przechwyc na comboBox z markami SelectedIndexChanged - zostanie wywolane kiedy ktos wyberze inna wartosc w tym combo
teraz wez np. SelectedItem
zrob zapytanie do bazy zeby wybrac modele przefiltrowane po marce (jesli masz masze ms sql uzyc namespace System.Data.SqlClient, tam masz m.in. SqlConnectionn i SqlCommand (jesli innej bazy, poszukaj odpowiedniego providera, tez bedzie tam connection i command z innym prefixem)
po pobraniu danych z bazy podepnij je jako DataSource do drugiego combo (ustaw tylko wczesniej ValueMember i DisplayMember)

0

Wszystko można zrobic na lokalnym datasecie bez ciaglego odwolywania sie do bazy. Trzeba tylko odpowiednio poustawiac relacje pomiędzy tabelami. Tu masz przykład; http://4programmers.net/Forum/467300?h=#id467300

0

massther - masz moze jakis przykladowy kod jak to zrobic z SelectedIndexChanged ?

Marcin.Miga - to by zadzialalo gdybym chcial pobierac dane z 2 oddzielnych tabel a ja chce z 1

0

mozemy wyobrazic sobie 2 scenariusze, zalezy od tego ile bedzie danych w tabeli Auta

  1. jesli malo
    raz laczymy sie do bazy i pobieramy zawartosc Auta do np. DataTable (ewentualnie mozemy pomyslec nad jakims mechanizmem co jakis czas odswiezajacym nam te dane)
  2. jesli danych jest duzo
    proponuje jednak po zmainie marki laczyc sie za kazdym razem do bazy zeby wybrac modele
    z moich doswiadczen wynika ze jesli polaczenie do bazy jest dosc szybkie, np. dlatego ze aplikacja (web) stoi na tej samej maszynie co sql srv to jest to wydajny mechanizm

wiec zaproponuje rozwiazanie 2:

w Page_Load
if (!Page.IsPostBack)
GetAllCarBrands();

void GetAllCarBrands()
{
SqlConnection conn = new SqlConnection(myConnStr);
SqlCommand comm = new ("select distinct marka from Auta", conn);
SqlDataReader r = null;
try
{
conn.Open();
r = comm.ExecuteReader();
comboBrands.DisplayMember = "marka";
comboBrands.ValueMember = "marka";
comboBrands.DataSource = r;
}
catch()
{/jakis komunikat dla usera/}
finally
{
if (r!=null && !r.IsClosed) r.Close();
conn.Close();
}
}

przykladowa deklaracja DropDownList w kodzie strony z obsluga zdarzenia SelectedIndexChanged
<asp:DropDownList ID="DropDownList1" runat="server" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"></asp:DropDownList>

teraz w code behind masz metode:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(myConnStr);
SqlCommand comm = new ("select distinct model from Auta where marka=@marka", conn);
comm.Parameters.Add("@marka", SqlDbTypes.NVarChar).Value = comboBrandes.SelectedValue;
SqlDataReader r = null;
try
{
conn.Open();
r = comm.ExecuteReader();
comboModels.DisplayMember = "model";
comboModels.ValueMember = "model";
comboModels.DataSource = r;
}
catch()
{/jakis komunikat dla usera/}
finally
{
if (r!=null && !r.IsClosed) r.Close();
conn.Close();
}

}

pisane z palca, wiec moga byc literowki i bledy, ale z grubsza to tak powinno byc :)

0

dzikie massther :) zrobilem to tak (na windows forms) i prawie działa:

        public void ComboSelectMarka()
        {
            SqlConnection conn = new SqlConnection(sqlConIP);
           
            try
            {

                // open connection
                conn.Open();

                string query = "SELECT DISTINCT Marka FROM Cars";

                // pass the connection to sql object
                SqlCommand cmd = new SqlCommand(query, conn);

               
                // creating sql data adapter
                SqlDataAdapter adp = new SqlDataAdapter(cmd);

                // creating a dataset
                DataSet ds = new DataSet();

                // filling the bind in datagrid
                adp.Fill(ds, "Cars");
                conn.Close();
            
                DataTable oDataTable = ds.Tables["Cars"];

                comboBox1.DisplayMember = "Marka";
                comboBox1.ValueMember = "Marka";

                foreach (DataRow oRow in oDataTable.Rows)
                {
                    comboBox1.Items.Add(oRow["Marka"]);
                }
                comboBox1.SelectedIndexChanged += new System.EventHandler(DropDownList1_SelectedIndexChanged);
                }

            finally
            {
                // closer the connection
                if (conn != null)
                    conn.Close();
            }
        }

        protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
        {
            SqlConnection conn = new SqlConnection(sqlConIP);

            try
            {
                // open connection
                conn.Open();

                string query = "SELECT DISTINCT Model FROM Cars WHERE Marka=@Marka";

                // pass the connection to sql object
                SqlCommand cmd = new SqlCommand(query, conn);

                cmd.Parameters.AddWithValue("Marka", comboBox1.Text);

                // creating sql data adapter
                SqlDataAdapter adp = new SqlDataAdapter(cmd);

                // creating a dataset
                DataSet ds = new DataSet();

                // filling the bind in datagrid
                adp.Fill(ds, "Cars");
                conn.Close();

                DataTable oDataTable = ds.Tables["Cars"];

                comboBox2.DisplayMember = "Model";
                comboBox2.ValueMember = "Model";

                foreach (DataRow oRow in oDataTable.Rows)
                {
                    comboBox2.Items.Add(oRow["Model"]);
                }
            }

            finally
            {
                // closer the connection
                if (conn != null)
                    conn.Close();
            }
        }

Prawie działa, ponieważ po wybraniu danej marki pojawiaja sie te modele co trzeba ale gdy wybiore kolejna marke to do modeli dopisuja sie kolejne modele dla tej marki itd powieksza sie lista modeli, czego uzyc zeby po wybraniu kolejnej marki modele sie uzupelnialy od nowa ???

0

No nie za dobrze. Ileż może być modeli aut ? Zaledwie kilka tysięcy.

Zapakuj wszystko do DataTable:

tabela = new DataTable("Cars");
dataAdapter =  new SqlDataAdapter("SELECT * FROM Cars", polaczenie_z_baza);
dataAdapter.Fill(tabela);

Podepnij tabele pod combo:

comboBox2.DataSource = tabela;
comboBox2.DisplayMember = "Model";

W momencie wyboru marki (SelectedIndexChanged) ustaw filtr domyślnego widoku:

tabela.DefaultView.RowFilter = String.Format("marka='{0}'", comboBox1.Text);

I to wszystko.

0

kiedy uzywasz comboBox2.Items.Add(oRow["Model"]);
to .net sam nie wyczysci kolekcji poprzednich Items - uzyc przed forem metody Items.Clear()
lub zamiast Items.Add ustawa DataSource

jesli chodzi o propozycje adf88 - to jak pisalem wczeniej bedzie to ok, przy malej ilosci danych (czyli na oko cos kolo kilkuset do kilku tys. zaleznie od maszyny na ktorej bedzie chodzilo)
no i oczywiscie dane pobierzesz raz, wiec kiedy pojawia sie nowe rekordy ty ich nie bedziesz mial

0

Dzieki wam za rozwiazanie problemu :)

Jeszcze krotkie pytanie, ktore tu zadam: jak w jedenej z kolumn wyswietlanych w datagridview moge przechowywac odnosniki do stron www, ktore po kliknieciu sie otworza ??

0

w DataGridView kolumna typu DataGridViewLinkColumn

lapisz zdarzenie CellContentClick

ja tu nie sprawdzam czy bylo klikniecie w kolumne z linkiem, ale jesli parsowanie Uri sie wylozy, to nie bedzie proby otwarcia stronki
mozesz albo sprawdzic sobie kolumne po typie, albo gdzies pamietac w ktore kolumny klikniecia chcesz obslugiwac, raczej sugeruje kodowanie czego innego w warunku niz indexu, bo jak zaczniesz dodawac/usuwac kolumny zaraz okaze sie ze cos nie dziala
proponuje raczej np. dataGridView1.Columns[e.ColumnIndex].Name lub po DataPropertyName

    private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        Uri myUri;
        if (Uri.TryCreate(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString(), UriKind.Absolute, out myUri))
            System.Diagnostics.Process.Start(myUri.AbsoluteUri);
        else
            MessageBox.Show("Bledny adres");
    }

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