3

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.

TaW
  • 53,122
  • 8
  • 69
  • 111
ZNackasha
  • 755
  • 2
  • 9
  • 29

1 Answers1

5

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.

Community
  • 1
  • 1
TaW
  • 53,122
  • 8
  • 69
  • 111
  • 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