I have a datagridview that fills correctly and colors the rows based on the Notify column.
I am using the dataGridView1_CellFormatting
event to color the row.
However when I issue the command to hide the column I lose the color as well.
dataGridView1.Columns["Notify"].Width = 0;
Would like to use the color to save the space in the grid for other columns. Setting the width to 0 ie the second column still shows part of the column.
When I add dataGridView1.Columns["Notify"].Visible = false;
I loose the formatting:
private void PopulateLogs()
{
var logs = logManager.GetLogRecordsByDay(selectedDay);
dataGridView1.DataSource = logs;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;
dataGridView1.AllowUserToResizeRows = false;
dataGridView1.Columns["Id"].Visible = false;
dataGridView1.Columns["Notify"].Visible = false;
dataGridView1.Columns["LogDateTime"].DefaultCellStyle.Format = "HH:mm";
dataGridView1.Columns["LogDateTime"].Width = 20;
dataGridView1.Columns["LogEntry"].Width = 100;
dataGridView1.Columns["Analyst"].Width = 15;
dataGridView1.AllowUserToAddRows = false;
}
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Notify")
{
if (e.Value != null)
{
string stringValue = (string)e.Value;
stringValue = stringValue.ToLower();
if ((stringValue.IndexOf("1") > -1))
{
this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.MistyRose;
}
}
}
}
This is the solution that worked for me. Thanks Jimi
private void gvLogs_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
if (gvLogs["Notify", e.RowIndex].Value.ToString().Equals("1"))
{
this.gvLogs.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.MistyRose;
}
}
In modern programming people tend to separate the data (= model) from the way that this data is displayed (= view).
This way they can change the way that data is displayed without having to change the model. You can unit test the model without needing a form, and you can change the model without having to change the display.
You are displaying a sequence of log items. The color of a particular displayed log item depends on the value of one of the log item properties.
class DislayedLogItem
{
public int Id {get; set;}
public string Notify {get; set;}
public DateTime LogTime {get; set;}
...
}
Apparently there is something about the value that makes your want to change the back color of the row. You didn't tell us what is so special, but you need a method like:
// this displayed log item is special if property Notify contains the character '1'
public bool IsSpecial => this.Notify.Contains('1');
The nice thing of separating this, is that if you later decide that a displayed log item is special because it has a date before the year 2000, this is the only place that needs to change.
Similarly, you want a property for the background:
private Color SpecialColor = Color.MystyRose;
Again: this is designed for change: only one place that has to be changed if you want a different color.
You've probably used the visual studio designer to add the columns. Every Column displays one of the properties that you want to show. Probaby in the constructor:
InitializeComponent();
columnId.DataPropertyName = nameof(DisplayedLogItem.Id);
columnLogTime.DataPropertyName = nameof(DisplayedLogItem.Log)
columnAnalyst.DataPropertyName = nameof(DisplayedLogItem.Analyst);
No column to display Notify. You didn't want to show this column anyway.
But what you do want, is whenever a "special" row is about to be added, you want to give it a special backcolor.
For this you need event DataGridView.RowPrePaint
private void OnRowPrepaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
DataGridViewRow row = e.Row;
DisplayedLogItem logItem = (DisplayedLogItem)row.DataBoundItem;
if (logItem.IsSpecial)
row.BackColor = this.SpecialColor;
}
Maybe you can do this when a row is added: DataGridView.RowsAdded event.
You need a procedure to fetch the Log items that need to be displayed. Out of scope of the question:
public IEnumerable<DisplayedLogItem> FetchLogItemsToDisplay()
{
...
}
The following is enough to display the log
this.dataGridView1.DataSource = this.FetchLogItemsToDisplay().ToList();
This is enough to show the data. However, if you want to be notified when rows are added / removed / updated, you need a BindingList:
private BindingList<DisplayedLogItem> DisplayedLogItems
{
get => (BindingList<DisplayedLogItem>)this.dataGridView1.DataSource;
set => this.dataGridView.DataSource = value;
}
To display, for instance after loading:
void Form_Loaded(object sender, ...
{
this.DisplayedLogItems = new BindingList<DisplayedLogItem>(
this.FetchLogItemsToDisplay().ToList());
}
Now whenever the operator Adds / Removes / Edits a row, this is updated in the DisplayedLogItems. So if the operator indicates that he has finished editing the data, for instance by clicking the Ok button:
void ButtonOk_Clicked(object sender, ...)
{
ICollection<DisplayedLogItem> editedLogItems = this.DisplayedLogItems;
// find out which items are added / removed / changed and process them:
this.ProcessEditedLogItems(editedLogItems);
}
The following might be useful if you need to process selected rows:
DisplayedLogItem CurrentLogItem => (DisplayedLogItem)this.dataGridView1.SelectedRow;
IEnumerable<DisplayedLogItem> SelectedLogItems => this.dataGridView1.SelectedRows
.Cast<DataGridViewRow>()
.Select(row => row.DataBoundItem)
.Cast<DisplayedLogItem>();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.