DataGridView Winform c# - c#

every time, i press btnAgregar, add "productos" to list.
only the first time the gridview show the first record of the list
after the list grows, but the datagridview don't refrash, showing only the first record.
List<Entidades.Productos> ProductosVenta = new List<Productos>();
private void btnAgregar_Click(object sender, EventArgs e)
{
Entidades.Productos productos = new Entidades.Productos();
productos = Datos.Productos.ObtenerFormaPagoPorId(int.Parse(txtId.Text));
ProductosVenta.Add(productos);
gvVenta.DataSource = ProductosVenta;
}

the solution is make null the data source before asing the list
ProductosVenta.Add(productos);
gvVenta.DataSource = null; // this does the trick
gvVenta.DataSource = ProductosVenta;

Related

Selected index combobox winforms

Ok, very dumb question but i haven't really found an answer on internet.
I have multiple comboboxes on a form. The binding of each combobox is on form_load.
When the form loads, the first item is selected on the form. This is obvious, but I don't want this. So i used in the form_load the following code:
private void InvoiceView_Load(object sender, EventArgs e)
{
// Bind list of customers to combobox
CustomerComboBox.DataSource = invoicePresenter.getCustomers();
CustomerComboBox.DisplayMember = "CustomerName";
CustomerComboBox.ValueMember = "CustomerId";
// Bind list of products to combobox
productCombobox.DataSource = invoicePresenter.getProducts();
productCombobox.DisplayMember = "ProductName";
productCombobox.ValueMember = "ProductId";
// Bind list of vat codes to combobox
vatComboBox.DataSource = invoicePresenter.getTaxCodes();
vatComboBox.DisplayMember = "taxCodeShortDescr";
vatComboBox.ValueMember = "taxCodeId";
// Set comboboxes empty
CustomerComboBox.SelectedItem = null;
productCombobox.SelectedItem = null;
vatComboBox.SelectedItem = null;
}
This works. But the textboxes are still giving me the data of the first item ? My guess is because its in the selectedIndexChanged. But i have no clue what to use else.
If I put the combobox.selectedIndex = -1; I face the same issue.
the code:
private void CustomerComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
// Bind the selected customer itemvalues to the texboxes
txtCustomerName.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerName.ToString();
txtAddress.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerAddress.ToString();
txtPostalCode.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerPostalCode.ToString();
txtCity.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerCity.ToString();
txtCountry.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerCountry.ToString();
txtVatNumber.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerCountryCode.ToString() + ((tbl_customer)CustomerComboBox.SelectedItem).CustomerVat.ToString();
}
One would think, because im using selecteditem in the textbox binding, it would be null also. But this is not the case.
Interestingly, seems like you've hit one of the WF data binding quirks. The problem is caused by the fact that the CurrencyManager class which maintains every list data source does not allow setting the Position property to -1 (thus Current to null) when the list count is not zero. Since the ComboBox is synchronizing the SelectedIndex with the CurrencyManager.Position, this effectively prevents having an unselected item.
As a workaround, if the data bound mode of the list portion is not essential for you, replace the line
CustomerComboBox.DataSource = invoicePresenter.getCustomers();
with
foreach (var customer in invoicePresenter.getCustomers())
CustomerComboBox.Items.Add(customer);
Do the same for the other comboboxes that need such behavior.
You can remove the handler for the SelectedIndex_Changed event of combobox, bind data, then add the handler back. like this :
private void InvoiceView_Load(object sender, EventArgs e)
{
this.CustomerComboBox.SelectedIndexChanged -= new EventHandler(CustomerComboBox_SelectedIndexChanged);
this.productCombobox.SelectedIndexChanged -= new EventHandler(productCombobox_SelectedIndexChanged);
this.vatComboBox.SelectedIndexChanged -= new EventHandler(vatComboBox_SelectedIndexChanged);
// Bind list of customers to combobox
CustomerComboBox.DataSource = invoicePresenter.getCustomers();
CustomerComboBox.DisplayMember = "CustomerName";
CustomerComboBox.ValueMember = "CustomerId";
// Bind list of products to combobox
productCombobox.DataSource = invoicePresenter.getProducts();
productCombobox.DisplayMember = "ProductName";
productCombobox.ValueMember = "ProductId";
// Bind list of vat codes to combobox
vatComboBox.DataSource = invoicePresenter.getTaxCodes();
vatComboBox.DisplayMember = "taxCodeShortDescr";
vatComboBox.ValueMember = "taxCodeId";
this.CustomerComboBox.SelectedIndexChanged += new EventHandler(CustomerComboBox_SelectedIndexChanged);
this.productCombobox.SelectedIndexChanged += new EventHandler(productCombobox_SelectedIndexChanged);
this.vatComboBox.SelectedIndexChanged += new EventHandler(vatComboBox_SelectedIndexChanged);
}

add the new row client has entered to data source on radgirdview

I am new to using the telerik tools for winforms and I was wondering if anyone could help me to find the best way so that the client can add a new row on the radgrid and for it to show this change on the data source.
so far I have the radgrid set up so that the client can add a new row. I just need to bind it to the data source.
private void radGridView1_Click(object sender, EventArgs e)
{
this.radGridView1.AllowEditRow = false;
this.radGridView1.AllowAddNewRow = true;
this.radGridView1.AllowDeleteRow = false;
this.radGridView1.AddNewRowPosition = Telerik.WinControls.UI.SystemRowPosition.Top;
this.radGridView1.MasterTemplate.AddNewBoundRowBeforeEdit = true;
radGridView1.EnableAlternatingRowColor = true;
}
Have a look at the UserAddedRow event for RadGridView. This is fired after the user added a new row to the grid. You could then add the new entries to a source list or data table.
List<Foo> _lSource = new List<Foo>();
DataTable _tSource = new DataTable();
private void radGridView1_UserAddedRow(object sender, GridViewRowEventArgs e)
{
Foo foo = new Foo();
foo.Col1 = e.Row.Cells["col1"].Value.ToString();
foo.Col2 = e.Row.Cells["col2"].Value.ToString();
_lSource.Add(foo);
_tSource.Rows.Add(e.Row.Cells["col1"].Value.ToString(), e.Row.Cells["col2"].Value.ToString());
}
I added both possibilities in the same code snippet. Just choose one (list or table). I just created a random class to show you an example. You can create your own classes and name the properties as you want. Just note that the column (col1 and col2 in my example) must exist, otherwise you'll get a NullReferenceException. If you're using DataTable you have to add the columns once before adding rows.
_tSource.Columns.Add("col1");
_tSource.Columns.Add("col2");
I also recommend not to update the RadGridView properties on a click event of RadGridView. Because it is enough to set those properties once. Now you set them every time you click in your grid view. Either move them to the Load event of your form or set it directly in designer properties.
private void Form_Load(object sender, EventArgs e)
{
radGridView1.AllowEditRow = false;
radGridView1.AllowAddNewRow = true;
radGridView1.AllowDeleteRow = false;
radGridView1.AddNewRowPosition = Telerik.WinControls.UI.SystemRowPosition.Top;
radGridView1.MasterTemplate.AddNewBoundRowBeforeEdit = true;
radGridView1.EnableAlternatingRowColor = true;
}
RadGridView supports data binding to variety of data sources and CRUD operation will be handled for you automatically. Here you can find information on the supported data sources: Telerik UI for WinForms Documentation
And here is how to bind to a DataTable, where all CRUD operations work out of the box
RadGridView radGridView1 = new RadGridView();
this.Controls.Add(radGridView1);
radGridView1.Dock = DockStyle.Fill;
DataTable table = new DataTable();
table.Columns.Add("col1");
table.Columns.Add("col2");
table.Rows.Add("value1", "value1");
table.Rows.Add("value2", "value2");
radGridView1.DataSource = table;
Here is also a design time tutorial.

DevExpress lookupedit repository item add new row in Xtra Grid View in first row

I have a devexpress gridcontrol with 5 columns. The first column is a lookupedit repository with some data, let say with CarTypes.
To load data in grid I am using a BindingSource. In this BindingSource.DataSource I have load a IList<Cars>
and then
added this binding source in dataSource of my gridcontrol
like bellow
BindingSource _carsBindingSource = new BindingSource();
private void BindData(IList<Cars> data)
{
_carsBindingSource.DataSource = data;
carsGridControl.BeginUpdate();
carsGridControl.DataSource = _carsBindingSource;
carsGridControl.RefreshDataSource();
carsGridControl.EndUpdate();
}
I have a button to add new line in my grid "Add new car" and add a new line in _carBindingSource
private void AddNewRow()
{
_newRow = true;
_carsBindingSource.AllowNew = true;
Cars newCar = new Cars();
newCar.CarType = new CarType();
_carsBindingSource.Add(newCar );
//_carsBindingSource.Insert(0,newCar);
}
Now I want to add the new line in the first row of grid.
I use Insert
_carsBindingSource.Insert(0,newCar);
But it didn't work. The lookupedit repository can't load data.
With _carsBindingSource.Add(newCar); it works fine
Can anyone help me? Thank you!
If you haven't already, consider using an intermediate list for your car types:
private List<CarTypes> _CarTypes;
// Elsewhere in the code...
_CarTypes = GetCarTypes();
And then in the form load event, be sure this is bound to the data source:
repositoryLookupItemCarTypes.DataSource = _CarTypes;
With this, the grid should now automatically manage the instantiation and selection of the CarType object for each Cars object. You can omit this line when you add a car to the grid:
newCar.CarType = new CarType();
In the designer, I think it helps to alter the DisplayMember Property of the repository Item.
With this setup, any Car added to your grid should automatically have the CarType as a populated Lookup Edit.
If any of this is unclear, let me know. I did a quick and dirty solution to test this, and I obviously can't post it all, but I can tell you it did work with both Add and Insert.
Actualy I found a solutions.
The problem was in GridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e) event
where I change the AllowEdit value (e.Column.OptionsColumn.AllowEdit = true;).
private void gridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
string cName = e.Column.FieldName;
GridView gv = sender as GridView;
if (cName == "CarType.IdApi")
{
if (isNewRow)
{
Cars cars= (Cars)gv.GetRow(e.RowHandle);
int a = e.RowHandle;
if (cars.ID== 0 && e.RowHandle == 0)
{
e.Column.OptionsColumn.AllowEdit = true;
}
else
{
e.Column.OptionsColumn.AllowEdit = false;
}
}
}
}
When I use Insert(0, new Car) then because of second row whitch has value
the AllowEdit was false;
So I remove else code and it works
private void gridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
string cName = e.Column.FieldName;
GridView gv = sender as GridView;
if (cName == "CarType.IdApi")
{
if (isNewRow)
{
Cars cars= (Cars)gv.GetRow(e.RowHandle);
int a = e.RowHandle;
if (cars.ID== 0 && e.RowHandle == 0)
{
e.Column.OptionsColumn.AllowEdit = true;
}
}
}
}
So finlay I found that bindingSource.Add(object) and bindingSource.Insert(0,object) is same!
I apologize for my english!!

C# 2 Comboboxes with identical, not twice-selectable content

I have a dialog form where the user has to selected which colums from a textfile he wants to use for drawing a graph.
If someone doesn't quite understand what I mean, please look at the following example:
The dialog opens
The user selects e.g. that the x-values of his graph shall be from the second column of the textfile
The user selects e.g. that the y-values of his graph shall be from the third column of the textfile
The user clicks "OK"
The problem I have is the following:
I want to prevent the user from selecting the same column for x and y values, which would result in a line in an angle of probably 45 degrees and make the graph useless.
Both comboboxes are filled with the same array of strings, which contains the headlines of the columns in the textfile. Getting those strings into the comboboxes works great, but:
I tried removing the item selected in one combobox from the other combobox and otherwise.
Before that, the currently selected item is stored in a variable and the items are reset to the default state, which means all headlines from the textfile.
But, as I programmatically set the index to where it was before, so that the user doesn't have to, the SelectedIndexChanged event fires and traps my code in an infinite loop.
public void setComboboxText()
{
cbX.Items.Clear();
cbY.Items.Clear();
cbX.Items.AddRange(cbText);
cbY.Items.AddRange(cbText);
}
void CbXSelectedIndexChanged(object sender, EventArgs e)
{
var item = cbX.SelectedItem;
setComboboxText();
cbX.SelectedItem = item;
cbY.Items.Remove(cbX.SelectedItem);
}
void CbYSelectedIndexChanged(object sender, EventArgs e)
{
var item = cbY.SelectedItem;
setComboboxText();
cbY.SelectedItem = item;
cbX.Items.Remove(cbY.SelectedItem);
}
The code does the following:
The currently selected item is temporarily stored
The items of the combobox are reset
The currently selected item is set to be the item stores before
The item selected in the changed box disappears from the other combobox
Any help appreciated, especially if someone could tell me if I can do what I want with another event or even without events.
Thanks in advance
I think this is what you are trying to achieve.
public partial class Form1 : Form
{
List<string> source1 = new List<string>();
List<string> source2 = new List<string>();
public Form1()
{
InitializeComponent();
for (int i = 0; i < 10; i++)
{
source1.Add("item" + i);
source2.Add("item" + i);
}
comboBox1.Items.AddRange(source1.ToArray());
comboBox2.Items.AddRange(source2.ToArray());
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox2.Items.Contains(comboBox1.SelectedItem))
{
comboBox2.Items.Clear();
List<string> updatedList = new List<string>();
updatedList = (from x in source2
where !x.Equals(comboBox1.SelectedItem)
select x).ToList<string>();
comboBox2.Items.AddRange(updatedList.ToArray());
}
}
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.Items.Contains(comboBox2.SelectedItem))
{
comboBox1.Items.Clear();
List<string> updatedList = new List<string>();
updatedList = (from x in source1
where !x.Equals(comboBox2.SelectedItem)
select x).ToList<string>();
comboBox1.Items.AddRange(updatedList.ToArray());
}
}
}
Make the source collections available avaiable to each combobox SelectedIndexChanged handlers
On each selection change update the source of the other combobox only if the newly selected item exists in the other combobox Items.

how to dynamically add combobox in windows forms(C#) and bound it to a column of a table in sql database

My windows form has an ADD button which adds a combo box to the form after each click. The problem is, i am not able to bind it to a table column at run time. Using an existing databinding source selects the same value in all the combo boxes. I am coding in C#
here is the sample code :
ComboBox ocbNext = new ComboBox();
//HAVE set the rest of the properties right, the problem is with the databinding
ocbNext.DataSource = this.dummysubjectBindingSource;
ocbNext.DisplayMember = "sub_name";
ocbNext.ValueMember = "sub_name";
this.Controls.Add(ocbNext);
I added a DataSet to the solution and droped the Employees table (from Northwind) in the designer, which automatically created the employeesBindingSource. I dropped a combobox and a button on the Form and I set the DataSource and DataMember of the combo. Then I handled some events:
private void Form1_Load(object sender, EventArgs e)
{
this.employeesTableAdapter.Fill(this.dS.Employees);
}
private int _i = 0;
private void button1_Click(object sender, EventArgs e)
{
ComboBox combo = new ComboBox();
combo.DataSource = this.employeesBindingSource;
combo.DisplayMember = this.dS.Tables[0].Columns[++_i].ColumnName;
combo.Location = new Point(comboBox1.Location.X, comboBox1.Location.Y + comboBox1.Height * _i);
this.Controls.Add(combo);
}
So on each click, a new combo is added onto the form dynamically right under the previous combo. The combo is also bound to the next column in the Employees table (no boundary checks however).
As you can see, this is pretty easy stuff. Hope this helps.
Okay, so here is a variation of the code that could help you with that other question you asked in the comments of this answer.
It assumes you have a Form with a button and a DataSet with table Employees. On button click it creates a combo, and fills it with data (the Name column of Employees). Each time you add a combo, it gets its own copy of the data (this is important to be able to remove items from one combo at a time). Then, every time you select a value in the combo, the combo is disabled and the other combos don't have that selected value in their list.
private int _i = 0;
private void button1_Click(object sender, EventArgs e)
{
DataSet dataS = dS.Clone();
this.employeesTableAdapter.Fill((DS.EmployeesDataTable)dataS.Tables[0]);
BindingSource bindSource = new BindingSource(dataS, "Employees");
ComboBox combo = new ComboBox();
combo.Name = this.dS.Tables[0].Columns[0].ColumnName + (++_i).ToString();
combo.DataSource = bindSource;
combo.DisplayMember = this.dS.Tables[0].Columns[1].ColumnName; //This column is the Name of Employee
combo.Location = new Point(button1.Location.X, button1.Location.Y + combo.Height * _i);
combo.SelectedIndexChanged += new EventHandler(comboBox_SelectedIndexChanged);
this.Controls.Add(combo);
}
private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is ComboBox && ctrl != sender && ctrl.Enabled)
{
((BindingSource)((ComboBox)ctrl).DataSource).RemoveAt(((ComboBox)sender).SelectedIndex);
}
}
((ComboBox)sender).Enabled = false;
}
This is pretty close to what you require, or easily adaptable to meet your expectations. Enjoy and please select an answer as the accepted one. Thanks!
Option 1: Fill the combobox with strings:
this.comboBox1.Items.Add("Syed");
this.comboBox1.Items.Add("Baqar");
Option 2: Fill the combobox with an array of strings:
this.comboBox1.Items.AddRange(new object[] { "Syed", "Baqar" });
You need to add controls to the parent window first, and then set the data source.
ComboBox ocbNext = new ComboBox();
this.Controls.Add(ocbNext);
ocbNext.DisplayMember = "sub_name";
ocbNext.ValueMember = "sub_name";
ocbNext.DataSource = this.dummysubjectBindingSource;
Should be fine if you create a new local ComboBox variable in the clickevent. If you use a global variable for the ComboBox this might explain your problems. But without a sample how you're doing it's hard to see what's really happening, so think this is just a rough guess

Categories