I have a DataGridView in a Windows Form, it has 2 columns, the last column is going to contain the name of a packet, the point is that this name never has to be duplicated.
I tried with this code using CellValidating event
string value = Convert.ToString(dgvTiendas.Rows[e.RowIndex].Cells[e.ColumnIndex].Value);
int cellIndex = e.RowIndex;
if(cellIndex == 1)
{
foreach (DataGridViewRow rw in dgvTiendas.Rows)
{
if (cellIndex == rw.Index)
{
return;
}
else
{
string valorRow = Convert.ToString(rw.Cells["ContenedorCodigoBarras"].Value);
if (value == valorRow)
{
MessageBox.Show("The container is already used");
dgvTiendas.Rows[e.RowIndex].ErrorText = "Contenedor ya utilizado";
e.Cancel = true;
}
else
{
e.Cancel = false;
}
}
}
}
When i run the application and i write a container's name, it is validated but it seems that validate the current cell because the "Error text" appears on the RowHeader.
Please help i have some weeks with this.
You are having this problem because you are setting the error text of the row with this code.
dgvTiendas.Rows[e.RowIndex].ErrorText = "Contenedor ya utilizado";
You need to set error text of the cell
dgvTiendas[e.ColumnIndex, e.RowIndex].ErrorText = "an error occured";
Related
To be honest, I have no idea why the variable is being set to null. The object is set, then once I go through the DisplayPromptAsync, it sets the object to null.
I'm not sure what to try as I've never come across this issue.
Here's a gif of the issue. Once I enter into the field and press submit, an object gets reset.
async void OpenContainerItem()
{
// Pause the timer
blnTimerActive = false;
if (SelectedItem != null)
{
if (SelectedItem.intQuanChecked == SelectedItem.intQuantity)
return;
try
{
int intQuantity = 0;
// Ask for quantity
string result = await Application.Current.MainPage.DisplayPromptAsync("Quantity",
"How many " + SelectedItem.objItem.strItemName + " did you count?",
"Okay", cancel: "Cancel",
placeholder: "Quantity",
keyboard: Keyboard.Numeric);
// Check if it's been cancelled
if (result != null)
{
// check if theres nothing entered
if (result == "")
{
// Why tho?
await Application.Current.MainPage.DisplayAlert("Error", "Please enter a quantity.", "Okay");
}
else
{
intQuantity = int.Parse(result);
if (0 > ((SelectedItem.intQuantity - SelectedItem.intQuanChecked) - intQuantity))
{
Application.Current.MainPage.DisplayAlert("Error", "Thats too many items!", "Okay");
Reload();
blnTimerActive = true;
return;
}
modDatabaseUtilities.ContainerItemsPreCheck(SelectedItem.intContainerItemID, intQuantity, strCurrentUser);
Reload();
}
}
}
catch(Exception ex)
{
Application.Current.MainPage.DisplayAlert("Error", "Couldn't process this change. Please try again.", "Okay");
}
}
#ScottUphus - Is SelectedItem bound to a ListView? (If it is bound to anything, you should add that xaml in your question.) If so, then its a common problem: xamarin sets it back to null when the display layout is refreshed. (I'm not sure the exact "rule" for when it happens. In your case, I suspect the modal interaction causes this.)
This is how I solve such issues:
public MyItemType ValidSelectedItem { get; private set; }
public MyItemType SelectedItem
{
get => _SelectedItem;
set {
... your current setter code here ...
// Remember most recent non-null value.
if (value != null)
ValidSelectedItem = value;
}
}
private MyItemType _SelectedItem;
ValidSelectedItem remembers the non-null item, even if xamarin resets the selection back to null. Use it in code that needs that value.
Is there a difference in using "Okay" or "OK" in DisplayPromptAsync ? try to change it in your code.
this is default Page.DisplayPromptAsync Method:
public System.Threading.Tasks.Task<string> DisplayPromptAsync
(
string title,
string message,
string accept = "OK",
string cancel = "Cancel",
string placeholder = default,
int maxLength = -1,
Xamarin.Forms.Keyboard keyboard = default,
string initialValue = ""
);
In my C# windows forms program I would like to update the TextBoxes according to the RowHeader clicked on in the DataGridView:
if (e.RowIndex != -1 || e.ColumnIndex != -1)
{
fnameBox.Text = dgvPatient.Rows[rowIndex].Cells[0].Value.ToString();
mnameBox.Text = dgvPatient.Rows[rowIndex].Cells[1].Value.ToString();
lnameBox.Text = dgvPatient.Rows[rowIndex].Cells[2].Value.ToString();
mobnumBox.Text = dgvPatient.Rows[rowIndex].Cells[3].Value.ToString();
emailBox.Text = dgvPatient.Rows[rowIndex].Cells[4].Value.ToString();
bdate.Value = Convert.ToDateTime(dgvPatient.Rows[rowIndex].Cells[5].Value.ToString());
medHistBox.Text = dgvPatient.Rows[rowIndex].Cells[6].Value.ToString();
}
So, my problem is that the DataGridView shows an empty row at the end, so when I click on this header, the `Convert.ToDateTime statement throws an error and bugs the app. I tried checking if the result of conversion is null value... the code above is latest trial and it also failed.
How do I remove the error of clicking on the last RowHeader?
You should check null before using value and add try catch to your code. Should check cell value not null for all cells before ToString() dgvPatient.Rows[rowIndex].Cells[0].Value != null and use DateTime.TryParse instead of Convert.ToDateTime
try
{
fnameBox.Text = dgvPatient.Rows[rowIndex].Cells[0].Value != null ? dgvPatient.Rows[rowIndex].Cells[0].Value.ToString() : string.Empty;
mnameBox.Text = dgvPatient.Rows[rowIndex].Cells[1].Value.ToString();
lnameBox.Text = dgvPatient.Rows[rowIndex].Cells[2].Value.ToString();
mobnumBox.Text = dgvPatient.Rows[rowIndex].Cells[3].Value.ToString();
emailBox.Text = dgvPatient.Rows[rowIndex].Cells[4].Value.ToString();
DateTime date;
DateTime.TryParse(dgvPatient.Rows[rowIndex].Cells[5].Value.ToString(), out date);
//bdate.Value = Convert.ToDateTime(dgvPatient.Rows[rowIndex].Cells[5].Value.ToString());
medHistBox.Text = dgvPatient.Rows[rowIndex].Cells[6].Value.ToString();
}
catch (Exception e)
{
}
public Login ClickGetStatus()
{
//IWebElement btnGetStatus = driver.FindElement(By.XPath("//*[contains(#id,'GetStatus')]"));
do
{
buttonName_GetStatus[0] = "abc";
Thread.Sleep(3000);
bool is_displayed =
wrapper.IsElementDisplayed(
driver.FindElement(By.XPath("//*[contains(#id,'GetStatus')]")));
//bool IsElementDisplayed = driver.FindElement(By.XPath("//*[contains(#id,'GetStatus')]")).Displayed;
if (is_displayed)
{
//wrapper.Click(btnExecute);
string getnameofbutton1 =
driver.FindElement(
By.XPath("//*[contains(#id,'GetStatus')]")).GetAttribute("id");
Console.WriteLine("Name of the button is : " + getnameofbutton1);
buttonName_GetStatus = getnameofbutton1.Split('_');
driver.FindElement(
By.XPath("//*[contains(#id,'GetStatus')]")).Click();
}
else
{
Console.WriteLine("Element is not displayed");
}
}
while (buttonName_GetStatus[0] == "GetStatus");
return this;
}
Below is the Logic for the above code
Checks for the button called Get Status
if it finds the button Get Status then clicks on it
i have used contains in the xpath as the element id for that button changes dynamically.
The above code runs fine and clicks on the Get Status button but doesn't come out from the loop when the name of the Get Status button changes to View Result and still searches for Get Status button
If the expected ID of the button after being updated is "ViewResult", then you can update your condition to use that.
while (buttonName_GetStatus[0] != "ViewResult");
This will keep looping round whilst the button does not equal "ViewResult".
Is this the behavior you're trying to achieve?
public Login ClickGetStatus()
{
//IWebElement btnGetStatus = driver.FindElement(By.XPath("//*
[contains(#id,'GetStatus')]"));
do
{
buttonName_GetStatus[0] = "abc";
Thread.Sleep(3000);
var elements = driver.FindElements(By.XPath("//*[contains(#id,'GetStatus')]"));
var is_displayed = elements.Count > 0;
//bool IsElementDisplayed = driver.FindElement(By.XPath("//*[contains(#id,'GetStatus')]")).Displayed;
if (is_displayed)
{
//wrapper.Click(btnExecute);
string getnameofbutton1 =
driver.FindElement(
By.XPath("//*[contains(#id,'GetStatus')]")).GetAttribute("id");
Console.WriteLine("Name of the button is : " + getnameofbutton1);
buttonName_GetStatus = getnameofbutton1.Split('_');
driver.FindElement(
By.XPath("//*[contains(#id,'GetStatus')]")).Click();
}
else
{
Console.WriteLine("Element is not displayed");
}
}
while (buttonName_GetStatus[0] != "ViewResult");
return this;
}
I think problem might be here, especially when you check if isDisplayed == true then this line buttonName_GetStatus = getnameofbutton1.Split('_'); overrides array so that infinitive loop appeared.
I have a combobox with two items. I also have a button that opens a new form when one of these items are selected. However if none of the items are selected there is an exception(nullpointer). I have tried (to no avail) to catch this exception and show a mbox that prompts the user to choose one of the items.
Here is the code for the button click even:
if (labelGrid.Text == "Member" && cbTable.SelectedItem.ToString().Equals("Workout"))
{
string name;
string ss;
foreach (DataGridViewRow item in this.dtGrid1.SelectedRows)
{
ss = dtGrid1.CurrentCell.Value.ToString();
name = dtGrid1.SelectedCells[1].Value.ToString();
BookMemberWorkout bmw = new BookMemberWorkout(ss, name);
bmw.Label2.Text = ss;
bmw.Label1.Text = name;
bmw.ShowDialog();
}
}
You are not supposed to use exceptions for flow control in non-exceptional cases. The case that the user didn't select anything is surely not exceptional.
The correct approach would be a simple null check:
if(cbTable.SelectedItem == null)
{
// Show message box
}
else
{
// Your current code
}
Why your exception handling code isn't working is impossible to answer, because you didn't include it in your question.
I think the problem is in the line:
ss = dtGrid1.CurrentCell.Value.ToString();
You can't be sure the value is not null, so you should check it before calling the .ToString().
Instead of using a message box you could use a RequiredValidator to perform javascript validation, avoiding a useless postback.
From performance and readability point-of-view, I'd recommend checking for selected value in the combo box rather than catching an exception, like this
if(cbTable.SelectedItem == null)
{
MessageBox.Show("Please select a value in the combo box.");
return;
}
if (labelGrid.Text == "Member" && cbTable.SelectedItem.ToString().Equals("Workout"))
{
string name;
string ss;
foreach (DataGridViewRow item in this.dtGrid1.SelectedRows)
{
ss = dtGrid1.CurrentCell.Value.ToString();
name = dtGrid1.SelectedCells[1].Value.ToString();
BookMemberWorkout bmw = new BookMemberWorkout(ss, name);
bmw.Label2.Text = ss;
bmw.Label1.Text = name;
bmw.ShowDialog();
}
}
However to answer your specific query, you can catch NullReferenceException like this:
try{
if (labelGrid.Text == "Member" && cbTable.SelectedItem.ToString().Equals("Workout"))
{
string name;
string ss;
foreach (DataGridViewRow item in this.dtGrid1.SelectedRows)
{
ss = dtGrid1.CurrentCell.Value.ToString();
name = dtGrid1.SelectedCells[1].Value.ToString();
BookMemberWorkout bmw = new BookMemberWorkout(ss, name);
bmw.Label2.Text = ss;
bmw.Label1.Text = name;
bmw.ShowDialog();
}
}
}
catch(NullReferenceException ex)
{
MessageBox.Show("Please select a value in the combo box.");
}
i'm searching a way to make an cell an mandatory cell on a new row.
The row consists of 7 cells. The Problem i have is, that if User enters the new row,
he can skip the very important first cell which have to contain a required number. I want that
if user enters the new row that he has to enter first the required cell in that row, before he can add more informations to the second cell and so on. I've tried row validating and checked for DBNull and so on, but nothing works. The best solution would be, that if an new row is entered, the first cell jumps to edit mode. If number is entered, the following cells can be edited, else not. If user cancels adding, the current row isn't added.
Thx for any kind of suggestions and info!
I've found a simple solution by myself. Just check in CellBeginEdit if the first cell has been filled on the new row - else other cells can not be edited and so no new row is been added.
May someone else can need it too. Thank you very much for your help!
private void dgvUsers_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (e.ColumnIndex != 0)
{
if ((e.RowIndex == dgvUsers.NewRowIndex) && (dgvUsers[0, e.RowIndex].Value == null))
{
e.Cancel = true;
}
}
}
Based on what you have described you could use the UserAddedRow event to grab the event and verify that the new row is populated correctly.
You can grab the data in a DataGridViewRowCollection through the Rows Property
I recently had this same issue. I have a DGV in the middle of the a Windows Form that takes Emergency Contact (EC) information. It allows users to enter multiple ECs. The Name, Phone, and Email of each EC must be validated on each row at the time of entry.
I did this:
private void CheckECName(DataGridViewCellValidatingEventArgs newValue)
{
StringBuilder _errMsg = new StringBuilder();
string _cellMsg = "";
string _eCon_Name = "";
DataGridViewCell cell = this.dgEmergencyContact.Rows[newValue.RowIndex].Cells[newValue.ColumnIndex];
if (!String.IsNullOrEmpty(newValue.FormattedValue.ToString()))
{
_eCon_Name = newValue.FormattedValue.ToString();
if (!((_eCon_Name.Trim()).Length == 0))
{
// Match the regular expression pattern against a text string.
// Only alphabetic and space characters
//Match m = r.Match(wholeName);
//if (!m.Success)
if (TestInput.IsFullName(_eCon_Name))
{
string _cellLabel = "Emergency Conact Name";
_cellMsg = "Emergency Contact name";
NotifyUserAndContinue(_cellLabel, _cellMsg, newValue);
return;
}
else
{
_cellMsg = "Emergency Contact name";
_errMsg.Append("The Emergency Contact Name: " + _eCon_Name + " is entered incorrectly.");
_errMsg.AppendLine("Acceptable format: First Last");
_errMsg.AppendLine("\n\tFirst MI Last");
_errMsg.AppendLine("\n\tFirst Middle Last");
_errMsg.AppendLine("\nNo commas or periods, please.");
NotifyUserAndForceRedo(_cellMsg, _errMsg.ToString(), newValue);
return;
}
}
}
}
private void CheckECEmail(DataGridViewCellValidatingEventArgs newValue)
{
StringBuilder _errMsg = new StringBuilder();
string _cellMsg = "";
string techEmail = newValue.FormattedValue.ToString().Trim();
DataGridViewCell cell = this.dgEmergencyContact.Rows[newValue.RowIndex].Cells[newValue.ColumnIndex];
if (!(techEmail.Length == 0))
{
// Send the contents of the Personal Email to the tester class
if (TestInput.IsEmail(techEmail))
{
string _cellLabel = "Emergency Conact Email";
_cellMsg = "Emergency Contact email address";
NotifyUserAndContinue(_cellLabel, _cellMsg, newValue);
return;
}
else
{
_cellMsg = "Emergency Contact email address";
_errMsg.Append("An invalid email address has been entered.");
_errMsg.AppendLine("Format email#server.type (jim#place.com)");
NotifyUserAndForceRedo(_cellMsg, _errMsg.ToString(), newValue);
return;
}
}
}
private void CheckECPhone(DataGridViewCellValidatingEventArgs newValue)
{
StringBuilder _errMsg = new StringBuilder();
string _cellMsg = "";
string techPhone = newValue.FormattedValue.ToString().Trim();
DataGridViewCell cell = this.dgEmergencyContact.Rows[newValue.RowIndex].Cells[newValue.ColumnIndex];
if (!(techPhone.Length == 0))
{
// Send the contents of the Personal Phone to the tester class
if (TestInput.IsPhone(techPhone))
{
string _cellLabel = "Emergency Conact Phone";
_cellMsg = "Emergency Contact phone number";
NotifyUserAndContinue(_cellLabel, _cellMsg, newValue);
return;
}
else
{
_cellMsg = "Emergency Contact phone number";
_errMsg.Append("An invalid phone number has been entered.");
_errMsg.AppendLine("Acceptable formats: 8606782345");
_errMsg.AppendLine("\t860-678-2345");
_errMsg.AppendLine("\t(860) 678-2345");
_errMsg.AppendLine("\t(860) 678 - 2345");
NotifyUserAndForceRedo(_cellMsg, _errMsg.ToString(), newValue);
return;
}
}
}
private void NotifyUserAndForceRedo(string cellMessage, string errorMessage, DataGridViewCellValidatingEventArgs newValue)
{
DataGridViewCell cell = this.dgEmergencyContact.Rows[newValue.RowIndex].Cells[newValue.ColumnIndex];
MessageBox.Show(errorMessage);
dgEmergencyContact.Rows[cell.RowIndex].ErrorText = String.Format("{0} is entered incorrectly", cellMessage);
cell.ErrorText = String.Format("{0} is entered incorrectly", cellMessage);
try
{
dgEmergencyContact.EditingControl.BackColor = Color.OrangeRed;
}
catch (Exception)
{
}
newValue.Cancel = true;
}
private void NotifyUserAndContinue(string cellLabel, string cellMessage, DataGridViewCellValidatingEventArgs newValue)
{
DataGridViewCell cell = this.dgEmergencyContact.Rows[newValue.RowIndex].Cells[newValue.ColumnIndex];
string _goodMsg = String.Format("A valid {0} has been entered.", cellMessage);
AutoClosingMessageBox.Show(cellMessage, cellLabel, 2500);
cell.Style.BackColor = Color.White;
cell.ErrorText = "";
dgEmergencyContact.Rows[cell.RowIndex].ErrorText = "";
}
This validates each cell as the user tabs or enters. I have code on the back doing regedit checks against what I consider a valid name, phone number, and email, and they return bool results.
Hope this helps, someone.