I have a crud form with a datagridview.
Here's my "refresh" code:
private void Recuperar()
{
DataSet ds = new DataSet();
string CommandText = "SELECT * from sectores order by sector";
SQLiteDataAdapter adapter = new SQLiteDataAdapter(CommandText, Variables.Conexion);
DataTable table = new DataTable();
table.TableName = "sectores";
adapter.Fill(table);
grilla.DataSource = table;
grilla.Refresh();
grilla.Columns["sector_id"].Visible = false;
grilla.Columns["clave"].Visible = false;
grilla.Columns["sector"].HeaderText = "Sector";
grilla.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
SetDataBinding();
}
private void SetDataBinding()
{
this.textBoxId.DataBindings.Clear();
this.textBoxId.DataBindings.Add(new System.Windows.Forms.Binding("Text", grilla.DataSource, "sector_id"));
this.tbSector.DataBindings.Clear();
this.tbSector.DataBindings.Add(new System.Windows.Forms.Binding("Text", grilla.DataSource, "sector"));
this.tbClave1.DataBindings.Clear();
this.tbClave1.DataBindings.Add(new System.Windows.Forms.Binding("Text", grilla.DataSource, "clave"));
this.tbClave2.DataBindings.Clear();
this.tbClave2.DataBindings.Add(new System.Windows.Forms.Binding("Text", grilla.DataSource, "clave"));
}
In the code of my "Add" button, i clear the text of my controls (the controls that are binded to the datagrid), so the user insert the new values.
private void btn_agregar_Click(object sender, EventArgs e)
{
grilla.ClearSelection();
accion = DataRowAction.Add;
SetEstado();
}
private void SetEstado()
{
if (accion == DataRowAction.Add)
btn_guardar.Text = "Agregar";
if (accion == DataRowAction.Change)
btn_guardar.Text = "Modificar";
if (accion == DataRowAction.Delete)
btn_guardar.Text = "Eliminar";
if (accion == DataRowAction.Nothing)
btn_guardar.Text = "Guardar";
groupBoxControles.Enabled = accion == DataRowAction.Add || accion == DataRowAction.Change;
PanelDerechaBotones.Enabled = accion != DataRowAction.Nothing;
panelAbajo.Enabled = accion == DataRowAction.Nothing;
grilla.Enabled = accion == DataRowAction.Nothing;
if (accion == DataRowAction.Add)
{
textBoxId.Text = "0";
tbSector.Text = "";
tbClave1.Text = "";
tbClave2.Text = "";
}
if (accion == DataRowAction.Add || accion == DataRowAction.Change)
{
tbSector.Focus();
}
}
the problem is that when the user cancels this action, the row that was selected in the grid now looks all empty. (moved empty values from the controls to the grid)
I know I'm missing something, but don't know what.
appreciate if someone help me.
Cancel button code
private void btn_cancelar_Click(object sender, EventArgs e)
{
accion = DataRowAction.Nothing;
SetEstado();
//((DataTable)grilla.DataSource).RejectChanges();
}
I am assuming that the cancel button is posting back and you are not rebinding? The grid has to be rebound after every postback.
Related
I want only 3 of the columns in my table in Datagridview1 not to be empty. I want it to warn the screen when there is an empty field.
I tried to make a mandatory field to be filled in the datagridview1 table
When I add other data to the data I pull from sql in Datagridview, I want it to warn the screen to be filled if there should be no empty space.
As you can see in the photo below, only those places should not be empty, and when I press save, it should detect when there is an empty space and give a warning to the screen.
give a warning if there is free space
private void btn_Save_Click(object sender, EventArgs e)
{
SqlCommand cmd = new SqlCommand("Select * from Envanter where BilgNo,VarlikSahibi,IP", baglanti);
cmd.Parameters.AddWithValue("BilgNo", dataGridView1);
cmd.Parameters.AddWithValue("VarlikSahibi", dataGridView1);
cmd.Parameters.AddWithValue("IP", dataGridView1);
foreach (DataGridViewRow row in dataGridView1.Rows)
{
commandBuilder = new SqlCommandBuilder(da);
da.Update(tablo);
MessageBox.Show("Saved");
Envanter();
return;
/*
if (dataGridView1.Rows.Cells[1].Value == null | Convert.ToString(row.Cells[1].Value) | string.IsNullOrEmpty)
{
DialogResult dr = MessageBox.Show("pls no empty", "Warn!", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
return;
*/
}
}
If you are using plain C# model classes, you can rely on data annotations validation attributes.
If you are using DataTable as the model, you can validate the DataTable by setting column or row errors and check if the data table has errors.
You can also look over the rows or cells of DataGridView and set cell or row errors, with or without databinding.
Example - Validating Cells of DataGridView and show error on cells
private bool ValidateCell(DataGridViewCell cell)
{
//Validation rules for Column 1
if (cell.ColumnIndex == 1)
{
if (cell.Value == null ||
cell.Value == DBNull.Value ||
string.IsNullOrEmpty(cell.Value.ToString()))
{
cell.ErrorText = "Required";
return false;
}
else
{
cell.ErrorText = null;
return true;
}
}
//Other validations
return true;
}
private bool ValidateDataGridView(DataGridView dgv)
{
return dgv.Rows.Cast<DataGridViewRow>()
.Where(r => !r.IsNewRow)
.SelectMany(r => r.Cells.Cast<DataGridViewCell>())
.Select(c => ValidateCell(c)).ToList()
.All(x => x == true);
}
Then use above methods before saving the data:
private void SaveButton_Click(object sender, EventArgs e)
{
if (!ValidateDataGridView(dataGridView1))
{
MessageBox.Show("Please fix validation errors");
return;
}
//Save changes;
}
To show the errors on cells or rows of DataGridView, set ShowRowErrors and ShowCellErrors to true.
dataGridView1.DataSource = dt;
dataGridView1.ShowCellErrors = true;
Also, if you want to update the validations of the cells, after editing the cell:
private void DataGridView1_CellValueChanged(object sender,
DataGridViewCellEventArgs e)
{
ValidateCell(dataGridView1[e.ColumnIndex, e.RowIndex]);
}
First Iterate over the dataset rows and then iterate over the value of each cell if there are any empty values return the message box of your choice to the user. Please find the below attached code for your reference.
You can do the following :
foreach (DataGridViewRow rw in this.dataGridView1.Rows)
{
for (int i = 0; i < rw.Cells.Count; i++)
{
if (rw.Cells[i].Value == null || rw.Cells[i].Value == DBNull.Value || String.IsNullOrWhiteSpace(rw.Cells[i].Value.ToString())
{
// here is your input message box...
string promptValue = Prompt.ShowDialog("Message", "some other string you want!");
}
else
{
// Proceed with the things you want to do..
}
}
}
And use the below code to create an input popup:
public static class Prompt
{
public static string ShowDialog(string text, string caption)
{
Form prompt = new Form()
{
Width = 500,
Height = 150,
FormBorderStyle = FormBorderStyle.FixedDialog,
Text = caption,
StartPosition = FormStartPosition.CenterScreen
};
Label textLabel = new Label() { Left = 50, Top=20, Text=text };
TextBox textBox = new TextBox() { Left = 50, Top=50, Width=400 };
Button confirmation = new Button() { Text = "Ok", Left=350, Width=100, Top=70, DialogResult = DialogResult.OK };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(textBox);
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.AcceptButton = confirmation;
return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
}
}
And you can call it using :
string promptValue = Prompt.ShowDialog("Message", "some other string you want!");
I am needing that if there is no CheckBox selected in the DataGridView the button Uno and the button Varios are disabled.
If a single CheckBox is selected, the button Uno is enabled and the button Varios disabled.
And if there is more than one CheckBox selected, the button Uno is disabled and the button Varios is enabled.
But, the following happens:
The code I use is the following:
public Form1()
{
InitializeComponent();
btnUno.Enabled = false;
btnVarios.Enabled = false;
}
To enable and disable the buttons:
private void dtgTitulo_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
int contador = 0;
foreach (DataGridViewRow row in dtgTitulo.Rows)
{
if (row.Cells["Seleccione"].Value != null && row.Cells["Seleccione"].Value.Equals(true))//Columna de checks
{
contador++;
if (contador <= 0)
{
btnUno.Enabled = false;
btnVarios.Enabled = false;
}
else if (contador == 1)
{
btnUno.Enabled = true;
btnVarios.Enabled = false;
}
else
{
btnUno.Enabled = false;
btnVarios.Enabled = true;
}
}
}
}
Can someone help me? Any suggestion?
UPDATE
HOW TO I LOAD THE DATAGRIDVIEW WITH CHECKBOXES:
private DataTable Query()
{
DataTable datos = new DataTable();
SqlConnection sqlConn = new SqlConnection("STRING");
try
{
sqlConn.Open();
string consulta = "SELECT Titulo AS Título FROM V_CuetaWeb GROUP BY titulo ORDER BY titulo DESC";
SqlCommand sqlCommand = new SqlCommand(consulta, sqlConn);
SqlDataAdapter da = new SqlDataAdapter(sqlCommand);//este se encarga de inicializar el command
da.Fill(datos);
sqlConn.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return datos;
}
I form_Load:
private void Form1_Load(object sender, EventArgs e)
{
ds = new DataSet();
ds.Tables.Add(Query());
ds.Tables[0].Columns.Add("Seleccione", typeof(bool));
dtgTitulo.DataSource = ds.Tables[0];
}
Try Below code:
AS per #JIMI's suggestion
private void dtgTitulo_CellMouseUp(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != 1) return;
dtgTitulo.CommitEdit(DataGridViewDataErrorContexts.Commit);
var contador = dtgTitulo.Rows.OfType<DataGridViewRow>().Count(r => (r.Cells[1].Value != null) && ((bool)r.Cells[1].Value == true));
if (contador <= 0)
{
btnUno.Enabled = false;
btnVarios.Enabled = false;
}
else
{
if (contador == 1)
{
btnUno.Enabled = true;
btnVarios.Enabled = false;
}
else
{
btnUno.Enabled = false;
btnVarios.Enabled = true;
}
}
}
after click on checkboxes they show/hide ticks, but value in cell doesn't change immediately. call EndEdit to apply them.
private void dtgTitulo_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex < 0 || dtgTitulo.Columns[e.ColumnIndex].Name != "Seleccione")
return;
dtgTitulo.EndEdit();
int contador = 0;
foreach (DataGridViewRow row in dtgTitulo.Rows)
{
if (Equals(true, row.Cells["Seleccione"].Value))
{
contador++;
if (contador > 1)
break;
}
}
btnUno.Enabled = contador == 1;
btnVarios.Enabled = contador > 1;
}
p.s. note optimizations made to avoid unnecessary iterations
This is the view of my datagridview..
This is the translate button when i click it a new row appears next to it and a new button is also initialized in that row.
Now what i want is that if the translate button is clicked the new row that appears shouldn't contain the translate button..i have initialized the button dynamically..Here is my code.
private void button()
{
var buttonCol = new DataGridViewButtonColumn();
buttonCol.Name = "ButtonColumnName";
buttonCol.HeaderText = "Header";
buttonCol.Text = "Translate";
buttonCol.Name = "Edit";
buttonCol.Width = 30;
buttonCol.UseColumnTextForButtonValue = true;
dataGridView1.Columns.Add(buttonCol);
}
This is the event when the button is clicked..
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
// button();
Column_handling();
if (e.ColumnIndex == 10)
{
DataRow dt = datarows.NewRow();
dt[0] = this.dataGridView1.CurrentRow.Cells[0].Value.ToString();
dt[1] = this.dataGridView1.CurrentRow.Cells[1].Value.ToString();
dt[2] = this.dataGridView1.CurrentRow.Cells[2].Value.ToString();
dt[3] = this.dataGridView1.CurrentRow.Cells[3].Value.ToString();
dt[4] = this.dataGridView1.CurrentRow.Cells[4].Value.ToString();
dt[5] = this.dataGridView1.CurrentRow.Cells[5].Value.ToString();
dt[6] = this.dataGridView1.CurrentRow.Cells[6].Value.ToString();
dt[7] = this.dataGridView1.CurrentRow.Cells[7].Value.ToString();
dt[8] = this.dataGridView1.CurrentRow.Cells[8].Value.ToString();
dt[9] = this.dataGridView1.CurrentRow.Cells[9].Value.ToString();
datarows.Rows.InsertAt(dt, e.RowIndex+1);
dataGridView1.Refresh();
}
any ideas?
You have to change cell type to TextBox.
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
Column_handling();
if (e.ColumnIndex == 10)
{
DataRow dt = datarows.NewRow();
//fillign vlaues
datarows.Rows.InsertAt(dt, e.RowIndex + 1);
var row = this.dataGridView1.Rows[e.RowIndex + 1];
var cell = new DataGridViewTextBoxCell();
cell.Value = string.Empty;
row.Cells["ButtonColumnName"] = cell;
cell.ReadOnly = true;
dataGridView1.Refresh();
}
}
I made cell ReadOnly to stop user from inputting anything into it.
Button method pass a boolean field as parameter and set it false when you click Translate button to create row.
Then set the Visibility property to this boolean field
set default value true otherwise.
Ok, I know it is an old post, but anyhow... This is what works for me.
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if ((dataGridView1.Columns[e.ColumnIndex] as DataGridViewButtonColumn) != null && dataGridView1.Rows[e.RowIndex].IsNewRow)
{
DataGridViewCellStyle emptyCellStyle = new DataGridViewCellStyle();
emptyCellStyle.Padding = new Padding(75, 0, 0, 0);
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style = emptyCellStyle;
}
}
I have a Winforms datagridview where the existing rows shouldn't be editable but the new row should be.
So i set the ReadOnly property to true on the grid, but then i still see the new row but can't edit it.
How can i combine these two properties ?
EDIT: just tried to set ReadOnly to true, but still can't edit or add new rows.
conn = new SqlCeConnection();
conn.ConnectionString = connectionstring;
conn.Open();
daFacturen = new SqlCeDataAdapter("SELECT * FROM Factuur", conn);
daFacturen.Fill(dsKlantenBeheer, "tblFactuur");
daFactuurRegels = new SqlCeDataAdapter("SELECT * FROM Factuurregel", conn);
daFactuurRegels.Fill(dsKlantenBeheer, "tblFactuurregel");
// Relation between customers and orders
DataRelation relKlantFactuur;
DataColumn relKlantFactuurcolMaster;
DataColumn relKlantFactuurcolDetail;
relKlantFactuurcolMaster = dsKlantenBeheer.Tables["tblKlant"].Columns["ID"];
relKlantFactuurcolDetail = dsKlantenBeheer.Tables["tblFactuur"].Columns["KlantID"];
relKlantFactuur = new DataRelation("RelKlantFactuur", relKlantFactuurcolMaster, relKlantFactuurcolDetail);
dsKlantenBeheer.Relations.Add(relKlantFactuur);
DataRelation relFactFactregel;
DataColumn relFactFactregelcolMaster;
DataColumn relFactFactregelcolDetail;
relFactFactregelcolMaster = dsKlantenBeheer.Tables["tblFactuur"].Columns["ID"];
relFactFactregelcolDetail = dsKlantenBeheer.Tables["tblFactuurregel"].Columns["FactuurID"];
relFactFactregel = new DataRelation("relFactFactregel", relFactFactregelcolMaster, relFactFactregelcolDetail);
dsKlantenBeheer.Relations.Add(relFactFactregel);
DataViewManager dsView = dsKlantenBeheer.DefaultViewManager;
dsView.DataViewSettings["tblKlant"].RowFilter = "Status = 0 or Status is null";
dsView.DataViewSettings["tblKlant"].Sort = "Naam, Voornaam";
// Grid Databinding
dgvFacturen.DataSource = dsView;
dgvFacturen.DataMember = "tblKlant.relKlantFactuur";
dgvFacturen.ReadOnly = true;
dgvFacturen.allowUserToAddRows = true;
Set ReadOnly for row/cells only, not for whole grid:
var row = dataGridView1.Rows[0];
row.ReadOnly = true; //whole row can't be edited
or
var row = dataGridView1.Rows[0];
row.Cells[0].ReadOnly = true; //only first cell is not editable
When DataGridView is ReadOnly then you can't edit, add, delete any row/cell in grid.
Here is my solution, simply add some custom code to CellBeginEdit, like this:
public bool Editable {get;set;}
int i;
private void dataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if(Editable) return;
if(i == e.RowIndex)
{
foreach (DataGridViewCell cell in dataGridView1.Rows[e.RowIndex].Cells)
{
if (cell.Value == null)
{
return;
}
}
e.Cancel = true;
}
else if (dataGridView1.Rows.Count - 1 != e.RowIndex)
{
e.Cancel = true;
}
else i = e.RowIndex;
}
The code above prevent you from re-editing the new row once you input all the values for all the cells in that row. If you want to allow user to edit that new row after committing all the values, the code seems to be much simpler:
private void dataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if(Editable) return;
if(e.RowIndex < dataGridView.Rows.Count - 2)
{
e.Cancel = true;
}
}
I've tested and works like a charm. I suppose your new row will have all the cells input with new values.
The listbox populates but can't find the selected value. It's either null or the default value (first item). Whenever I select another item, it changes to null. I did the !ispostback but still nothing. Using a wizard in asp.net/c#/sql. Any help is appreciated.
protected void Page_Load(object sender, EventArgs e)
{
ListBox lstService = (ListBox)Wizard1.FindControl("lstService");
string s = lstService.SelectedValue.ToString();
int s1 = lstService.SelectedIndex;
if (s == "MarketTrack Toys")
{
Wizard2.Visible = true;
}
if (!Page.IsPostBack)
{
BindGrid();
}
if ((Wizard1.ActiveStepIndex <= 5) && (Wizard1.ActiveStepIndex != 0))
{
Wizard1.DisplaySideBar = true;
Wizard2.DisplaySideBar = false;
}
else
{
Wizard1.DisplaySideBar = false;
Wizard2.DisplaySideBar = true;
}
}
private void BindGrid()
{
dAS = new DataAccessClass();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
ds = dAS.func_FillDataset("select servicename from dbo.Services", "Services");
ListBox lstService = (ListBox)Wizard1.FindControl("lstService");
lstService.DataSource = ds;
lstService.DataTextField = "ServiceName";
lstService.DataValueField = "ServiceName";
lstService.DataBind();
if (lstService.Items.Count > 0)
{
lstService.SelectedIndex = 0;
}
}
Walk it through in a debugger.
Whatever Object that is being placed in the ListBox doesn't know to convert itself to the string you're looking for with ToString()
The ListBox populates correctly because you specify how to get the names with lstService.DataTextField = "ServiceName";
You may have to rework the object you're putting in the ListBox or just override to ToString for that object instead.