I am working in Winforms and now got stuck; I have created a custom usercontrol for textbox as shown in the code below:
public partial class TextBox : UserControl
{
public TextBox()
{
InitializeComponent();
txtTEXT.Text = "";
}
[DefaultValue("Text")]
public string Caption
{
get { return lblCAPTION.Text; }
set { lblCAPTION.Text = value;}
}
[Browsable(true)]
public new string Text
{
get { return txtTEXT.Text; }
set { txtTEXT.Text = value; }
}
[Browsable(true),DefaultValue(100)]
public int Caption_Width
{
get { return lblCAPTION.Width; }
set { lblCAPTION.Width = value; }
}
private void txtTEXT_TextChanged(object sender, EventArgs e)
{
if (this.txtTEXT.Text.StartsWith("textBox"))
this.txtTEXT.Text = "";
}
public new BorderStyle BorderStyle
{
get { return txtTEXT.BorderStyle; }
set { txtTEXT.BorderStyle = value; }
}
public bool PasswordChar
{
get { return txtTEXT.UseSystemPasswordChar; }
set {txtTEXT.UseSystemPasswordChar = value ;}
}
public bool m_Mandatory = false;
public bool Mandatory
{
get { return m_Mandatory; }
set
{
m_Mandatory= value;
lblAMENDATORY.Visible = m_Mandatory;
}
}
private void TextBox_Resize(object sender, EventArgs e)
{
this.Height = txtTEXT.Height;
}
}
Then in another form, I have binded this textbox as in the code below:
BindingSource bs = new BindingSource();
BindingSource bsDet = new BindingSource();
DataSet data;
SqlDataAdapter masterDataAdapter;
SqlDataAdapter detailsDataAdapter;
SqlConnection connection = new SqlConnection(connectionString);
// Create a DataSet.
data = new DataSet();
// Add data from the Customers table to the DataSet.
masterDataAdapter = new SqlDataAdapter("select * from RFID_MAS", connection);
masterDataAdapter.Fill(data, "RFID_MAS");
// Add data from the Orders table to the DataSet.
detailsDataAdapter = new SqlDataAdapter("select * from RFID_DET", connection);
detailsDataAdapter.Fill(data, "RFID_DET");
// Establish a relationship between the two tables.
DataRelation relation = new DataRelation("MyRelation", data.Tables["RFID_MAS"].Columns["SEQ_NO"],data.Tables["RFID_DET"].Columns["MAS_SEQ"]);
data.Relations.Add(relation);
// Bind the master data connector to the Customers table.
bs.DataSource = data;
bs.DataMember = "RFID_MAS";
// Bind the details data connector to the master data connector,
// using the DataRelation name to filter the information in the
// details table based on the current row in the master table.
bsDet.DataSource = bs;
bsDet.DataMember = "MyRelation";
// textBox1 is default Windows TextBox
textBox1.DataBindings.Add(new Binding("Text", this.bs, "RFID_NO", true, DataSourceUpdateMode.OnValidation));
// textBox2 is my ouwn usercontrol textbox
textBox2.DataBindings.Add(new Binding("Text", this.bs, "SEQ_NO",true, DataSourceUpdateMode.OnValidation));
dataGridView2.DataSource = bsDet;
dataGridView1.AutoResizeColumns();
dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
bindingNavigator1.BindingSource = bs;
//bs.DataSource = dset.Tables[0];
//dataGridView1.DataSource = bs;
Then I am saving my textbox data as:
this.Validate();
this.bs.EndEdit();
SqlCommandBuilder cm = new SqlCommandBuilder(masterDataAdapter);
this.masterDataAdapter.Update(data.Tables[0]);
Now my problem here is that when I add a new record,
the data from TextBox1 (ie windows default textbox) get updated in the BindingSource,
but data from TextBox2 (ie my own usercontrol textbox) does not get updated in the Bindingsource.
Please Help me if I am missing out something.
Very thanks to you.
Related
I have problem when i try to refresh data in datagridview. Am using MySQL database. On every click on Reload button my old data is duplicated in grid. I try to set datagridview.DataSource = null also try to Refresh datagrid and also try to Resert binding source but nothing is happening.
Check this:
public MainForm()
{
InitializeComponent();
this.connStr = Properties.Settings.Default.connStr;
}
// Load
private void Form1_Load(object sender, EventArgs e)
{
SelectData();
}
// Seslect Data
public void SelectData()
{
bs.DataSource = GetData("SELECT * FROM porudzbine");
dataGridView1.DataSource = bs;
}
// Get Data
private DataTable GetData(string query)
{
try
{
conn = new MySqlConnection(connStr);
conn.Open();
adapter = new MySqlDataAdapter(query, conn);
adapter.Fill(dt);
}
catch(MySqlException ex)
{
MessageBox.Show(ex.Message.ToString());
}
return dt;
}
// Reload
private void osveziListuPorudzbinaButton_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = null;
dataGridView1.Refresh();
bs.ResetBindings(false);
bs.DataSource = GetData("SELECT * FROM porudzbine");
dataGridView1.DataSource = bs;
}
You have a field called dt somewhere in your form (not shown in the post), which you are refilling (hence adding the records to the previously loaded records) on each GetData call.
Remove the field and use something like this:
// Get Data
private DataTable GetData(string query)
{
var dt = new DataTable();
// ...
return dt;
}
I have 2 listboxes in a window form, one on left and one on right. The
1st listbox have some items while the 2nd listbox is empty. Also there
are 2 buttons between the 2 listboxes which used to move item from/to
the 1st and 2nd listbox
My problem here is that after I bind the data to the 1st listbox (from
a database, using DisplayMember and ValueMember) , and I try to move 1
of the item from this 1st listbox to the 2nd listbox and I want that
the selected item is also removed from the 1st listbox by:
private void btnMoveRight_Click(object sender, EventArgs e)
{
ADD();
}
private void ADD()
{
int c = listJobBox.Items.Count - 1;
` for(int i= c; i>=0; i--)
{
if(listJobBox.GetSelected(i))
{
lstAssignedJobs.Items.Add(listJobBox.Items[i]);
listJobBox.Items.Remove(listJobBox.SelectedItem); ---error line
But the selected item is not removed from the 1st listbox.
it displays error message "Items collection cannot be modified
when the DataSource property is set."
can any one give me the solution to my problem.
Add a boolean column to your DataTable object, something like IsSelected.
Then instead of binding your listbox1 directly to the table, bind it to a BindingSource. Add 2 bindingsources to your form using the designer. And place this code in your code behind file.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.InitializeDataObjects();
}
private void InitializeDataObjects()
{
this.InitData();
this.InitBindingSources();
}
private void InitData()
{
ds = new DataSet();
var dt = new DataTable("Table1");
dt.Columns.Add("Name", typeof(string));
ds.Tables.Add(dt);
}
private void InitBindingSources()
{
bindingSource1 = new BindingSource();
bindingSource2 = new BindingSource();
bindingSource1.DataSource = ds;
bindingSource1.DataMember = "Table1";
bindingSource2.DataSource = ds;
bindingSource2.DataMember = "Table1";
listBox1.DataSource = bindingSource1;
listBox1.DisplayMember = "Name";
listBox2.DataSource = bindingSource2;
listBox2.DisplayMember = "Name";
}
}
Then when you load your data, do the following:
private void btnLoadAndBind_Click(object sender, EventArgs e)
{
this.FetchData(this.ds.Tables["Table1"]);
this.AddSelectedColumn(this.ds.Tables["Table1"]);
this.bindingSource1.Filter = "IsSelected = false";
this.bindingSource2.Filter = "IsSelected = true";
}
private void FetchData(DataTable dataTable)
{
string CS = "your connectionstring";
using (SqlConnection con = new SqlConnection(CS))
{
try
{
SqlDataAdapter da = new SqlDataAdapter();
con.Open();
var sqlcmd = new SqlCommand("SELECT Name FROM sometable", con);
sqlcmd.CommandType = CommandType.Text;
da.SelectCommand = sqlcmd;
da.Fill(dataTable);
}
catch (Exception ex)
{
MessageBox.Show("exception raised");
throw ex;
}
}
}
private void AddSelectedColumn(DataTable suppliersDataTable)
{
var dc = new DataColumn("IsSelected", typeof(bool));
suppliersDataTable.Columns.Add(dc);
foreach (DataRow dr in suppliersDataTable.Rows)
{
dr["IsSelected"] = false;
}
}
Now your listboxes are both connected to the same datatable and filtered based on the IsSelected property / column. Just set this column to true or false and it will flip from box to box. Your eventhandler of a button could look like this:
public void button_Click(object sender, EventArgs e)
{
if (this.bindingSource1.Current!= null)
{
var dr = ((DataRowView)this.bindingSource1.Current).Row;
dr["IsSelected"] = true;
}
}
This works!
Things will be become much simpeler if you use a typed dataset. Most of the bindings then can be done in the designer and your code behind will shrink to 20 lines of code....
Lets say listbox1 is bound to datatable1 (it could be any other collection type) and listbox2 is bound to datatable2. When you click on move button, remove the selected item from the collection i.e datatable1 and add that item to other collection i.e. datatable2 and re-bind the listbox1 and lisbox2.
Here is a rough working example:
public partial class Form1 : Form
{
private DataTable _dataSource1;
private DataTable _dataSource2;
public Form1()
{
InitializeComponent();
_dataSource1 = GetData1();
_dataSource2 = GetData2();
Initialize();
}
private void btnMove_Click(object sender, EventArgs e)
{
MoveItem();
}
void Initialize()
{
listBox1.DataSource = _dataSource1;
listBox1.DisplayMember = "Fruits";
listBox1.ValueMember = "Fruits";
listBox2.DataSource = _dataSource2;
listBox2.DisplayMember = "Fruits";
listBox2.ValueMember = "Fruits";
}
DataTable GetData1()
{
var dt = new DataTable();
dt.Columns.Add("Fruits");
dt.Rows.Add(new object[] {"Apple"});
dt.Rows.Add(new object[] { "Orange" });
dt.Rows.Add(new object[] { "Grapes" });
return dt;
}
DataTable GetData2()
{
var dt = new DataTable();
dt.Columns.Add("Fruits");
return dt;
}
void MoveItem()
{
var index = listBox1.SelectedIndex;
var dataRowToRemove = _dataSource1.Rows[index];
var listItem = dataRowToRemove[0] as string;
_dataSource1.Rows.Remove(dataRowToRemove);
var dataRowToAdd = _dataSource2.NewRow();
dataRowToAdd[0] = listItem;
_dataSource2.Rows.Add(dataRowToAdd);
Initialize();
}
}
code does not display anything in datagridview
why?
class classman
{
public int id;
public string name;
}
private void Form2_Load(object sender, EventArgs e)
{
testtelContext db = new testtelContext();
List<classman> qry = (from p in db.firstlasts
join i in db.firstnames
on p.Idfname equals i.Idfname
select new classman
{
id = p.idfl,
name = i.fname
}).ToList();
BindingSource bs=new BindingSource();
bs.DataSource = qry;
dataGridView1.DataSource = bs;
}
There is value in bindingsource but it does not display dataGridView5 show picture http://irphoto.ir/uploads/13658793021.jpg
Probably need this:
dataGridView1.DataBind();
Right after you set the data source.
I use a PostgreSQL view to display data in a DataGridView:
dataSource = new BindingSource();
dataSource.DataSource = Program.DB.GetView(dbView); // returns a DataTable
dgData.DataSource = dataSource;
Now, after I added a record using a PostgreSQL function, I refresh the data in the grid (I don't call Rows.Add() on the DataGridView:
protected void RefreshData() {
dataSource.DataSource = Program.DB.GetView(dbView);
}
The insertion function of PostgreSQL returns the ID of the inserted row, so I know the ID (which is primary key) and want to set Selected to true in the DataGridView. The row can be anywhere in the set, because the view is sorted by name, not ID. I reckon I could do that by cycling over all rows and set the Selected when I found it, but this could become slow on large datasets.
Is there a way to somehow bind the rows of the datasource to the datagrid?
Add an event handler to the ListChanged event:
dataSource.ListChanged += dataSource_ListChanged;
Here is the event handler definition:
void dataSource_ListChanged(object sender, ListChangedEventArgs e)
{
if (dgData.Rows.Count > 0)
dgData.CurrentCell = dgData.Rows[e.NewIndex].Cells[0];
}
[UPDATE]
As I also suggested in the comments, maybe you should not repopulate the data source on each insert (or update). To demonstrate my point, I'll post a code sample which uses a DataGridView, 2 TextBoxes and 2 Buttons (for insert and update) and a SqlDataAdapter. The SQL table has 2 columns (id and value).
Here's the code (I didn't cover the deletion):
public partial class Form1 : Form
{
static BindingSource dataSource;
static string dbView = "default";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
dgData.MultiSelect = false;
dataSource = new BindingSource();
dataSource.ListChanged += dataSource_ListChanged;
RefreshData();
dgData.DataSource = dataSource;
dgData.Sort(dgData.Columns[1], ListSortDirection.Ascending);
}
void dataSource_ListChanged(object sender, ListChangedEventArgs e)
{
if (dgData.Rows.Count > 0)
dgData.CurrentCell = dgData.Rows[e.NewIndex].Cells[0];
}
protected void RefreshData()
{
dataSource.DataSource = DB.GetView(dbView);
}
private void insert_Click(object sender, EventArgs e)
{
DB.Insert(textBox1.Text);
RefreshData();
}
private void update_Click(object sender, EventArgs e)
{
DB.UpdateRandomRow(textBox2.Text);
RefreshData();
}
}
class DB
{
static DataTable dt;
static string conStr = "yourConnectionString";
static SqlDataAdapter _adapter;
static Random r = new Random(10);
public static SqlDataAdapter CreateSqlDataAdapter(SqlConnection connection)
{
_adapter = new SqlDataAdapter();
_adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
_adapter.SelectCommand = new SqlCommand(
"SELECT * FROM test", connection);
_adapter.InsertCommand = new SqlCommand(
"INSERT INTO test (value) " +
"VALUES (#value)", connection);
_adapter.UpdateCommand = new SqlCommand(
"UPDATE test SET [value] = #value " +
"WHERE id = #id", connection);
_adapter.InsertCommand.Parameters.Add("#value",
SqlDbType.NVarChar, 50, "value");
_adapter.UpdateCommand.Parameters.Add("#id",
SqlDbType.Int, 4, "id").SourceVersion = DataRowVersion.Current;
_adapter.UpdateCommand.Parameters.Add("#value",
SqlDbType.NVarChar, 50, "value").SourceVersion = DataRowVersion.Current;
return _adapter;
}
// random update, to demonstrate dynamic
// repositioning
public static DataTable UpdateRandomRow(string value)
{
var currentRandom = r.Next(dt.Rows.Count);
dt.Rows[currentRandom].SetField<string>(1, value);
using (var con = new SqlConnection(conStr))
{
con.Open();
_adapter = CreateSqlDataAdapter(con);
_adapter.Update(dt);
}
return dt;
}
internal static DataTable GetView(string dbView)
{
if (dt == null)
{
dt = new DataTable();
using (var con = new SqlConnection(conStr))
{
con.Open();
_adapter = CreateSqlDataAdapter(con);
_adapter.Fill(dt);
}
}
return dt;
}
internal static void Insert(string value)
{
if (dt == null)
GetView("");
var dr = dt.NewRow();
dr[1] = value;
dt.Rows.Add(dr);
using (var con = new SqlConnection(conStr))
{
con.Open();
_adapter = CreateSqlDataAdapter(con);
_adapter.Update(dt);
}
}
}
If you test it, you'll see that the request from your question is satisfied for both insert and update. Also, please note the performance improvement, as the data table is not recreated on each operation.
I cannot seem to bind to a TextBox. Here is my source:
public partial class formAirFreightLabels : Form
{
int pfDeclarationUID = -1;
BindingNavigator bindingNavigatorMain = new BindingNavigator();
BindingSource bindingSourceMain = new BindingSource();
public formAirFreightLabels(int pvDeclarationUID)
{
InitializeComponent();
pfDeclarationUID = pvDeclarationUID;
this.bindingNavigatorMain.BindingSource = this.bindingSourceMain;
this.bindingNavigatorMain.Dock = DockStyle.Bottom;
this.Controls.Add(this.bindingNavigatorMain);
this.Load += new EventHandler(formAirFreightLabels_Load);
}
void formAirFreightLabels_Load(object sender, EventArgs e)
{
SqlConnection cn = Program.GetSQLConnection();
if (cn != null)
{
SqlCommand cmd = new SqlCommand(String.Format("SELECT ShipperName, ShipperAddress, ConsigneeName, ConsigneeAddress FROM Declarations WHERE DeclarationUID={0}", pfDeclarationUID), cn);
SqlDataReader r = cmd.ExecuteReader(CommandBehavior.CloseConnection);
DataSet ds = new DataSet("Declarations");
ds.Load(r, LoadOption.OverwriteChanges, new string[] { "Declarations" });
bindingSourceMain.DataSource = ds;
textBoxShipperName.DataBindings.Add(new Binding("Text", bindingSourceMain, "ShipperName", true));
}
}
}
I keep getting a run-time error as follows:
Cannot bind to the property or column ShipperName on the DataSource.
Parameter name: dataMember
As msdn says, you need to add TableName.ColumnName in order bind the controls. Windows Form Binding , you may try like this.
textBoxShipperName.DataBindings.Add(new Binding("Text", bindingSourceMain, "Declarations.ShipperName", true))