2

I have DB table that consist of two columns(Price(int) and Currency(nverchar)) The cells of Price column is formatted depending on what currency is in the second column(cell). For example: In DB

PRICE CURRENCY
12000 USD
20000 EUR

The user should see a formatted view in the DataGrid. For example:

PRICE CURRENCY
$12,000.00 USD
€20,000.00 EUR

How can I do this?

I ​need to do this in Form_load or by a funk that will be called there. I mean: I need to check for all rows and if row[0].cells2 or row[1].cells[2]... contains 'usd' then i need change format the first cell of this row

Is that possible?

DrRed_LZ
  • 25
  • 5
  • 1
    Does this answer your question? [Conditional DataGridView Formatting](https://stackoverflow.com/questions/4067068/conditional-datagridview-formatting) – Serg Jun 15 '21 at 18:56
  • Using the DataGrid's CellFormatting event you could check the value of the Currency column and apply your formatting from there. [DataGrid Cell Formatting](https://stackoverflow.com/questions/2117210/how-to-custom-format-data-in-datagridview-during-databinding) ... [DataGrid Customize Data Formatting](https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-customize-data-formatting-in-the-windows-forms-datagridview-control?view=netframeworkdesktop-4.8&redirectedfrom=MSDN) – quaabaam Jun 15 '21 at 18:58
  • @JohnG user interface displayed like this https://imgur.com/a/Il7dfyq Textbox cell – DrRed_LZ Jun 15 '21 at 19:43

1 Answers1

1

If the grid’s data source is to be set, then… maybe… you could throw this into the grids CellFormating event. However, it should be clear that in the long run, the cell will get formatted many-many more times than necessary. I think we can do better. We can not “format” the cell until either 1) the user changes the Currency cell, or 2) new data is loaded into the grid.

The first part is trivial… wire up the grids CellValueChanged event. If the cell value that changed is a Currency cell… then, check the "new" value and format the Price cell accordingly.

This works when the user changes a Currency cells value, however, it does not work when the data is loaded. Therefore, a simple loop through the grid’s rows should solve that issue. Since we need to set the Price cells format in two different places, I suggest creating a method that takes a DataGridViewRow and formats the “Price” cell for the given row. It may look something like…

private void FormatAmountCell(DataGridViewRow row) {
  if (!row.IsNewRow && row.Cells["Currency"].Value != null) {
    string currency = row.Cells["Currency"].Value.ToString();
    DataGridViewCell cellToFormat = row.Cells["Price"];
    switch (currency) {
      case "EUR":
        cellToFormat.Style.FormatProvider = CultureInfo.GetCultureInfo("en-GB");
        break;
      default:
        cellToFormat.Style.FormatProvider = CultureInfo.GetCultureInfo("en-US");
        break;
    }
  }
}

With this helper we can then use it in the grids wired up CellValueChanged event.

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
  FormatAmountCell(dataGridView1.Rows[e.RowIndex]);
}

In addition, a small method that loops through the grids rows and sets each “Price” cells format. We will call this after the data is loaded into the grid.

private void FormatAmountCellForAllRows() {
  foreach (DataGridViewRow row in dataGridView1.Rows) {
    FormatAmountCell(row);
  }
} 

Putting all this together for testing may look something like…

DataTable GridTable;

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
  GridTable = GetData();
  dataGridView1.DataSource = GridTable;
  dataGridView1.Columns["Price"].DefaultCellStyle.Format = "c";
  FormatAmountCellForAllRows();
}

private DataTable GetData() {
  DataTable dt = new DataTable();
  dt.Columns.Add("Price", typeof(decimal));
  dt.Columns.Add("Currency", typeof(string));
  Random rand = new Random();
  for (int i = 0; i < 10; i++) {
    dt.Rows.Add(rand.NextDouble() * 100, (rand.Next(2) == 0 ? "USD" : "EUR"));
  }
  return dt;
}

Now you can sleep well knowing the formatting is never done unnecessarily.

JohnG
  • 9,259
  • 2
  • 20
  • 29