Hide GridView Image Column if Database value is Null - c#

I have a Gridview which has an image column to the right side.When the user checks a checkbox only those items with a non Null Image should be displayed.
I have seen that the Gridview uses the default Image if the database image corresponding to the row is empty.Will i need to write a new stored procedure for this or is there a better way to do it.
I currently have implemented this
try
{
if (checkBox1.Checked == true)
{
dgvGetData.Columns["image"].Visible = true;
foreach (DataGridViewRow row in dgvGetData.Rows)
{
Console.WriteLine("LOOP");
if (row.Cells[16].Value == null)
{
Console.WriteLine("######################################> NULL");
row.Visible = false;
}
else
{
Console.WriteLine("######################################> NOT NULL");
}
}
}
else
{
dgvGetData.Columns["image"].Visible = false;
}
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}

I'd recommend that you use the CellFormatting event handler. You can write a few lines of code to determine if you're on the correct column and then have it display whatever you want.
Here is a partial example:
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.Value == null && dataGridView1.Columns[e.ColumnIndex].Name == "Image")
{
dataGridView1.Rows[e.RowIndex].Visible = false;
}
}
https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcellformattingeventhandler(v=vs.110).aspx

Related

How to detect empty space in datagridview and warn the screen if it is empty?

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!");

Select all checkboxes for updating data in datagridview

I'm trying to update some of data from datagridview by selecting the checkbox headers for the rows I want to update and then pressing the update button. Problem is that it's not updating the rows as intended, it updates all columns except one. I need a way to update all columns of the rows that have been selected by the checkbox header.
Here is my current code:
private void Main_Load(object sender, EventArgs e)
{
DataGridViewCheckBoxColumn checkColumn = new DataGridViewCheckBoxColumn();
checkColumn.Name = "chk";
checkColumn.HeaderText = "Select";
checkColumn.Width = 50;
checkColumn.ReadOnly = false;
checkColumn.FillWeight = 10;
dataGridView1.Columns.Add(checkColumn);
}
private void checkboxheader_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (Convert.ToBoolean(row.Cells["chk"].Value) == false)
{
row.Cells["chk"].Value = true;
}
else
{
row.Cells["chk"].Value = false;
}
}
}
private void btnCHKPO_Click(object sender, EventArgs e)
{
Cursor = Cursors.WaitCursor;
DialogResult result = MessageBox.Show("Check Purchase Request ?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
int i = 0;
var addRows = new List<DataRow>();
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (Convert.ToBoolean(row.Cells["chk"].Value) == true)
{
addRows.Add(((DataRowView)row.DataBoundItem).Row);
var ST = 2;
row.Cells["ISSU_FLG"].Value = ST;
}
}
if (addRows.Count > 0)
{
if ((addRows != null))
{
for (; i < addRows.Count(); i++)
{
try
{
objConnect.UpdateDatabase(addRows.ToArray());
Po = 1;
}
catch (Exception err)
{
MessageBox.Show(err.Message,
"Information",
MessageBoxButtons.OK,
MessageBoxIcon.Asterisk,
MessageBoxDefaultButton.Button1);
}
}
if (Po == 1)
{
MessageBox.Show("Purchase Request Has Been Checked !" + "\n" + "Please search the data again",
"Information",
MessageBoxButtons.OK,
MessageBoxIcon.Asterisk,
MessageBoxDefaultButton.Button1);
Cursor = Cursors.Default;
btnSave_Click(this, new EventArgs());
}
}
}
else
{
MessageBox.Show("Please Select Row For Checking PO Info !",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Stop,
MessageBoxDefaultButton.Button1);
Cursor = Cursors.Default;
}
}
}
Alright, I don't know what your problem is, but I have a few ideas.
Firstly, there is the chance that for some reasons, when you're adding the rows, there are some missing. From the code you've given, I can't see anything wrong with the code, looks like you're correctly adding to the list based on the checkbox value. To ensure this isn't the problem, put a breakpoint on the if statement if (addRows.Count > 0) and check the value of the 'addRows' variable to ensure all the rows you expect are in there. If you're not sure on how to do this, google debugging in visual studio (or whatever IDE you're using).
Secondly, there is an issue with this objConnect.UpdateDatabase(addRows.ToArray()); I don't recognise this code, and not sure what it does. Is this part of EFC? Are you using a custom library to update your database? This is likely where the problem lies. Based on the code you've provided, I'm unsure of the structure of the database, how it's updated, and what technologies your using to do so. Maybe provide the setup for the database in your question? But this looks like where the issue may arise.
I've also got some optional feedback, there is some issues with your code in general that I have so advice for you on, but lets work through it piece by piece.
Firstly, instead of:
private void checkboxheader_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (Convert.ToBoolean(row.Cells["chk"].Value) == false)
{
row.Cells["chk"].Value = true;
}
else
{
row.Cells["chk"].Value = false;
}
}
}
Do this:
private void checkboxheader_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
row.Cells["chk"].Value = !Convert.ToBoolean(row.Cells["chk"].Value) ;
}
}
This improves the readability of your code, it's basically saying 'Set this cell's value to the opposite of what it was', without the need for the large if statement.
Then in the first foreach block, change:
if (Convert.ToBoolean(row.Cells["chk"].Value) == true)
to
if (Convert.ToBoolean(row.Cells["chk"].Value))
Same principle. If statements will execute code based on a boolean.
E.g.
true == true is true.
false == true is false.
The point being, there is no need to compare your value to true, as when it's true, it'll be true regardless, and when it's false, it'll be false regardless.
Look into boolean algebra to learn more.
Combine the next two ifs.
if (addRows.Count > 0)
{
if ((addRows != null))
{
Like so:
if (addRows != null && addRows.Count > 0)
Note: always check for null in a variable before you use it, if you don't you risk a null reference exception. Does your program crash if you try to update with nothing selected?
Finally:
for (; i < addRows.Count(); i++)
{
try
{
objConnect.UpdateDatabase(addRows.ToArray());
Po = 1;
}
catch (Exception err)
{
MessageBox.Show(err.Message,
"Information",
MessageBoxButtons.OK,
MessageBoxIcon.Asterisk,
MessageBoxDefaultButton.Button1);
}
}
Currently, your adding to the rows you want to update to 'addRows', and here your iterating over each row. Now I think what you're trying to do is update each individual row, one at a time, but then you call
objConnect.UpdateDatabase(addRows.ToArray())
This is passed an array, which is multiple rows. So your updating the full set or rows, rather than each individual row. So there is no need to loop through each row. To fix this code, change it to:
try
{
objConnect.UpdateDatabase(addRows.ToArray());
Po = 1;
}
catch (Exception err)
{
MessageBox.Show(err.Message,
"Information",
MessageBoxButtons.OK,
MessageBoxIcon.Asterisk,
MessageBoxDefaultButton.Button1);
}
So remove the for loop.
You can do even more than this, but it's a decent start.

Trigger GridView1_SelectedIndexChanged event in pageload if session is == to column

I am trying to use selectedindex on my gridview if it has a column with an == value to session.
Right now I am only successfull on changing its background color. But how could I also trigger the button If it has similar value on my Session.
private void load_session_value()
{
string trans_id = Session["transaction_id_report"].ToString();
string trans_number = Session["transaction_no_report"].ToString();
//string grid_value_id = GridView1
//string grid_value_num
if (trans_id != null && trans_number != null)
{
foreach (GridViewRow row in GridView1.Rows)
{
if (row.Cells[1].Text.ToString() == trans_id && row.Cells[2].Text.ToString() == trans_number)
{
row.BackColor = ColorTranslator.FromHtml("#A1DCF2");
GridView1_SelectedIndexChanged(new object(),new EventArgs());
}
}
}
}
This is my current output during page_load
I'm not sure, but i think you are looking for this.
if (row.Cells[1].Text.ToString() == trans_id && row.Cells[2].Text.ToString() == trans_number)
{
row.BackColor = ColorTranslator.FromHtml("#A1DCF2");
//call the Button1_Click method
Button1_Click(new object(), new EventArgs());
}
protected void Button1_Click(object sender, EventArgs e)
{
//do the button click stuff
}

Reloading and Updating using Entity Framework and DBContext

Ok so I have tried a few things and keep getting stuck. I had the update button working at one point and now it will not update. The delete button will work and delete records but I can not get the gridview to refresh after the record is deleted. I also want the gridview to reload after the update button is pressed and the record is updated. Here is what I have:
protected void btnDelete_Click(object sender, EventArgs e)
{
switch (btnDelete.Text)
{
case DeleteButton:
try
{
if (txtLocationName.Text != null && txtSubAccountName.Text != null)
{
Location locationCheck = _context.Locations.ToList()
.First(x => x.Name == txtLocationName.Text && x.SubAccount == txtSubAccountName.Text);
if (locationCheck != null)
{
Location n = new Location
{
Id = grdvwLocationList.SelectedIndex,
Name = txtLocationName.Text,
SubAccount = txtSubAccountName.Text
};
_context.Locations.Remove(n);
_context.SaveChanges();
}
}
}
catch (Exception)
{
lblLocationNameNotification.Text = "Please type in a location/sub-account or select a location/sub-account that doesn't have a asset to delete.";
txtLocationName.Text = "";
txtSubAccountName.Text = "";
}
break;
case CancelButton:
Reload();
break;
}
}
public void PopulateLocationGridView()
{
var locations = _context.Locations.Where(l => l.CompanyId == CompanyId)
.OrderBy(l => l.Name)
.ToList();
grdvwLocationList.DataSource = locations;
grdvwLocationList.DataBind();
if (locations.Count > 0)
{
grdvwLocationList.SelectedIndex = 0;
RowSelected();
}
else
{
txtLocationName.Text = "";
txtSubAccountName.Text = "";
}
}
The add button works just fine it just seems to be refreshing the grid view
I have the following exampe working in a winforms application
The trick is the dset.local
private void Form1_Load(object sender, EventArgs e)
{
var dset = Db.Tasks; // Db is my context.
DbSet<Task> qry = dset;
qry.Load();
bindingSource1.DataSource =dset.Local.ToBindingList();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Debug.Print(Db.Tasks.Count().ToString());
bindingSource1.EndEdit();
Db.SaveChanges();
}
After working on it last night I knew there was something that I was missing. I ended up going about it like this:
protected void btnDelete_Click(object sender, EventArgs e)
{
try
{
_context = new IMSDBContext();
switch (btnDelete.Text)
{
case DeleteButton:
if (txtLocationName.Text != null && txtSubAccountName.Text != null)
{
Location location = _context.Locations.ToList()
.First(x => x.Name == txtLocationName.Text && x.SubAccount == txtSubAccountName.Text);
_context.Locations.Remove(location);
_context.SaveChanges();
PopulateLocationGridView();
grdvwLocationList.SelectedIndex = 0;
RowSelected();
}
break;
case CancelButton:
Reload();
break;
}
}
catch (Exception ex)
{
lblLocationNameNotification.Text = ex.Message;
}
finally
{
if (_context != null)
{
_context.Dispose();
}
}
}
I had tried to use the PopulateLocationGridView() and RowSelect() methods by themselves and it was still having trouble. I ended up putting in the grdvwLocationList.SelectedIndex = 0; in to set the selected index on the first index in the list instead of the index of the record that I just deleted. That is where I was having trouble. I thought that the SelectRow() would reselect the index again but I had to reset it back to another index. If there are any questions or comments please feel free. I am still learning and would like all of the advise that I can get.

repositoryitemhyperlinkedit show/hide according to the row data

I am using an XtraGridView control in my winform. Now I added a RepositoryItemHyperLinkEdit to it. But I want to show/hide each link according to the row data.
How can I achieve this?
Thanks for any help..
I tried the next code but it did not work, the cell did not be empty.
("Show link" part is ok, but String.Empty does not work)
private void xgvGrid_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
{
if (e.Column == gcControlField)
{
if (xgvGrid.GetFocusedRowCellValue("ControlField") != null)
{
if (xgvGrid.GetFocusedRowCellValue("ControlField").ToString() == "LINK")
e.DisplayText = "Show link";
else
e.DisplayText = string.Empty;
}
}
}
You can add your checking in the event GridView.CustomColumnDisplayText.
e.g. Each row is bind to a Person instance
private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
{
// gcLink is your column using repositoryitemhyperlinkedit
if (e.Column == gcLink)
{
var person = gridView1.GetRow(e.RowHandle) as Person;
if (person != null)
{
// Logic to show/hide the link based on other field
if (person.FirstName == "John")
e.DisplayText = string.Empty;
else
e.DisplayText = person.Link;
}
}
}

Categories

Resources