I am working on a project where cells in a DataGridView get highlighted. And I was wondering if I can make marks on the scrollbar itself to indicate where those highlights are. Any ideas may be helpful.
1 Answers
The Yes, the No and a Maybe
The Yes: According to this it is possible. However, this is a links only answer; not sure where that will lead..
The No: According to Cody Gray's excellent analysis in his answer to this post painting on a scrollbar is not possible.
But Maybe a workaround will solve your problem..?
Here is the idea:
You add a thin Panel
that either overlays the scrollbar or attaches itself to its left. I should be really thin and go over the height of the scrolbar; it gets redrawn with the usual Paint events.
You keep a List of Rows, for which marks should be shown. This List is re-created or maintained upon:
- adding & removing
Rows
- changing your target row
- possibly when sorting or Filtering
Here is a little code, just a quick proof of concept. For a more robust solution I guess I would create a decorator class to which the DataGridView
would register.
Now, when you move the lift towards the marks you will find the target rows. A lot of room for improvement, but a start imo..
You have to change the isRowMarked()
function to your needs. I have chosen to test the first Cell's Backcolor..
You can also easily use different colors for different marks; maybe by copying them from the marked row/cell.
public Form1()
{
InitializeComponent();
dataGridView1.Controls.Add(indicatorPanel);
indicatorPanel.Width = 6;
indicatorPanel.Height = dataGridView1.ClientSize.Height - 39;
indicatorPanel.Top = 20;
indicatorPanel.Left = dataGridView1.ClientSize.Width - 21;
indicatorPanel.Paint += indicatorPanel_Paint;
dataGridView1.Paint += dataGridView1_Paint;
}
Panel indicatorPanel = new Panel();
List<DataGridViewRow> tgtRows = new List<DataGridViewRow>();
void dataGridView1_Paint(object sender, PaintEventArgs e)
{
indicatorPanel.Invalidate();
}
void indicatorPanel_Paint(object sender, PaintEventArgs e)
{ // check if there is a HScrollbar
int hs = ((dataGridView1.ScrollBars & ScrollBars.Vertical) != ScrollBars.None ? 20 : 0);
e.Graphics.FillRectangle(Brushes.Silver, indicatorPanel.ClientRectangle);
foreach (DataGridViewRow tRow in tgtRows)
{
int h = (int)(1f * (indicatorPanel.Height - 20 + hs) * tRow.Index
/ dataGridView1.Rows.Count);
e.Graphics.FillRectangle(Brushes.Red, 0, h-3, 6, 4);
}
}
bool isRowMarked(DataGridViewRow row)
{
return row.Cells[0].Style.BackColor == Color.Red; // <<-- change!
}
// call in: dataGridView1_RowsRemoved, dataGridView1_RowsAdded
// also whenever you set or change markings and after sorting or a filtering
void findMarkers()
{
tgtRows.Clear();
foreach (DataGridViewRow row in dataGridView1.Rows)
if (isRowMarked(row) ) tgtRows.Add(row);
indicatorPanel.Invalidate();
}
Note I have removed the first answer as the original requirements talk of 'marks' not just 'a few marks'. The second version seems a lot nicer to me, now.
-
Please don't forget to mention that using [relevant technology from this century](http://msdn.microsoft.com/en-us/library/ms754130(v=vs.110).aspx) (as opposed to archaic winforms from the stone age) this is perfectly doable using proper DataBinding and does not involve any of these horrible procedural code hacks ;) – Federico Berasategui Jun 25 '14 at 19:25
-
given a fixed row size (height) in the DataGrid (without which this gets more complicated), it's just a matter of `var margin = new Thickness(0, rowIndex * rowHeight,0,0);` in an `IValueConverter`. – Federico Berasategui Jun 25 '14 at 19:32
-
very similar to how I'm vertically positioning the Bookings in [this answer](http://stackoverflow.com/a/19049586/643085) in the `TimeRangeToVerticalMarginConverter` class. – Federico Berasategui Jun 25 '14 at 19:38
-
Don't guess. Do it! Your answer lets me doubt that you have understood the question, btw. Using the rowHeight should not be part of the equation. – TaW Jun 25 '14 at 19:41
-
[here](https://github.com/High-Core/WPFSamples/tree/master/DataGridScrollBarHighlight). (Actually 4) Lines of C# code for a full solution which includes toggling highlights on each row via a CheckBox ;) – Federico Berasategui Jun 25 '14 at 20:29