Add items to DataGridView - c#

I have a grid in which the sizes must be at the same height from the description.
private void btnAgregar_Click(object sender, EventArgs e)
{
dgvProformaDetalle.AutoGenerateColumns = false;
dgvProformaDetalle.DataSource = FillDgv();
dgvProformaDetalle.Columns["ColumnId"].DataPropertyName = "ProductoId";
dgvProformaDetalle.Columns["ColumnDescripcion"].DataPropertyName = "DescripcionProducto";
dgvProformaDetalle.Columns["ColumnTalla"].DataPropertyName = "DescripcionTalla";
}
private List<DetalleProformaExtendida> FillDgv()
{
List<DetalleProformaExtendida> listaArticulo = new List<DetalleProformaExtendida>();
DetalleProformaExtendida model = new DetalleProformaExtendida
{
ProductoId = txtIdProducto.Text,
DescripcionProducto = txtDescripcion.Text
};
listaArticulo.Add(model);
foreach (Talla item in checkedListBoxTallas.CheckedItems)
{
DetalleProformaExtendida _talla = new DetalleProformaExtendida();
_talla.TallaId = item.TallaId;
_talla.DescripcionTalla = item.Descripcion;
listaArticulo.Add(_talla);
}
return listaArticulo;
}

Maybe you want to set the ContentAlignment of your Cells? Maybe to TopLeft or TopRight?
dgvProformaDetalle.Columns["ColumnDescripcion"].CellTemplate.Style.Alignment =
DataGridViewContentAlignment.TopLeft;
dgvProformaDetalle.Columns["ColumnTalla"].CellTemplate.Style.Alignment =
DataGridViewContentAlignment.TopRight;
But I am really just guessing here..

Related

How to bind a many-to-many relation in WinForms?

I have the following DataSet:
The Product and Part tables can be edited using these DataGridViews:
When the user double-clicks a row in the Products grid, the following form opens:
The left column is supposed to list the parts associated with this product. The right column is supposed to list all the other parts. Using the << and >> buttons, the user should be able to choose which parts belong to the current product.
I have done something similar with a one-to-many relation and it worked perfectly. The code was as follows:
public partial class ProductPartsForm : Form
{
private int _productID;
private DataSet1 _data;
public ProductPartsForm(DataSet1 data, DataRowView productRowView)
{
var productRow = (DataSet1.ProductRow)productRowView.Row;
_productID = productRow.ID;
_data = data;
InitializeComponent();
productBindingSource.DataSource = productRowView;
assignedPartBindingSource.DataSource = productBindingSource;
assignedPartBindingSource.DataMember = "FK_Product_Part";
assignedPartsListBox.DisplayMember = "Name";
unassignedPartBindingSource.DataSource = _data;
unassignedPartBindingSource.DataMember = "Part";
unassignedPartsListBox.DisplayMember = "Name";
unassignedPartBindingSource.Filter = $"isnull(ProductID, 0) = 0";
}
private void assignButton_Click(object sender, EventArgs e)
{
var partRowView = (DataRowView)unassignedPartBindingSource.Current;
var partRow = (DataSet1.PartRow)partRowView.Row;
var productRowView = (DataRowView)productBindingSource.Current;
var productRow = (DataSet1.ProductRow)productRowView.Row;
partRow.ProductRow = productRow;
UpdateUI();
}
private void unassignButton_Click(object sender, EventArgs e)
{
var partRowView = (DataRowView)assignedPartBindingSource.Current;
var partRow = (DataSet1.PartRow)partRowView.Row;
partRow.SetProductIDNull();
UpdateUI();
}
private void UpdateUI()
{
assignedPartsListBox.Refresh();
unassignedPartsListBox.Refresh();
assignButton.Enabled = unassignedPartsListBox.Items.Count > 0;
unassignButton.Enabled = assignedPartsListBox.Items.Count > 0;
}
}
With the many-to-many relation, there are two things I couldn't get to work:
The left column doesn't show the names of the parts. It should display lowercase letters, like the right column; instead, it shows the string System.Data.DataRowView. I want to fix this using some sort of lookup, but I don't know how.
When you press <<, the selected part stays on the right column instead of moving to the left column. If you try to press << again with the same part, you get the following error:
System.Data.ConstraintException: 'Column 'ProductID, PartID' is constrained to be unique. Value '-4, -3' is already present.'
(which is understandable). I think this can be fixed using a filter expression, but I'm not sure how to write it and how to update the right column automatically after every change.
Has anyone done something similar and can help point me in the right direction?
Here's what I finally came up with. The key function is UpdateFilters, which creates a list of part IDs assigned to the current product and then filters the two columns "manually" using the IN and NOT IN operators.
public partial class ProductPartsForm : Form
{
private int _productID;
private DataSet1 _data;
public ProductPartsForm(DataSet1 data, DataRowView productRowView)
{
var productRow = (DataSet1.ProductRow)productRowView.Row;
_productID = productRow.ID;
_data = data;
InitializeComponent();
productBindingSource.DataSource = productRowView;
assignedPartBindingSource.DataSource = _data;
assignedPartBindingSource.DataMember = "Part";
assignedPartsListBox.DisplayMember = "Name";
unassignedPartBindingSource.DataSource = _data;
unassignedPartBindingSource.DataMember = "Part";
unassignedPartsListBox.DisplayMember = "Name";
}
private void ProductPartsForm_Load(object sender, EventArgs e)
{
UpdateFilters();
UpdateUI();
}
private void assignButton_Click(object sender, EventArgs e)
{
var partRowView = (DataRowView)unassignedPartBindingSource.Current;
var partRow = (DataSet1.PartRow)partRowView.Row;
var productRowView = (DataRowView)productBindingSource.Current;
var productRow = (DataSet1.ProductRow)productRowView.Row;
_data.ProductPart.AddProductPartRow(productRow, partRow);
UpdateFilters();
UpdateUI();
}
private void unassignButton_Click(object sender, EventArgs e)
{
var partRowView = (DataRowView)assignedPartBindingSource.Current;
var partRow = (DataSet1.PartRow)partRowView.Row;
var productPartRow = _data.ProductPart
.Single(pp => pp.ProductID == _productID && pp.PartID == partRow.ID);
_data.ProductPart.RemoveProductPartRow(productPartRow);
UpdateFilters();
UpdateUI();
}
private void UpdateFilters()
{
var assignedIds = _data.ProductPart
.Where(pp => pp.ProductID == _productID)
.Select(pp => pp.PartID.ToString());
if (assignedIds.Any())
{
assignedPartBindingSource.Filter = $"ID IN ({string.Join(",", assignedIds)})";
unassignedPartBindingSource.Filter = $"ID NOT IN ({string.Join(",", assignedIds)})";
}
else
{
assignedPartBindingSource.Filter = "FALSE";
unassignedPartBindingSource.RemoveFilter();
}
}
private void UpdateUI()
{
assignedPartsListBox.Refresh();
unassignedPartsListBox.Refresh();
assignButton.Enabled = unassignedPartsListBox.Items.Count > 0;
unassignButton.Enabled = assignedPartsListBox.Items.Count > 0;
}
}

how to clear all of datagridview rows including the first row(i have tried Dgv.DataSource = null; Dgv.Rows.Clear();)

I am a beginner of C# and created a DataGridView like:
private DataGridViewTextBoxColumn createText(string name, string Hname, int width)
{
DataGridViewTextBoxColumn tmt = new DataGridViewTextBoxColumn();
tmt.Name = name;
tmt.HeaderText = Hname;
tmt.Width = width;
tmt.DataPropertyName = name;
return tmt;
}
private DataGridViewComboBoxColumn PMcreateCombo(string name, int width, string item_str)
{
DataGridViewComboBoxColumn tmd = new DataGridViewComboBoxColumn();
string[] items;
items = item_str.Split(' ');
tmd.HeaderText = name;
tmd.Name = name;
//tmd.MaxDropDownItems = 4;
foreach (string str in items)
{
tmd.Items.Add(str);
}
tmd.Width = width;
tmd.DataPropertyName = name;
return tmd;
}
I want to use a numericupdown to control the number of columns, so i wrote something like this:
private void numericUD_ValueChanged(object sender, EventArgs e)
{
Dgv.DataSource = null;
Dgv.Rows.Clear();
Init();
}
private void Init()
{
SCM = new List<SCM>();
Dgv.AutoGenerateColumns = false;
Dgv.AllowUserToAddRows = false;
Dgv.Columns.Add(createText("AA", "AA", 60));
Dgv.Columns.Add(createCombo("QQ", 60, "RRR GGG BBB"));
addNewColumns();
Dgv.DataSource = Table;
}
But when i change the numericUpDown, the AA QQ and Addnewcolumn all are created just after the old one, but if i mark the Init() in the functionnumericUD_ValueChanged, the first row (AA QQ) still remains, but the second row disappears.
So i want to ask how to delete all of the element in DataGridView including the first row, then create a new one according to the numericrupdown
thanks
You need to refresh the DataGridView after clearing the datasource.
private void numericUD_ValueChanged(object sender, EventArgs e)
{
Dgv.DataSource = null;
Dgv.refresh();
Init();
}

Textbox autocomplete function not autocompleting in C# WinForm Application

Im having problems with this simple function on a textbox.. I have a winforms application, with a textbox, set up to autocomplete like this:
if (rbSerialNumSearch.Checked)
{
txtSerialNum.Enabled = true;
AutoCompleteStringCollection data = new AutoCompleteStringCollection();
//Test data
data.Add("555-777-333");
data.Add("222-333-444");
data.Add("111-222-333");
txtSerialNum.AutoCompleteCustomSource = data;
txtSerialNum.AutoCompleteMode = AutoCompleteMode.Suggest;
txtSerialNum.AutoCompleteSource = AutoCompleteSource.CustomSource;
}
But it is not working. Nothing appears when i type in the textbox? If i i specify strings directly to the textbox collection property (in design mode), it works fine, but when i try to add strings programmatically, nothing happends?
Thanks in advance..
ENTIRE CODE FOR FORM HERE:
namespace GUI
{
public partial class UpdateEquipmentForm : Form
{
EquipmentManager em;
ProductManager pm;
CategoryManager cm;
public UpdateEquipmentForm()
{
InitializeComponent();
em = new EquipmentManager();
pm = new ProductManager();
cm = new CategoryManager();
}
private void btnSearch_Click(object sender, EventArgs e)
{
if (rbCategorySearch.Checked)
{
List<Equipment> equipments = em.GetAllEquipmentInStock().Where(eq => eq.Product.Category_Id == (int)cbChooseCategory.SelectedValue).ToList();
var resultset = (from eq in equipments
select new { eq.Product.ProductNameNum, eq.Id, eq.SerialNumber, eq.InvoiceNumber, eq.CreatedDate, eq.ExpiryDate, eq.FirstUseDate }).ToList();
dgvResult.DataSource = resultset;
}
if (rbProductsSearch.Checked)
{
List<Equipment> equipments = em.GetAllEquipmentInStock().Where(eq => eq.Product.Id == (int)cbChooseType.SelectedValue).ToList();
var resultset = (from eq in equipments
select new { eq.Product.ProductNameNum, eq.Id, eq.SerialNumber, eq.InvoiceNumber, eq.CreatedDate, eq.ExpiryDate, eq.FirstUseDate }).ToList();
dgvResult.DataSource = resultset;
}
if (rbSerialNumSearch.Checked)
{
List<Equipment> equipments = em.GetAllEquipmentInStock();
var resultset = (from eq in equipments
where eq.SerialNumber.Contains(txtSearchEquipment.Text)
select new { eq.Product.ProductNameNum, eq.Id, eq.SerialNumber, eq.InvoiceNumber, eq.CreatedDate, eq.ExpiryDate, eq.FirstUseDate }).ToList();
dgvResult.DataSource = resultset;
}
}
private void rbCategorySearch_CheckedChanged(object sender, EventArgs e)
{
if (rbCategorySearch.Checked)
{
cbChooseCategory.Enabled = true;
cbChooseCategory.DataSource = cm.GetAllActiveCategories();
cbChooseCategory.DisplayMember = "Name";
cbChooseCategory.ValueMember = "Id";
}
else
{
cbChooseCategory.Enabled = false;
}
}
private void rbProductsSearch_CheckedChanged(object sender, EventArgs e)
{
if (rbProductsSearch.Checked)
{
cbChooseType.Enabled = true;
cbChooseType.DataSource = pm.GetAllActiveProducts();
cbChooseType.DisplayMember = "ProductNameNum";
cbChooseType.ValueMember = "Id";
}
else
{
cbChooseType.Enabled = false;
}
}
private void rbSerialNumSearch_CheckedChanged(object sender, EventArgs e)
{
if (rbSerialNumSearch.Checked)
{
txtSerialNum.Enabled = true;
AutoCompleteStringCollection data = new AutoCompleteStringCollection();
data.Add("555-777-333");
data.Add("222-333-444");
data.Add("111-222-333");
txtSerialNum.AutoCompleteCustomSource = data;
txtSerialNum.AutoCompleteMode = AutoCompleteMode.Suggest;
txtSerialNum.AutoCompleteSource = AutoCompleteSource.CustomSource;
}
else
{
txtSerialNum.Enabled = false;
}
}
}
}
Found the problem.. Really stupid of me. I was referencing the wrong textbox :-( The one i should be referencing is called txtSearchSerial and not txtSerialNum. Doh !
Appreciate the effort guys..thanks.
You can set a break point to
txtSerialNum.Enabled = true;
I think this application never run into this block.
Or after this code, you re-set the binding of txtSerialNum.

How to access a class from a listbox item?

I build a class that stores values from an XML file. I am loading that data into a ListBox like this:
private void LoadBookXML(string bookXML, ListBox theBookListBox)
{
XDocument loadedData = XDocument.Load(bookXML);
var data = from query in loadedData.Descendants("book")
select new Books
{
Title = (string)query.Attribute("title").Value.ToUpper(),
Theme = (string)query.Attribute("theme").Value,
Abbreviation = (string)query.Attribute("abbr").Value,
Chapters = (string)query.Attribute("chapters").Value,
Writer = (string)query.Attribute("writer").Value,
Place = (string)query.Attribute("place").Value,
Completed = (string)query.Attribute("completed").Value,
Time = (string)query.Attribute("time").Value,
Summary = (string)query.Attribute("summary").Value,
Link = (string)query.Attribute("link").Value,
Number = (string)query.Attribute("number").Value,
WriterAndPlace = "Written by " + (string)query.Attribute("writer").Value + " in " + (string)query.Attribute("place").Value,
};
theBookListBox.ItemsSource = data;
GestureService.GetGestureListener(theBookListBox).Hold += new EventHandler<GestureEventArgs>(theBookListBox_Hold);
When I press and hold an item in the ListBox, I am calling a function that brings up context menu like this:
private void theBookListBox_Hold(object sender, GestureEventArgs e)
{
AppState state = ThisApp._appState;
if (e.OriginalSource is TextBlock)
{
if (((string)((e.OriginalSource as TextBlock).Name)) == "btBookName")
{
UpdateLayout();
_cmReader = new ContextMenu();
MenuItem item = new MenuItem();
item.IsEnabled = true;
item.IsHitTestVisible = true;
TextBlock block = new TextBlock();
block.Text = "HELP, I AM TRYING TO GET DATA FROM THE BOOKS CLASS!!!";
block.TextDecorations = TextDecorations.Underline;
item.Header = block;
MenuItem item5 = new MenuItem
{
Header = "book info"
};
item5.Click += new RoutedEventHandler(bookInfo_Click);
_cmReader.Items.Add(item);
_cmReader.Items.Add(item5);
OpenContextMenu();
}
}
}
So my question is how can I access the data from the Books class that is stored into each of the ListBoxItems? I am using C#.
is that what you mean?
Books book = theBookListBox.SelectedItem as Books;
//All
foreach(Books book in theBookListBox.Items)
{
}
I think your class is inside of the form.
So its better do this...
private void LoadBookXML()
{
string bookXmL = "";
listBox theBookListBox = new ListBox();
Your other code here..
}
then.....
private void theBookListBox_Hold(object sender, GestureEventArgs e)
{
AppState state = ThisApp._appState;
if (e.OriginalSource is TextBlock)
{
if (((string)((e.OriginalSource as TextBlock).Name)) == "btBookName")
{
LoadBookXML();
Your other code here...
}
}
}

objects in datagridview

Im adding objects to a datagridview ( only one kind) through a list
ej.
List<Material> mater = new List<Material>();
DataGridView dgvMAterial = new DataGridView();
dgvMaterial.DataSource = null;
mater.Add((Material)cmbMaterial.SelectedValue);
dgvMaterial.DataSource = mater;
But every time I click over the datagrid I get an indexoutofrangeexeption.
Can somone tell me why?
thanks
here is my whole code for the form
public partial class inicio : Form
{
private string ConnectionString = "Data Source=localhost\\sqlexpress;Initial Catalog=data.mdf;Integrated Security=SSPI;";
//private string ConnectionString = "Server=.\\SQLExpress;AttachDbFilename=|DataDirectory|\\data\\data_data.mdf.mdf; Database=data.mdf;Trusted_Connection=Yes;";
private ISessionFactory sessionFactory;
List<Material> mater = new List<Material>();
List<Salarios> salar = new List<Salarios>();
IBindingList mind = new BindingList<Salarios>();
Productos prod;
public inicio()
{
InitializeComponent();
sessionFactory = nhn.BusinessObjects.Initialize.CreateSessionFactory(ConnectionString);
dgvMaterial.DataSource = mater;
}
private void materialToolStripMenuItem_Click(object sender, EventArgs e)
{
Catalogos.frmMaterial material = new costeos.Catalogos.frmMaterial(ConnectionString);
material.ShowDialog(this);
material.Dispose();
}
private void salariosToolStripMenuItem_Click(object sender, EventArgs e)
{
Catalogos.frmSalarios salarios = new costeos.Catalogos.frmSalarios(ConnectionString);
salarios.ShowDialog(this);
salarios.Dispose();
}
private void agregarToolStripMenuItem_Click(object sender, EventArgs e)
{
Catalogos.frmAddRemuneraciones rem = new costeos.Catalogos.frmAddRemuneraciones(ConnectionString);
rem.ShowDialog(this);
rem.Dispose();
}
private void agregarToolStripMenuItem1_Click(object sender, EventArgs e)
{
Catalogos.frmAddAdmin adm = new costeos.Catalogos.frmAddAdmin(ConnectionString);
adm.ShowDialog(this);
adm.Dispose();
}
private void agregarToolStripMenuItem2_Click(object sender, EventArgs e)
{
Catalogos.frmAddInsumosInd insumos = new costeos.Catalogos.frmAddInsumosInd(ConnectionString);
insumos.ShowDialog(this);
insumos.Dispose();
}
private void txt_KeyPress(object sender, KeyPressEventArgs e)
{
if (char.IsDigit(e.KeyChar) || char.IsPunctuation(e.KeyChar) || char.IsControl(e.KeyChar))
{
e.Handled = false;
}
else
{
e.Handled = true;
}
}
private void inicio_Load(object sender, EventArgs e)
{
LlenaCampos();
}
private void LlenaCampos()
{
using (var session = sessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var mat = session.CreateCriteria(typeof(Material))
.List<Material>();
var sal = session.CreateCriteria(typeof(Salarios))
.List<Salarios>();
transaction.Commit();
cmbMaterial.DataSource = mat;
cmbMaterial.DisplayMember = "Nombre";
cmbSalarios.DataSource = sal;
cmbSalarios.DisplayMember = "Nombre";
cmbMIndirecta.DataSource = sal;
cmbMIndirecta.DisplayMember = "Nombre";
}
}
}
private void btnAddMaterial_Click(object sender, EventArgs e)
{
materialBindingSource.DataSource = null;
//dgvMaterial.DataSource = null;
mater.Add((Material)cmbMaterial.SelectedValue);
//dgvMaterial.DataSource = mater;
dgvMaterial.DataSource = materialBindingSource;
materialBindingSource.DataSource = mater;
materialBindingSource.ResetBindings(false);
}
private void button2_Click(object sender, EventArgs e)
{
dgvSalarios.DataSource = null;
salar.Add((Salarios)cmbSalarios.SelectedValue);
dgvSalarios.DataSource = salar;
}
private void button3_Click(object sender, EventArgs e)
{
dgvMIndirecta.DataSource = null;
mind.Add((Salarios)cmbMIndirecta.SelectedValue);
dgvMIndirecta.DataSource = mind;
}
private void button1_Click(object sender, EventArgs e)
{
using (var session = sessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
if (prod == null)
{
prod = new Productos { CargasTurno = float.Parse(txtCargasTurno.Text), CavidadesMolde = int.Parse(txtCavidadesMolde.Text), Clave = txtClave.Text, Comentarios = txtComentarios.Text, MezclasTurno = float.Parse(txtMezclasTurno.Text), Moldes = int.Parse(txtMoldes.Text), Nombre = txtNombre.Text, Peso = float.Parse(txtPesoTotal.Text), TotalPza = int.Parse(txtPzasTotales.Text), Turnos = int.Parse(txtTurnos.Text) };
session.Save(prod);
transaction.Commit();
}
foreach (DataGridViewRow dr in dgvMaterial.Rows)
{
Material m = dr.DataBoundItem as Material;
m.Materiales
PMaterial mat = new PMaterial { Material = dr.DataBoundItem as Material, Cantidad = float.Parse(dr.Cells["Cantidad"].Value.ToString()), Fecha = DateTime.Now, Producto = prod };
session.Save(mat);
}
transaction.Commit();
session.Close();
}
}
}
}
}
That's probably not DGV problem, but with this combo box. Show us the code that fills combo box and sets its properties.
If you are casting to Material class you should probably use SelectedItem instead of SelectedValue. (unless you exactly know what you're doing)
I would guess that you have an event-handler that isn't happy. What exactly does the message say?
You might also be having problems if you are adding the same Material instance to the list multiple times; since IndexOf will only find the first occurrence. This line makes me very suspicious:
mater.Add((Material)cmbMaterial.SelectedValue);
since it could potentially (on consecutive clicks / etc) do exactly this.
Note: if you used BindingList<T> instead all you'd have to doo is Add(...) - no resetting required:
field:
BindingList<Material> mater = new BindingList<Material>();
init grid:
dgvMaterial.DataSource = mater;
add item:
mater.Add(newInstance);
If you assign data source to the DGV you should check element count - if zero then assign null. I don't know why this is the way it is, but I'm doing it in all my forms.
//I'm still analysing the rest of the code

Categories

Resources