How to set first index as blank in combobox - c#

I have a combobox that is bound with a datasource. In this combobox I have to add a blank field at index 0.
I have written following code for getting records.
public List<TBASubType> GetSubType(int typ)
{
using (var tr = session.BeginTransaction())
{
try
{
List<TBASubType> lstSubTypes = (from sbt in session.Query<TBASubType>()
where sbt.FType == typ
select sbt).ToList();
tr.Commit();
return lstSubTypes;
}
catch (Exception ex)
{
CusException cex = new CusException(ex);
cex.Write();
return null;
}
}
}
After this it bind with combobox with data binding source as below code.
M3.CM.BAL.CM CMobj = new M3.CM.BAL.CM(wSession.CreateSession());
lstSubTypes = CMobj.GetSubType(type);
this.tBASubTypeBindingSource.DataSource = lstSubTypes;

If you just want to select nothing initially, you can use
comboBox1.SelectedIndex=-1;

Thus you can't modify Items when you are are bound to DataSource, then only option to add blank row is modifying your data source. Create some empty object and add it to data source. E.g. if you have list of some Person entities bound to combobox:
var people = Builder<Person>.CreateListOfSize(10).Build().ToList();
people.Insert(0, new Person { Name = "" });
comboBox1.DisplayMember = "Name";
comboBox1.DataSource = people;
You can define static property Empty in your class:
public static readonly Person Empty = new Person { Name = "" };
And use it to insert default blank item:
people.Insert(0, Person.Empty);
This also will allow to check if selected item is default one:
private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
Person person = (Person)comboBox.SelectedItem;
if (person == Person.Empty)
MessageBox.Show("Default item selected!");
}

cboCustomers.Items.Add(""); // Just add a blank item first
// Then load the records from the database
try
{
OleDbConnection con = new OleDbConnection(strDBConnection);
OleDbCommand cmd = new OleDbCommand();
con.Open();
cmd.Connection = con;
cmd.CommandText = "SELECT * FROM Customers";
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
cboCustomers.Items.Add(dr["Name"]);
}
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

After creating my combo boxes, I added these lines to the end of the Load() method:
private void xyz_Load(object sender, EventArgs e)
{
this.xyzTableAdapter.Fill(this.DataSet.xyz);
this.comboBoxXYZ.SelectedIndex = -1;
}
replace xyz with the names you've given to your controls

Related

C# Button with multiple events

I am trying to overwrite a content in an label several times by always clicking the same button. Unfortunately, I only know how to override it once.
The problem I am facing is that the data in the label are from an SQL database and it only displays the data with ID = 1 in the label.
This is my code:
MySqlConnection conn = new MySqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString); // Connectionstring to the database
public MainWindow()
{
InitializeComponent();
}
private void btContinue_Click(object sender, RoutedEventArgs e)
{
try
{
conn.Open();
MySqlCommand cmd = new MySqlCommand("SELECT l_question from l_liescale", conn);
MySqlDataAdapter adp = new MySqlDataAdapter(cmd);
DataSet ds = new DataSet();
lbquestion.Content = cmd.ExecuteScalar(); //here I get the data into the label
}
catch (MySqlException ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
conn.Close();
}
}
}
Is there a way to display every data record from the database in one label and always overwriting it with the next record by clicking the button?
You should use ExecuteReader() instead of ExecuteScalar() to retrieve collection of data.
StringBuilder sb = new StringBuilder();
using(var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var question = reader[0].ToString();
sb.AppendFormat("Q: {0}\n", question); // use any other format if needed
}
}
lbquestion.Content = sb.ToString();
But the better way is to use ItemsControl or ListBox or other list-controls.
If you want to iterate by clicking the button you can retrieve all records to the memory and then iterate it in the event handler:
private readonly List<string> _questions;
private int currentIndex = -1;
public MainWindow()
{
InitializeComponent();
_questions = GetQuestionsByDataReader();
}
private void btContinue_Click(object sender, RoutedEventArgs e)
{
if(currentIndex < _questions.Count)
{
lbquestion.Content = _questions[++currentIndex];
}
}

Filtering WPF TreeView without using Observable Collection

I am filling my TreeView from MySQL database. So I don't have classes for each of them. I use HierarchicalDataTemplates to construct TreeView and I have three levels. I want to filter the first levels comparing the included TextBlock's Text and user input. How can I filter without using ObservableCollection? (I tried to use ICollectionView, but I failed.)
Source = CollectionViewSource.GetDefaultView(FileTreeView.ItemsSource);
this.Source.Filter = item =>
{
TreeViewItem vitem = item as TreeViewItem;
if (vitem == null) return false;
foreach (object items in vitem.Items)
{
vitem.ApplyTemplate();
TreeViewItem firstlevel = vitem.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
UIElement element = GetChildControl(firstlevel, "fem_title");
if (element != null)
{
TextBlock txt = (TextBlock)element;
return (txt.Text.Contains(title.SelectedValue.ToString()));
}
}
return false;
It throws an "NotSupportedException".
How I populate the TreeView:
private DataSet FillDataGrid()
{
try
{
MySqlConnection con = new MySqlConnection();
con.ConnectionString = ConString;
con.Open();
MySqlDataAdapter femda = new MySqlDataAdapter("SELECT * FROM fem_table", con);
MySqlDataAdapter versionda = new MySqlDataAdapter("SELECT * FROM version_table", con);
MySqlDataAdapter fileda = new MySqlDataAdapter("SELECT * FROM file_table", con);
DataSet ds = new DataSet();
femda.Fill(ds, "fem_table");
versionda.Fill(ds, "version_table");
fileda.Fill(ds, "file_table");
DataRelation dr = new DataRelation("DataRelationship_fem_version",
ds.Tables["fem_table"].Columns["fem_guid"],
ds.Tables["version_table"].Columns["fem_table_fem_guid"],
true);
DataRelation dr2 = new DataRelation("DataRelationship_version_file",
ds.Tables["version_table"].Columns["version_id"],
ds.Tables["file_table"].Columns["version_table_version_id"],
true);
dr.Nested = true;
ds.Relations.Add(dr);
ds.Relations.Add(dr2);
return ds;
}
catch (Exception ex)
{ throw new Exception(ex.Message); }
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.FileTreeView.DataContext = FillDataGrid();
}
Filter works with underlying data, not with UIElements. Since you don't use classes to represent TreeViewItem and populate them just with string, then your item is actually a string.
This works:
public partial class MainWindow : Window
{
public List<string> Test = new List<string>() { "test", "someothertext" };
public MainWindow()
{
InitializeComponent();
treeView.ItemsSource = Test;
var Source = CollectionViewSource.GetDefaultView(treeView.ItemsSource);
string search_text = "test";
Source.Filter = item =>
{
return item.ToString().Contains(search_text);
};
}
}
I didn't understand if you use multiple textboxes to filter, but if you dont you should just give a name to one and use its text like
string search_text = txtbox.Text;

Insert DataGridView values into MySql database. c#

I want to add new values to MySql database from dataGridView1. The code itself appears to be correct, no errors in Visual Studio 2012, but there is no data inserted in my db.
Here's the code I'm using:
private void button2_Click(object sender, EventArgs e)
{
confirm exec = new confirm();
}
public class confirm
{
public void method(DataGridViewCellEventArgs f)
{
DataGridView dataGridView1 = new DataGridView();
Label label1 = new Label(); // contains User ID which is used for payer_code
Label label6 = new Label(); // contains current dayTime
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if ((bool)dataGridView1.Rows[f.RowIndex].Cells["paidDataGridViewTextBoxColumn"].Value == true)
{
try
{
string MyConnectionString = "Server=localhost; Database=contractsdb; Uid=root; Pwd=";
MySqlConnection connection = new MySqlConnection(MyConnectionString);
MySqlCommand cmd = new MySqlCommand();
cmd = connection.CreateCommand();
connection.Open();
cmd.CommandText = "INSERT INTO payments(pay_name, pay_code, payer_code, pay_sum, pay_date)VALUES(#pay_name, #pay_code, #payer_code, #pay_sum, #pay_date)";
cmd.Parameters.AddWithValue("#pay_name", dataGridView1.Rows[f.RowIndex].Cells["contractnameDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#pay_code", dataGridView1.Rows[f.RowIndex].Cells["contractcodeDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#payer_code", label1.Text);
cmd.Parameters.AddWithValue("#pay_sum", dataGridView1.Rows[f.RowIndex].Cells["sumDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#pay_date", label6.Text);
cmd.ExecuteNonQuery();
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}
I think you are misunderstanding something about OOP. Do it like this:
your confirm class method should also have the reference of datagridview1 (you are creating an empty datagridview so it never goes even into the foreach loop)
public void method(DataGridView datagridview1) //remove your first argument, you don't need it anymore
{
//delete the line "DataGridView dataGridView1 = new DataGridView();"
//and keep the rest of the code as it is
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if(row.Cells["paidDataGridViewTextBoxColumn"].Value == true) //it will check every row, and you don't need "DataGridViewCellEventArgs" argument now
{
try
{
//your code, it will be same here
}
}
}
for calling the method:
(use the same button_click event as you were doing)
private void button2_Click(object sender, EventArgs e)
{
confirm exec = new confirm();
exec.method(datagridview1); //pass "datagridview1" reference
}
It will pass the reference of your original datagridview1 to the confirm class.

Getting data from MS Access database and display it in a listbox

How do I read data in ms access database and display it in a listbox. I have the codes here but i got errors.
private void button3_Click(object sender, EventArgs e)
{
using (OleDbConnection conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\Sisc-stronghold\mis!\wilbert.beltran\DataBase\DataStructure.accdb"))
using(OleDbCommand cmd = new OleDbCommand(" SELECT * from TableAcct", conn))
{
conn.Open();
OleDbDataReader Reader = cmd.ExecuteReader();
//if (Reader.HasRows)
if (Reader.HasRows)
{
Reader.Read();
listBox1.Text = Reader.GetString("FirstName");
}
}
the errors are here:
1. Error 1 The best overloaded method match for'System.Data.Common.DbDataReader.GetString(int)' has some invalid arguments.
2. Error 2 Argument '1': cannot convert from 'string' to 'int'
try this one,
List<String> firstName = new List<String>();
List<String> lastName = new List<String>();
private void loadButton_Click(object sender, EventArgs e)
{
cn.Open();
OleDbDataReader reader = null;
cmd = new OleDbCommand("select* from Records", cn);
reader = cmd.ExecuteReader();
while (reader.Read())
{
firstName.Add(reader["FirstName"].ToString());
lastName.Add(reader["LastName"].ToString());
}
cn.Close();
}
then in your search button, insert this,
private void searchButton_Click(object sender, EventArgs e)
{
clearSearchResult();
try
{
int totalItems = FirstName.Count;
int count = 0;
while (count < totalItems)
{
if (textBox6.Text == FirstName[count].ToString())
{
listBox1.Items.Add(FirstName[count].ToString());
count = 100;
}
else
{
count++;
}
It's good to use when you want to show the information of the "FirstName" in the listBox1_SelectedIndexChanged if you want. here's an example,
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
int totalItems = lastName.Count;
int count = 0;
while (count < totalItems)
{
if ((listBox1.SelectedItem.ToString()) == firstName[count].ToString()))
{
textBox1.Text = firstName[count].ToString();
textBox2.Text = lastName[count].ToString();
count = 100;
}
else
{
count++;
}
}
hope this helps,
change
listBox1.Text = Reader.GetString("FirstName");
to
listBox1.Text = Reader.GetString(0); // zero base ordinal of column
GetString() takes an int as the parameter and not a string. Meaning that you must use the index of the column.
In your specific circumstance as "FirstName" is the second column the index would be 1:
listBox1.Text = Reader.GetString(1);
http://msdn.microsoft.com/en-us/library/system.data.oledb.oledbdatareader.getstring.aspx
Thy using a While loop
while(reader.Read())
{
listbox1.Items.Add(reader["FirstName"]);
}
This moves through all the rows you selected. reader.Read() returns false if there are no more rows.
Also: if you Want to retrive valmue from a column I suggest you do it with the index ón the reader instance. Like my example.
var value = reader["ColumnName"];
This increases readability comparing to
var value = reader.GetString(0);
UPDATE
If you want to only display the fist value - I suggest you use cmd.ExecuteScalar() and the adapt you sql to only return the value you need:
using(OleDbCommand cmd = new OleDbCommand("SELECT firstname from TableAcct", conn))
{
conn.Open();
var firstName = cmd.ExecuteScalar();
}
Be aware the this will give you the first "FirstName" in the table. And since there is no "order by firstname" or "where someKey = 1" - this might not rturn that you expected.
If you want to create MS Access data base and to access it, and to display data in some component, like here i will show you.how to connect with MS Access Data Base and display data from data base in Label.
First of all create any Access data base like here "PirFahimDataBase".
Now in your Visual Studio go to the menu and do this
Click Data
Add New Data Base
Click Next
Click New Connection
Now change the Data Source by clicking Change and select Microsoft Access data base files
Click Browse for selecting your created data base
Now in Button ClickEvent paste these code which will get data from data base and will show it in the label
using System.Windows.Forms; //these two lines should be written before namespace at top of the program
using System.Data.OleDb;
private void button1_Click(object sender, EventArgs e)
{
System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data source= C:\Users\pir fahim shah\Documents\PirFahimDataBase.accdb";
try
{
conn.Open();
MessageBox.Show("connected successfuly");
OleDbDataReader reader = null; // This is OleDb Reader
OleDbCommand cmd = new OleDbCommand("select TicketNo from Table1 where Sellprice='6000' ", conn);
reader = cmd.ExecuteReader();
while (reader.Read())
{
label1.Text= reader["TicketNo"].ToString();
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to connect to data source");
}
finally
{
conn.Close();
}
}//end of button click event
Your error is in this line:
listBox1.Text = Reader.GetString("FirstName");
You must pass a number in the GetString() function.
DataColumn[] PrimaryKeyColumn = new DataColumn[1]; //Define Primary coloumn
DataSet dataSet = new DataSet();
DataTable dataTable = new DataTable();
ReadAndUpdateExcel.ReadExcel(strPath, sheetName, out dataSet);
dataSet.Tables.Add(dataTable);
PrimaryKeyColumn[0] = dataSet.Tables[0].Columns[0];
dataSet.Tables[0].PrimaryKey = PrimaryKeyColumn;
string num = dataSet.Tables[0].Rows[dataSet.Tables[0].Rows.IndexOf(dataSet.Tables[0].Rows.Find(strTCName))]["ACNO"].ToString();
//string country

ComboBox taking 2 columns, displaying 1st using 2nd with Thread.Task

I've made a previous post that tried to use a textbox. From this I found out you can simply add an sql query results (the excute reader) to the ComboBox and then display and use the other column value.
Problem I have is I'm using a task for my form that runs a different HUGE sql query so it does not lock up my controls in my form. The problem, in detail, is that I'm using an invoke method wrapped around that control that only gets the 1st column.
public void fillmycombo()
{
SqlConnection conn1 = new SqlConnection(myConn1);
conn1.Open();
if (string.Compare(_userName, admin) == 0)
{
SqlCommand accountFill = new SqlCommand("SELECT name, FROM dbo.Customer", conn1);
SqlDataReader readacc = accountFill.ExecuteReader();
while (readacc.Read())
{
AddItem(readacc.GetString(0).ToString());
//accCollection.DataSource = readacc;
//accCollection.DisplayMember = "name";
//accCollection.ValueMember = "keycode";
}
conn1.Close();
}
}
this method as you can see gets the name.
private void AddItem(string value)
{
if (accCollection.InvokeRequired)
{
accCollection.Invoke(new Action<string>(AddItem), new Object[] { value });
}
else
{
accCollection.Items.Add(value);
}
}
as you can see im using the invoke method to wrap the control for use in my method that is on the task.
private void button1_Click_1(object sender, EventArgs e)
{
checkBox1.Checked = true;
string acct = accCollection.Text;
Task t = new Task(() => GetsalesFigures(acct));
t.Start();
}
this runs the task that calls my giant query method.
private void getsalesfigures(string acct)
{
string acct;// test using 1560
SqlConnection conn = new SqlConnection(myConn);
SqlCommand Pareto = new SqlCommand();
BindingSource bindme = new BindingSource();
SqlDataAdapter adapt1 = new SqlDataAdapter(Pareto);
DataSet dataSet1 = new DataSet();
DataTable table1 = new DataTable();
acct = Acct;
string fromDate = this.dateTimePicker1.Value.ToString("MM/dd/yyyy");
string tooDate = this.dateTimePicker2.Value.ToString("MM/dd/yyyy");
Pareto.Connection = conn;
Pareto.CommandType = CommandType.StoredProcedure;
Pareto.CommandText = "dbo.GetSalesParetotemp";
Pareto.CommandTimeout = 120;
Pareto.Parameters.AddWithValue("#acct", acct);
Pareto.Parameters.AddWithValue("#from", fromDate);
Pareto.Parameters.AddWithValue("#too", tooDate);
SetCheckBoxValue(true);
SetPictureBoxVisibility(true);
adapt1.Fill(dataSet1, "Pareto");
SetCheckBoxValue(false);
SetPictureBoxVisibility(false);
SetDataGrid(true, dataSet1, "Pareto", DataGridViewAutoSizeColumnsMode.AllCells);
dataGridView1.AutoResizeColumns(
DataGridViewAutoSizeColumnsMode.AllCells);
}
catch (Exception execc)
{
MessageBox.Show("Whoops! Seems we couldnt connect to the server!"
+ " information:\n\n" + execc.Message + execc.StackTrace,
"Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
What I want to do is add another field to my query called "keycode", store this in a 2nd column in my ComboBox and then display the name field for the user, but use the keycode field as the value to be used in my giant task query.
I'm having trouble figuring out how I to do this.
In the past, I've used an object that contains an override of ToString() and instead of adding plain strings to my combo boxes (or other lists), I add these objects. Then, when you need to get the value of a selected item, you can cast it and do GetValue(). Here's a sample.
class LookupTableItem {
private string Text;
private object Value;
public LookupTableItem(string Text, object Value) {
this.Text = Text;
this.Value = Value;
}
public override string ToString() {
return Text;
}
public object GetValue() {
return Value;
}
}
Then, change your AddItem to add items this way:
accCollection.Items.Add(new LookupTableItem(text, value));
And to retrieve the value:
((LookupTableItem)accCollection.Items[0]).GetValue();

Categories