I am working on a cascading drop-down for Country and City, which is working fine for now but I need to add other city
as last value to the second drop down (City DD) irrespective of what country user selects. i am not able to make it work like a normal add operation to list.
public CascadingDropDownNameValue[] FetchCities(string knownCategoryValues, string category)
{
string CountryCode;
StringDictionary strCountries = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
CountryCode = strCountries["Country"].ToString();
con.Open();
SqlCommand cmd = new SqlCommand("select * from Cities where Country=@Code Order by CityName ", con);
cmd.Parameters.AddWithValue("@Code", CountryCode);
cmd.ExecuteNonQuery();
SqlDataAdapter dastate = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
dastate.Fill(ds);
con.Close();
List<CascadingDropDownNameValue> states = new List<CascadingDropDownNameValue>();
foreach (DataRow dtRow in ds.Tables[0].Rows)
{
string StateID = dtRow["CityID"].ToString();
string StateName = dtRow["CityName"].ToString();
states.Add(new CascadingDropDownNameValue(StateName, StateID));
}
return states.ToArray();
}
Above code is a sample code I am following this tutorial s for Cascading drop-down
you can do this without touching your code.. simply add into the table "Cities" new row
Country = "xxx"
CityName = "ZZZ: other country"
and then update your SQL:
SqlCommand cmd = new SqlCommand("select * from Cities where Country=@Code OR Country='xxx' Order by CityName ", con);
the ZZZ
at the beginning is just to make sure it is always at the end when order by CityName
Why not pass it as a list to the function (i don't like returning lists) as return values. This way you're in control what happens to the list after getting the database values.
public void Fill()
{
List<CascadingDropDownNameValue> cities = new List<CascadingDropDownNameValue>();
FetchCities(cities, knownCategoryValues, category);
cities.Add(new CascadingDropDownNameValue("new city", "0"));
}
public void FetchCities(List<CascadingDropDownNameValue> values, string knownCategoryValues, string category)
{
string CountryCode;
StringDictionary strCountries = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
CountryCode = strCountries["Country"].ToString();
con.Open();
SqlCommand cmd = new SqlCommand("select * from Cities where Country=@Code Order by CityName ", con);
cmd.Parameters.AddWithValue("@Code", CountryCode);
cmd.ExecuteNonQuery();
SqlDataAdapter dastate = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
dastate.Fill(ds);
con.Close();
List<CascadingDropDownNameValue> states = new List<CascadingDropDownNameValue>();
foreach (DataRow dtRow in ds.Tables[0].Rows)
{
string StateID = dtRow["CityID"].ToString();
string StateName = dtRow["CityName"].ToString();
values.Add(new CascadingDropDownNameValue(StateName, StateID));
}
}
UPDATE : Another nice approach would be returning IEnumerable< CascadingDropDownNameValue>
public void Fill()
{
List<CascadingDropDownNameValue> cities = new List<CascadingDropDownNameValue>();
cities.AddRange(FetchCities(connectionString, knownCategoryValues, category));
cities.Add(new CascadingDropDownNameValue("new city", "0"));
}
public IEnumerable<CascadingDropDownNameValue> FetchCities(string connectionString, string knownCategoryValues, string category)
{
StringDictionary strCountries = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
string CountryCode = strCountries["Country"].ToString();
using (SqlConnection con = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand("select * from Cities where Country=@Code Order by CityName ", con))
{
cmd.Parameters.Add("@Code", SqlDbType.VarChar).Value = CountryCode;
using (SqlDataReader reader = cmd.ExecuteReader())
while (reader.Read())
{
string StateID = reader["CityID"].ToString();
string StateName = reader["CityName"].ToString();
yield return new CascadingDropDownNameValue(StateName, StateID);
}
}
}
The advantage is that it will stream the rows and transform them to objects when needed. This will give the advantage that if you only want a top 10. It won't get more rows from the sql-server. (except for some row caching/block reads)
DataSet.Fill
would get all rows before returning objects. So if that table contains +1m rows. It will first create a DataTable with 1m rows and then returning them in objects.
The reason i pass the connectionstring to it, is to allow more open recordsets. (one open recordset per connection)
In this case the cities.AddRange
will iterate all rows. To add only a top 10 would be:
var cities = FetchCities(connectionString, knownCategoryValues, category).Take(10);
cities.AddRange(cities);
Good luck.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.