I have a combobox in a wpf form. I would like to bind it to a table in MS SQL server. However each time i run my code i keep on running into errors. Any assistance would be appreciated. Below is my code:
private void OnLoad(object sender, RoutedEventArgs e)
{
FillComboBox();
}
protected void FillComboBox()
{
SqlConnection con = new SqlConnection(cs);
DataSet ds = new DataSet();
try
{
con.Open();
SqlCommand cmd = new SqlCommand("SELECT RegNumber,Make FROM Vehicles GROUP BY RegNumber,Make", con);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(ds);
combovehicle.DisplayMemberPath = "RegNumber";
combovehicle.SelectedValue= "Make";
combovehicle.DataContext = ds.Tables[0];
}
catch(Exception)
{
}
}
}
}
combovehicle.DisplayMemberPath = "RegNumber";
combovehicle.SelectedValue= "Make";
combovehicle.DataContext = ds.Tables[0];
So you told WPF to display using the property Make and RegNumber
but you passed in a DataTable object
DataRow does provide indexer for accessing the property but it does NOT contain those properties. Plus DataTable is not IEnumerable so you can't really use it as data source.
AND most importantly you are doing it all wrong. You should almost never make database call directly in your view and set the data source to the output table. You should do this thru MVVM pattern.
Related
In my WPF (C#) application I am trying to update my SQL database when changes are made to a datagrid in the app.
Displaying the dataset in the Datagrid works fine, but I can not get updates made in the datagrid sent back to the database.
This is what I have so far - The issue is, that I can't figure out how to pass the dataset (ds) and the sqladapter (sea) to the BtnSave_Click void, which should update the SQL with the changes made (I get a "Mainwindow does not contain a definition for 'ds'). I have been using VB.Net previously and there I could declare them as public variables, but that can't be done here I guess. I have read that I could declare a static class and put them there, but also that that is a bad technique.
I am very thankful for any suggestions on how to proceed. Cheers, Peter.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void grdSchedule_Loaded(object sender, RoutedEventArgs e)
{
string strCon = ConfigurationManager.ConnectionStrings["strCon"].ConnectionString;
string CmdString = string.Empty;
using (SqlConnection con = new SqlConnection(strCon))
{
CmdString = "SELECT * FROM tbl_Schedule";
SqlCommand cmd = new SqlCommand(CmdString, con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
sda.TableMappings.Add("Table", "tbl_Schedule");
DataSet ds = new DataSet("tbl_Schedule");
sda.Fill(ds, "tbl_Schedule");
grdSchedule.ItemsSource =ds.Tables["tbl_Schedule"].DefaultView;
ds.AcceptChanges();
}
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
DataSet changes = this.ds.GetChanges();
if (changes != null)
{
//Data has changes.
//use update method in the adapter. it should update the datasource
int updatedRows = this.sda.Update(changes);
this.ds.AcceptChanges();
}
}
}
}
For save changes via sqlDataAdapter you need to specify commands for properties UpdateCommand, DeleteCommand, InsertCommand.
Also need notice that such commands must contains parameters which will be binded to columns in your DataTable.
var updateCommand = new SqlCommand("Update tbl_schedule set OperationId=#OperationId where Id=#Id")
updateCommand.Parameters.Add("#OperationId", SqlDbType.int, "OperationId")
updateCommand.Parameters.Add("#Id", SqlDbType.Int, "Id");
sda.UpdateCommand = updateComand;
I have a combobox that is filled from a database conditionally by checking off one of 10 checkboxes. Each of the 10 checkboxes contains the code below, which selects a portion of column based on a value in column2.
private void Check1_CheckedChanged(object sender, EventArgs e)
{
if (Check1.CheckState == CheckState.Checked)
{
// SQL Server connection
SqlConnection conn = new SqlConnection(#"Server = Server; Database = DB; Integrated Security = True");
DataSet ds = new DataSet();
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT [Column1] FROM [DB].[dbo].[Table1] WHERE [Column2] = 50", conn);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(ds);
combo1.DisplayMember = "Column1";
combo1.ValueMember = "ID";
combo1.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
//Exception Message
}
finally
{
conn.Close();
conn.Dispose();
}
}
if (Check1.CheckState == CheckState.Unchecked)
{
combo1.DataSource = null;
}
Therefore, it is rather trivial to fill the combobox with each separate condition. What I want to do that I'm not sure of the approach, however, is that when more than one checkbox is checked, the combobox will display the data from every checked checkbox at once (all this data will be from the same column). Moreover, when a single checkbox is then unchecked, I only want it to remove its own dataset from the combobox and not everything.
Is this possible?
I think it's possible if you have 1 dataset and then you dynamically build up your SQL query. Set up a variable for the columns you want to return based on all the selected comboBoxes.
Use 1 method for all your after update event on the comboBoxes to make it easier and more maintainable.
In terms of mapping the dynamics columns to the dropdowns, I don't work with Winform so I'm not sure but hope this can help a bit.
You can use the for loop to iterate the values you have retrieved and append the combo box value. Example:
comboBox.Items.Clear(); // <-- Declare this at initialization of the page or whatever scenario you have
private void Check1_CheckedChanged(object sender, EventArgs e)
{
if (Check1.CheckState == CheckState.Checked)
{
// SQL Server connection
SqlConnection conn = new SqlConnection(#"Server = Server; Database = DB; Integrated Security = True");
DataSet ds = new DataSet();
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT [Column1] FROM [DB].[dbo].[Table1] WHERE [Column2] = 50", conn);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(ds);
// Using loop to iterate the values and append the combo box
for(int i=0;i<da.Rows.Count;i++)
{
combo1.Items.Add(da[i]["Column1"].ToString());
combo1.Items[combo1.Itemx.Count-1].Text=da[i]["Column1"].ToString();
combo1.Items[combo1.Itemx.Count-1].Value=da[i]["Column1"].ToString();
}
}
catch (Exception ex)
{
//Exception Message
}
finally
{
conn.Close();
conn.Dispose();
}
}
if (Check1.CheckState == CheckState.Unchecked)
{
combo1.DataSource = null;
}
This is just an example, hope you can get the idea
I have dynamically created a DataGrid using database information. I want to make it so I am able to click on the rows that it has created and it calls another C# method which then loads more data.
I'm not entirely sure how to make the new method run different SQL queries, I'm guessing I am going to have to use the ID of the data that I have pulled from the database? But I dont know how to get that ID from the row either so it would be really helpful if you could help with that.
Here is the code that I have written to get the data and then create the DataGrid:
protected void SubMenuLoadData(object sender, ImageClickEventArgs e)
{
DataGridView1.DataSource = GetData("SELECT [ID], [Description] FROM Table1 WHERE[Part Number] like 'A%'");
DataGridView1.DataBind();
}
private DataTable GetData(string query)
{
string constr = ConfigurationManager.ConnectionStrings["ArrowEngineering"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand(query))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
return dt;
}
}
}
}
}
I'm using Visual Studio 2010 and C# to create a windows form with a combobox that should contain employees initials. I have spent the last few days searching through every solution I can find and I still can not get my combobox to populate.
This is what I've got as of now:
public static void FillComboBox(string Query, System.Windows.Forms.ComboBox LoggedByBox)
{
using (var CONN = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Users\\Documents\\Service Request Application\\bin\\Debug\\servicereq1.mdb"))
{
CONN.Open();
DataTable dt = new DataTable();
try
{
OleDbCommand cmd = new OleDbCommand(Query, CONN);
OleDbDataReader myReader = cmd.ExecuteReader();
dt.Load(myReader);
}
catch (OleDbException e)
{
Console.WriteLine(e.ToString());
Console.ReadLine();
return;
}
LoggedByBox.DataSource = dt;
LoggedByBox.ValueMember = "ID";
LoggedByBox.DisplayMember = "Initials";
}
}
Then I call it when the form loads
private void Form1_Load(object sender, EventArgs e)
{
FillComboBox("select ID, Initials from [Fixers and Testers]", LoggedByBox);
}
When I run the program, the combobox is still blank. I'm positive that my column names and table names are correct. Any suggestions?
I finally got my ComboBox filled and I wanted to share what I changed for anyone else who stumbles across this question in their searches. After spending a bit more time searching through other questions and MSDN, I was able to come up with this.
private void LoadComboLogged()
{
AppDomain.CurrentDomain.SetData("DataDirectory",#"\\prod\ServiceRequests");
string strCon = #"Provider=Microsoft.Jet.OLEDB.4.0;DataSource=|DataDirectory|\servicereq1.mdb";
try
{
using (OleDbConnection conn = new OleDbConnection(strCon))
{
conn.Open();
string strSql = "SELECT Initials FROM [Fixers and Testers] WHERE [Status] ='C'";
OleDbDataAdapter adapter = new OleDbDataAdapter(new OleDbCommand(strSql, conn));
DataSet ds = new DataSet();
adapter.Fill(ds);
loggedByComboBox.DataSource = ds.Tables[0];
loggedByComboBox.DisplayMember = "Initials";
loggedByComboBox.ValueMember = "Initials";
}
}
catch (Exception ex)
{
}
}
I also found that I needed to call
LoadComboLogged();
when I initialized my form. Without that line, the ComboBox would only show a blank dropdown list. Hope this helps someone else who runs into this problem.
Passing control to static method causing this issue. Instead of passing control to the method make that method returns the table and within the load method load the control.
SqlConnection con = new SqlConnection("Data Source=RUSH-PC\\RUSH;Initial Catalog=Att;Integrated Security=True");
con.Open();
SqlDataAdapter da = new SqlDataAdapter("select name from userinfo", con);
DataTable dt = new DataTable();
da.Fill(dt);
DataRow dr;
dr = dt.NewRow();
dt.Rows.InsertAt(dr, 1);
comboBox1.DisplayMember = "name";
comboBox1.ValueMember = "name";
comboBox1.DataSource = dt;
con.Close();
This may help you...
Good luck...:-)
Another possible solution would be to query and return a list of strings. Perhaps it may be less efficient, but it's what I used in a recent project of mine. Here's an example that would reside in a method, possibly called GetInitialsFromDatabase():
using(var conn = new MySqlConnection(connectionString)
{
conn.Open();
using(MySqlCommand cmd = new MySqlCommand())
{
cmd.Connection = conn;
cmd.CommandText = "SELECT Initials FROM [Fixers and Testers] WHERE [Status] ='C'";
MySqlDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
// initials is a List<String> previously defined (Assuming strings)
initials.Add(String.Format("{0}", reader[0]));
}
}
conn.Close();
}
And then return the initials List, and then in your GUI you could say:
comboBox1.DataSource = returnedList;
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
I took an video from you tube to Retrieving Data from SQL Server using C# and ADO.Net
http://www.youtube.com/watch?v=4kBXLv4h2ig&feature=related
I Do the same as him in the video...
I want to show data from an sql database in a DataGridView.
I get an error whit
da.Fill(dg);
dg.DataSource = dg.Tables[0];
I name my DataGridView dg...
Complete code
using System.Data.SqlClient;
namespace SQLconnection
{
public partial class Form1 : Form
{
SqlConnection cs = new SqlConnection("Data Source=FRANK-PC\\SQLEXPRESS; Initial Catalog=Forc#; Integrated Security=TRUE");
SqlDataAdapter da = new SqlDataAdapter();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
da.InsertCommand= new SqlCommand ("INSERT INTO tblContacts VALUES (#FirstName,#LastName)", cs );
da.InsertCommand.Parameters.Add("#FirstName", SqlDbType.VarChar).Value = txtFirstName.Text;
da.InsertCommand.Parameters.Add("#LastName", SqlDbType.VarChar).Value = txtLastname.Text;
cs.Open();
da.InsertCommand.ExecuteNonQuery();
cs.Close();
}
// Display data in dg
private void button2_Click(object sender, EventArgs e)
{
da.SelectCommand = new SqlCommand("SELECT * FROM tblContacts", cs);
da.Fill(dg);
dg.DataSource = dg.Tables[0];
}
}
}
you should open the connection before filling the table with the data adapter, add this:
cs.Open();
DataSet ds = new DataSet();
da.Fill(ds);
cs.Close();
dg.DataSource = ds.Tables[0];
note that this is anyway a bad practice, there are trillions of examples here in SO on how to handle the SQLConnections, you should use a using block so that it gets closed and disposed immediately after usage and do not have connections or adapters or data tables or sqlcommand global to all form but create them only when/where needed.
You should actually move out all data access logic from the UI to a separated class, Business Logic or Data layer.
Edit:
you should do something like this:
using(SQLConnection conn = 'connection string here')
{
using(SQLCommand cmd = new ('sql query', conn))
{
//execute it blah blah
}
}
check out this question: Closing SqlConnection and SqlCommand c#
The Fill method open/close connection implicitly but the problem is in name of dataGrdiView and DataTable/DataSet reference variable - dg
private void button2_Click(object sender, EventArgs e)
{
da.SelectCommand = new SqlCommand("SELECT * FROM tblContacts", cs);
DataTable dt=new DataTable();
da.Fill(dt);
dg.DataSource = dt;
}
I'm guessing since you didn't include the exception you are receiving, but you need to open your SqlConnection prior to using it:
private void button2_Click(object sender, EventArgs e)
{
da.SelectCommand = new SqlCommand("SELECT * FROM tblContacts", cs);
cs.Open();
da.Fill(dg);
cs.Close();
dg.DataSource = dg.Tables[0];
}
Try it this, but is important know what kind of exception throws.
private void button2_Click(object sender, EventArgs e)
{
cs.Open();
using (SqlDataAdapter a = new SqlDataAdapter("SELECT * FROM tblContacts", cs))
{
DataTable t = new DataTable();
a.Fill(t);
dg.DataSource = t;
}
}