populate dropdown list from a list of objects - c#

In an attempt of building a 3-tier architecture c# asp.net application, I've started building a class that is database which is used for the connecting to the database, another class that is City which has a method for each column in the table cities, and a Cities class in which I have the GetCities method that creates a list of City objects and then use the DataSource wizard to set the control to use the data from GetCities().
All I get is blanks in the dropdown list. Any idea why?
public List<City> GetCities()
{
List<City> cities = new List<City>();
Database db = new Database();
SqlConnection conn = db.GetConnection();
String sql = "SELECT * FROM CITIES";
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
City c = new City(reader.GetInt32(0), reader.GetString(1).ToString());
cities.Add(c);
}
db.CloseConnection();
return cities;
}
thanks

Did you set the DataTextField, DataValueField properties, and call DataBind?
At this point I would try to get the concept working as simply as possible, and then start adding things back in until you locate the problem. Start with a brand new page, add a DropDownList but don't touch the data source or change any properties, go directly into the codebehind and add this in Page_Load:
DropDownList1.DataValueField = "ID";
DropDownList1.DataTextField = "Name";
DropDownList1.DataSource = new[] {
new { ID = 1, Name = "Alice" },
new { ID = 2, Name = "Mike" },
new { ID = 3, Name = "John" }
};
DropDownList1.DataBind();
Does it work? It does for me. Then try to change DataValueField, DataTextField, and DataSource to work with your customer list. Is it broken now? Then you know the problem is in the customer list somewhere, not with the way you're binding the data.

Have you called DataBind() method on the object you want to be populated ?

The issue resided in the City class which after a close inspection I've realised that the constructor was assigning the parameter received incorrectly. It's now working. Thanks!
public class City
{
int id;
string name;
public City(int id, string name)
{
this.id = id;
this.name = name;
}
public int Id
{
get { return id; }
set { id = value; }
}
public String Name
{
get { return name; }
set { name = value; }
}
}

Related

How can I add new row to database with values stored in ObservableCollection?

So I have two ObservableCollections:
ObservableCollection<Student> studentslist
ObservableCollection<Subject> subjectslist
and I'm passing them to class where I have set up whole communication with sql database.
studentslist contains values passed by:
StudentsList.Add(new Student { IdStudent = newStudentId, Name = NameBox.Text, Surname = SurnameBox.Text, Index = IndexBox.Text })
subjectlist contains values from checked checkboxes in my listbox (I'm still not sure if this is correct):
var selectedSubjects = SubjectList.Where(subjects => subjects.IsChecked == true);
var selectedSubjectsCollection = new ObservableCollection<Subject>(selectedSubjects);
and this is my Subject class:
public class Subject
{
public int IdSubject{ get; set; }
public string subject{ get; set; }
public bool IsChecked { get; set; }
public override string ToString()
{
return $"{subject}";
}
}
Now in my class, responsible for connection with sql data base, I've created method which grabs both of this collections and based on their values I would like to create new record in database:
public void addRecord(ObservableCollection<Student> studentslist, ObservableCollection<Przedmiot> subjectslist)
{
OpenConection();
//...
CloseConnection();
}
In database I have Student table:
Student(IdStudent, FirstName, LastName, IndexNumber)
and Subject table:
Subject(IdSubject, Name)
And as far as I can read data from my data base, I don't know how in correct way pass these values to corresponding values in data base.
I like to do this kind of thing using stored procedures to minimise the amount of T-SQL code in the app.
An example would be:
public static void InsertSubject(Przedmiot subject)
{
using (SqlConnection conn = new SqlConnection("Connection String"))
{
try
{
SqlCommand command = new SqlCommand("dbo.InsertSubject", conn) { CommandType = CommandType.StoredProcedure };
command.Parameters.Add(new SqlParameter("#IdSubject", subject.IdSubject));
command.Parameters.Add(new SqlParameter("#Name", subject.subject));
conn.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
// handle exceptions
}
}
}
You would then have a stored procedure with the same signature to perform the INSERT, i.e.:
CREATE PROCEDURE dbo.InsertSubject
#IdSubject int
, #Name varchar(50)
AS
...
GO
If you want to pass in the entire collection you could implement a foreach loop in the above example.
Personally I like to call these methods once per insert and have it as an int returning method (for example) so I can pass some data out, e.g., the ID of the inserted row.

bind data on dropdownlist

I'm trying run this code
private void LoadProdName()
{
con.Open();
cmd = new SqlCommand(#"SELECT productName
FROM Products3
WHERE productType = #Type",con);
cmd.Parameters.AddWithValue("#Type",ddlProducts.SelectedItem.Value.ToString());
da = new SqlDataAdapter(cmd);
dt = new DataTable();
da.Fill(dt);
ddlProdName.DataSource = dt;
ddlProdName.DataBind();
con.Close();
}
my selectedIndesChange codes:
protected void ddlProducts_SelectedIndexChanged(object sender, EventArgs e)
{
LoadProdName();
}
which uses the value of my first dropdownlist.My problem is whenever I select a ProductType on my dropdownlist it will fill my second DDL with the select query but I am not getting any data at all from my second dropdownlist.
Now I'm getting some progress.
This is what I get now:
For cascade drowdownlist you must do a postback in your dropdownlist event "OnSelectedIndexChanged" or use an AJAX call to your method
try this guide: http://www.aspsnippets.com/Articles/Creating-Cascading-DropDownLists-in-ASP.Net.aspx
try this code after your query
ddlProdName.DataSource = cmd.ExecuteReader();
ddlProdName.DataTextField = "productName";
ddlProdName.DataValueField = "productName"; //or productId
ddlProdName.DataBind();
In your case, you will want to do:
ddlProdName.DataTextField = "productName"; //this is the name of column that's in your datatable.
ddlProdName.DataValueField = "productName";
If you are specifying anything other than collection of simple data type as the data source, you will need to specify the DisplayMember and ValueMember (in winforms) and DataTextField and DataValueField (in webforms, from Sergio's answer) property of the combobox so that it knows which property to display and which should be used as value.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
DataColumn prodName = new DataColumn("Products");
dt.Columns.Add(prodName);
dt.Rows.Add("a");
dt.Rows.Add("b");
dt.Rows.Add("c");
comboBox1.DataSource = dt;
comboBox1.DisplayMember = "Products";
comboBox1.ValueMember = "Products";
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}

C# access List after return

I'm a noob with C# but I'm trying to create a simple code for connecting to my mysql database (most of the code I got from google). So I have this part where something from the database is selected and stored in a list. Now I want to access this from another class but I have no idea how to do that and I couldn't find the answer on google either (this thread also didn't worked for me: Access List from another class) so can anyone please help me?
Here's the particular code:
public List<string>[] Select()
{
string query = "SELECT * FROM users";
//Create a list to store the result
List<string>[] list = new List<string>[3];
list[0] = new List<string>();
list[1] = new List<string>();
list[2] = new List<string>();
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
MySqlCommand cmd = new MySqlCommand(query, connection);
//Create a data reader and Execute the command
MySqlDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
list[0].Add(dataReader["id"] + "");
list[1].Add(dataReader["test"] + "");
list[2].Add(dataReader["balance"] + "");
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
//return list to be displayed
return list;
}
else
{
return list;
}
}
Class containing your original method:
public class YourClass
{
public List<string>[] Select()
{
string query = "SELECT * FROM users";
//Create a list to store the result
List<string>[] list = new List<string>[3];
///
/// you original implementation here
///
}
}
Here Class where you use your method:
public class UsingClass
{
private YourClass _yourClass;
public UsingClass()
{
_yourClass = new YourClass();
}
private void SomeUsingMethod()
{
List<string>[] list = _yourClass.Select();
}
}
Seriously I think the way you've structured the data here, is strange.
You're creating an array of a objects, where the object is a List of string:
List<string>[] list = new List<string>[3];
You want to be thinking in objects; create a class that represents the data; in this case User. Something like this:
public class User
{
public string Id { get; set; }
public string Test { get; set; }
public string Balance { get; set; }
}
So personally I'd do the following:
Create a class that represents each user record.
Create a variable to hold a list of users.
Read from MySql and assign each record to a new User object.
Add the user to the list.
Return the list.
Change the return type of your Select method to be List<User> like this:
public List<User> Select() {
Then amend the rest of the method to create and return list of users.
public List<User> Select() {
List<User> list = new List<User>();
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
User user = new User();
user.Id = dataReader["id"].toString();
user.Test = dataReader["test"].toString();
user.Balance = dataReader["balance"].toString();
list.Add(user);
}
dataReader.Close();
this.CloseConnection();
}
return list;
}
Then you can use your list something like this:
ClassThatContainsSelectMethod yourDBObject = new ClassThatContainsSelectMethod();
List<User> users = yourDBObject.Select();
foreach (User user in users)
{
Console.WriteLine(user.Id, user.Test, user.Balance);
}
This code of course could be better structured with factories and error/null checks but it should get you going in the right direction.
There are multiple ways to share data from classes.One of them is defining a property for the desired list and then accsess it. Lets say you have class data
class DataString
{
private string data = "data";
public string Data
{
get { return data}
set { data = value }
}
}
and
class Program
{
static void Main()
{
DataString dataStr = new DataString();
// Assigning the dataStr property causes the 'set' accessor to be called.
dataStr.Data = "some string";
// Evaluating the Hours property causes the 'get' accessor to be called.
System.Console.WriteLine(dataStr.Data); //this will display "some string"
}
}
You could the same way create a list class with your desired functions and variables and modiffy them with methods and access them with properties.

How to select items and move from one list box with datasource to another?

listBox2.DataSource = listBox1.SelectedItems;
listBox2.DisplayMember = "Descripcion";
listBox2.ValueMember = "Id";
After using the above code, I am not able to select one by one. Help!
some one please post codes to remove too
First, you have to define a model for your Listbox :
public class MyModel
{
public int Id { get; set; }
public string Description { get; set; }
}
After you can set items like this :
listBox2.Items.Add(new MyModel() { Id = 1, Description = "description" });
listBox2.DisplayMember = "Description";
listBox2.ValueMember = "Id";
And now, your listbox will show the description property. If you select an item, the SelectedValue in listbox2 will be the value of id property
if (listBox1.SelectedItem != null)
{
listBox2.Items.Add(listBox1.SelectedItem);
}
listBox2.DisplayMember = "Descripcion";
listBox2.ValueMember = "Id";
this is working fine....
Use SqlDataAdapter to dump data into the listbox from the data source and based on the data selected in one of the listbox use listbox.add() method, Use a "for" loop to dump the data from one listbox to another using an index.
for(int i=0; i<listBox1.SelectedItems.Count; i++)
{
listBox2.Items.Add(listbox1.SelectedItems[i].toString());
}

Databinding in combo box

I have two forms, and a class, queries return in Stored procedure.
-- Stored Procedure:
ALTER PROCEDURE [dbo].[Payment_Join]
#reference nvarchar(20)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT p.iPaymentID
, p.nvReference
, pt.nvPaymentType
, p.iAmount
, m.nvMethod
, u.nvUsers
, p.tUpdateTime
FROM Payment p
, tblPaymentType pt
, tblPaymentMethod m
, tblUsers u
WHERE p.nvReference = #reference
and p.iPaymentTypeID = pt.iPaymentTypeID
and p.iMethodID = m.iMethodID
and p.iUsersID = u.iUsersID
END
// payment.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace Finance {
class payment {
string connection = global::Finance.Properties.Settings.Default.PaymentConnectionString;
#region Fields
int _paymentid = 0;
string _reference = string.Empty;
string _paymenttype;
double _amount = 0;
string _paymentmethod;
string _employeename;
DateTime _updatetime = DateTime.Now;
#endregion
#region Properties
public int paymentid
{
get { return _paymentid; }
set { _paymentid = value; }
}
public string reference
{
get { return _reference; }
set { _reference = value; }
}
public string paymenttype
{
get { return _paymenttype; }
set { _paymenttype = value; }
}
public string paymentmethod
{
get { return _paymentmethod; }
set { _paymentmethod = value; }
}
public double amount
{
get { return _amount;}
set { _amount = value; }
}
public string employeename
{
get { return _employeename; }
set { _employeename = value; }
}
public DateTime updatetime
{
get { return _updatetime; }
set { _updatetime = value; }
}
#endregion
#region Constructor
public payment()
{
}
public payment(string refer)
{
reference = refer;
}
public payment(int paymentID, string Reference, string Paymenttype, double Amount, string Paymentmethod, string Employeename, DateTime Time)
{
paymentid = paymentID;
reference = Reference;
paymenttype = Paymenttype;
amount = Amount;
paymentmethod = Paymentmethod;
employeename = Employeename;
updatetime = Time;
}
#endregion
#region Methods
public void Save()
{
try
{
SqlConnection connect = new SqlConnection(connection);
SqlCommand command = new SqlCommand("payment_create", connect);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#reference", reference));
command.Parameters.Add(new SqlParameter("#paymenttype", paymenttype));
command.Parameters.Add(new SqlParameter("#amount", amount));
command.Parameters.Add(new SqlParameter("#paymentmethod", paymentmethod));
command.Parameters.Add(new SqlParameter("#employeename", employeename));
command.Parameters.Add(new SqlParameter("#updatetime", updatetime));
connect.Open();
command.ExecuteScalar();
connect.Close();
}
catch
{
}
}
public void Load(string reference)
{
try
{
SqlConnection connect = new SqlConnection(connection);
SqlCommand command = new SqlCommand("Payment_Join", connect);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#Reference", reference));
//MessageBox.Show("ref = " + reference);
connect.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
this.reference = Convert.ToString(reader["nvReference"]);
// MessageBox.Show(reference);
// MessageBox.Show("here");
// MessageBox.Show("payment type id = " + reader["nvPaymentType"]);
// MessageBox.Show("here1");
this.paymenttype = Convert.ToString(reader["nvPaymentType"]);
// MessageBox.Show(paymenttype.ToString());
this.amount = Convert.ToDouble(reader["iAmount"]);
this.paymentmethod = Convert.ToString(reader["nvMethod"]);
this.employeename = Convert.ToString(reader["nvUsers"]);
this.updatetime = Convert.ToDateTime(reader["tUpdateTime"]);
}
reader.Close();
}
catch (Exception ex)
{
MessageBox.Show("Check it again" + ex);
}
}
#endregion
}
}
I have already binded the combo box items through designer,
When I run the application I just get the reference populated in form 2 and combo box just populated not the particular value which is fetched. New to c# so help me to get familiar
Assuming WinForms...
The ComboBox control has three properties to be used while using DataBinding.
DataSource;
DisplayMember;
ValueMember.
DataSource
A data source can be a database, a Web service, or an object that can later be used to generate data-bound controls. When the DataSource property is set, the items collection cannot be modified.
DisplayMember
The controls that inherit from ListControl can display diverse types of objects. If the specified property does not exist on the object or the value of DisplayMember is an empty string (""), the results of the object's ToString method are displayed instead.
If the new display member cannot be set, the previous display member setting is maintained.
ValueMember
Specify the contents of the ValueMember property in cases where you bind data.
You can clear the ValueMember property by setting the property to an empty string ("") or a null reference (Nothing in Visual Basic).
Setting a new ValueMember property raises the ValueMemberChanged and SelectedValueChanged events.
Now, the result of your stored procedure shall get stored in memory in an IList, BindingList<T> or any other bindable collection.
This collection should be set as the DataSource of your ComboBox. The best approach, in my opinion, is through a BindingSource.
Here's an example:
public partial class Form1 : Form {
private BindingSource bindingSource1;
public Form1() {
InitializeComponent();
bindingSource1 = new BindingSource();
comboBox1.DataSource = bindingSource1;
comboBox1.DisplayMember = "PaymentMethod";
comboBox1.ValueMember = "PaymentId";
bindingSource1.DataSource = GetPayments(); // GetPayments() shall return one of the above-mentioned bindable collections of payments.
}
}
Check if this helps you.

Categories

Resources