Formatting columns with multiple types - c#

I have currency text and numeric type values in my datagridview columns. I would like to format the currency value using the below code, but it's not working.
private void gv_EmployeeAdditional_CellLeave(object sender, DataGridViewCellEventArgs e)
{
if (gv_EmployeeAdditional.Rows[e.RowIndex].Cells["EmpDatatype"].Value.ToString() == "Currency")
{
gv_EmployeeAdditional[e.ColumnIndex, e.RowIndex-1].Style.Format = "#,##0.00##";
}
}

Can't test it right now but I think this is what you are looking for, set a break-point and make sure you are getting inside of the if statement then run a few test cases...
if (gv_EmployeeAdditional.Rows[e.RowIndex].Cells["EmpDatatype"].Value.ToString() == "Currency")
{
gv_EmployeeAdditional.Columns[e.ColumnIndex].DefaultCellStyle.Format = "N2";
gv_EmployeeAdditional.Columns[e.ColumnIndex].ValueType = typeof(decimal);
//gv_EmployeeAdditional[e.ColumnIndex, e.RowIndex - 1].Style.Format = "#,##0.00##";
}
Maybe even just try set this line:
gv_EmployeeAdditional[e.ColumnIndex, e.RowIndex - 1].Style.Format = "N2";
Formatting types in C# link here

Related

Extract Date form DataGridView to DateTimePicker

Here when am selecting a row in my datagridview I want the date in my database to show up on the DateTimePicker I have in my applicaiton.
But I am running into an error which is saying me that'String was not recognized as a valid DateTime.'
Since MySQL takes 'yyyy-MM-dd' format I changed my DateTimePicker format to the same.
I tried extracting the value of the DataGridView as a string and found that the format I am getting is "dd-MM-yyyy hh:MM:ss t"
What can I do to resolve it?
private void dtv_dis1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
txt_id.Text = dtv_dis1.SelectedRows[0].Cells[0].Value.ToString();
txt_amt.Text = dtv_dis1.SelectedRows[0].Cells[6].Value.ToString();
txt_remarks.Text = dtv_dis1.SelectedRows[0].Cells[5].Value.ToString();
//Error with date
String date = dtv_dis1.SelectedRows[0].Cells[1].Value.ToString();
dtp_date.Value = DateTime.ParseExact(date, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
//textBox1.Text = dtv_dis1.SelectedRows[0].Cells[1].Value.ToString();
tot = dtv_dis1.SelectedRows[0].Cells[2].Value.ToString();
mop = dtv_dis1.SelectedRows[0].Cells[4].Value.ToString();
cur = dtv_dis1.SelectedRows[0].Cells[3].Value.ToString();
if (tot == "Domestic")
{
rb_dom.Checked = true;
}
else
{
rb_in.Checked = true;
}
if (mop == "Cash")
{
rb_csh.Checked = true;
}
else if (mop == "Credit Card")
{
rb_cc.Checked = true;
}
else
{
rb_nb.Checked = true;
}
if (cur == "Doller")
{
rb_doller.Checked = true;
}
else if (cur == "Euro")
{
rb_euro.Checked = true;
}
else
{
rb_Rupees.Checked = true;
}
}
If the grids data source is a DataTable and the “Date” column’s type is a type of DateTime, then, it should be unnecessary to “parse” the date…
Simply grab the "data" row from the data source, then grab the DateTime value directly from the cell… something like…
if (dtv_dis1.CurrentRow != null) {
DataRowView drv = (DataRowView)dtv_dis1.CurrentRow.DataBoundItem;
dtp_date.Value = (DateTime)drv["Date"];
}
As commented, if the column type is a string type… then I suggest you change it to a type of DateTime.
A recommendation, load database data into a DataTable or List<T> then using a BindingSource assign the DataTable or List<T>.
Add a DataBinding to the DataTimePicker, set Format property to Custom, set CustomFormat to yyyy-MM-dd.
If using a List<T> and want to reflect changes in the DataGridView, implement INotifyPropertyChanged interface in the class representing T.
There is quirk with a List<T> and BindingSource to refect changes to the source so subscribe to ValueChanged event of the DateTimePicker and set the DateTime column value.
The screenshot below has the Date shown in the DataGridView with a custom DataGridView column where the birth date is synchronous with the DateTimePicker.
In general, typically one does not want to access data in a DataGridView through cells but instead as indicated above through the DataSource in the above a BindingSource.
To get at the current row in the DataGridView via a BindingSource, first assert the .Current property is not null, if not null case Current to the type eg. DataRow for a DataTable, a class type for a list.
In the following the DataSource is a List using Person1 class to get the current row information from a DataGridView shown above.
private void CurrentPersonButton_Click(object sender, EventArgs e)
{
if (_bindingSource is null || _bindingSource.Current is null) return;
var current = (Person1)_bindingSource.Current;
MessageBox.Show(
$"{current.FirstName} {current.LastName}\n" +
$"{current.BirthDate.Value:yyyy-MM-dd}");
}

Show 0/1 as yes/no in DevExpress XtraGrid?

I had this code for a regular DataGridView, and I'm having trouble getting the same effect on the XtraGrid:
private void RosterGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex == 7 && e.Value is long)
{
e.Value = (long)e.Value == 0 ? "No" : "Yes";
}
}
The issue is I am using SQLite and it doesn't have any true boolean data type, or else this would be easy. The column is set up in the DB to only accept 0 and 1, kind of a makeshift boolean.
With DevExpress you can set up the specific column to use the RepositoryItemCheckEdit:
// Assign a repository item to a column
RepositoryItemCheckEdit checkEdit = new RepositoryItemCheckEdit();
gridControl.RepositoryItems.Add(checkEdit);
gridView.Columns["Mark"].ColumnEdit = checkEdit;
After that, you can set up the ValueChecked, ValueUnchecked and ValueGrayed properties specify the values that correspond to the editor's checked, unchecked and indeterminate state, respectively. The default values of the ValueChecked, ValueUnchecked and ValueGrayed properties are true, false and null, respectively. You can assign custom values to these properties as your logic requires:
checkEdit.ValueChecked = (long)1;
checkEdit.ValueUnchecked = (long)0;
With this approach, you can avoid any value conversion operations when displaying and editing values in GridView.
Another possibility is to use the CustomColumnDisplayText event on the gridView
private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
{
if (e.Column = <yourColumn>)
{
e.DisplayText = (long) e.Value == 1 ? "Yes" : "No";
}
}

DataGridView using DataSourceNullValue: enter either nothing, or the nullValue

I have a DataGridView, which is databound to a DataSource.
One of the columns of the DataGridView is bound to a property of type decimal? (nullable decimal). This column is editable.
If the value of the property is null, then the underlying object should use a default value retrieved from another object.
Operators seem to be confused if this column shows nothing. Hence I want to show the string "<default>", indicating that the default value is used.
When editing this value, I'd like to give the operator the freedom to either leave an empty field, or enter something like "<default>", if he wants to indicate that the default value should be used. So:
operator enters the string "<default>": property gets value (decimal?)null
operator enters empty string: property gets value (decimal?)null
operator enters any other value: validate if it is a decimal, and use this value.
What I tried (that's always the first that is asked for :-)
public MyForm() // constructor
{
this.InitializeComponent();
// initialize datagridview (part of this could have been done in designer)
this.dataGridView1.AutoGenerateColumns = false;
this.dataGridView1.DataSource = ...;
var valueCellStyle = this.columnNonDefault.DefaultCellStyle;
valueCellStyle.DataSourceNullValue = (decimal?)null;
valueCellStyle.NullValue = "<default>";
}
The validation event handler is as follows:
private void OnCellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if (e.CollumnIndex == this.columnNonDefaultValue.Index)
{ // validating the non-default value
// allow either empty string, or cellStyle.NullValue or decimal
string proposedValue = (string)e.FormattedValue;
// check if empty:
if (String.IsNullOrEmpty(proposedValue)
{ // accept empty:
e.Cancel = false;
}
else
{ // check if "<default>"
var cellToValidate = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
DataGridViewCellStyle style = cellToValidate.InheritedStyle;
if (!style.IsNullValueDefault
&& String.Equals(proposedValue, style.NullValue.ToString()))
{ // accept default value:
e.Cancel = false;
}
else if (this.IsProperDecimal(proposedValue)
{ // accept decimal value
e.Cancel = false;
}
else
{ // all others: don't accept
this.ShowInvalidData(...)
e.Cancel = true;
}
}
}
}
This works fine if people enter a proper decimal value, or "<default>". If an empty string is entered, then as soon as the data is pushed to the databound item I get a string format exception.
I had expected I should handle the CellValuePushed event, with VirtualMode = true. Alas, because the grid view is databound this event is not called, not even if a proper value is pushed
So what can I use to accept both "" and empty string as (decimal?) null?
As an option you can use CellParsing and CellFormatting events to handle conversion between entered value to data source value and displaying the data source value in a suitable format.
CellParsing: To convert entered text to the suitable data source value.
Here you want to convert entered value to your default value based on some criteria (when the entered text is empty or "" or equals to the default value).
CellFormatting: To convert data source value to suitable text to show in cell.
Here you want to convert your default value to some text like <Default>.
Here is an example:
public class Test
{
public int X { get; set; }
public decimal? Y { get; set; }
}
BindingList<Test> list;
decimal? defaultValue = 100; //Some default value
string defaultFormattedValue = "<Default>"; //Some default formatted value
private void Form1_Load(object sender, EventArgs e)
{
list = new BindingList<Test>(new List<Test>());
this.dataGridView1.DataSource = list;
}
private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
{
var value = string.Format("{0}", e.Value);
if (value == string.Empty || value == "\"\"")
e.Value = defaultValue;
e.ParsingApplied = true;
}
private void dataGridView1_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e)
{
if (e.Value is int? && (int?)e.Value == defaultValue)
e.Value = defaultFormattedValue;
}

Datagrid cell formatting not retain after user edit?

i have a datagrid with the following cell formatting
datagrid.rows[0].cells[0].Value =1;
datagrid.rows[0].cells[0].Style.Format ="#k";
this works fine and the output will be 1k, however when the user edit the cell value example to 2 then cell formatting will not take effect?
question is how can i retain the cell formatting after user edit?
thanks
I guess you are not working with an underlying datasource. You are inserting DataGridViewRows manually into the DataGridView.
If you were using a datasource, if the column datatype was numeric, the styling will work in both edit and readonly modes.
In your case, you need to handle the CellFormatting event of the DataGridView and set the format of your cell there:
void dataGridView1_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex == 0)
{
// if the underlying type is int
int value;
if(e.Value != null && int.TryParse(e.Value.ToString(), out value))
{
e.Value = value.ToString("#k");
/*** OR ***
e.Value = value;
e.CellStyle.Format = "#k";
*/
}
}
}

Handle empty cells in DataGridView

I want to write a condition for when some cells of DataGridView are null or empty.
For example if cells[1] isn't null or empty , a method must be run and ...
I wrote it in some way , but some of them didn't work, and one of them work but its not good solution for my problem.As you now ,empty and null are different in DataGridView.
Additionally , My DataGridView has not been bound to database.
How can i do that in best way?
Regards.
DataGridViewCell object has "Value" method which returns callvalue as object, That value you can convert to string then check this string against null or empty.
string val = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value as string;
if(string.isNullorEmpty(val) ==false)
{
// your method run.
}
Cell value is a Object. Empty cell Value is null.
DataTable / DataView uses DbNull.Value when Empty.
Strings with Length = 0 are String.Empty
You need verify three options.
if your columns and row layout is fixed then you may call out your function in the cell validating event of the datagrid
void dataGridView2_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
e.Cancel = false;
if (e.RowIndex == 1 && e.ColumnIndex == 0)
{
if(string.IsNullorEmpty(e.FormattedValue.ToString())
// method call
}
}
//just replace from Value to FormattedValue like that
string val = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].FormattedValue as string;
if(string.isNullorEmpty(val))
{
// cell is empty
}
else
{
// cell is not empty
}

Categories

Resources