Как выделить поиск арабского c текста в DataGridView? - PullRequest
1 голос
/ 02 апреля 2020

Я хочу выделить данный текст поиска в DataGridView, но данные на арабском c. Я пробовал событие CellPainting, чтобы найти границы текста поиска и нарисовать FillRectangle, но я не смог точно получить границы текста поиска.

UI

Следующий код был тот, который я использовал:

private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    // High light and searching apply over selective fields of grid.  
    if (e.RowIndex > -1 && e.ColumnIndex > -1 && dgv.Columns[e.ColumnIndex].Name != "Id")
    {
        // Check data for search  
        if (!String.IsNullOrWhiteSpace(txtSearch.Text.Trim()))
        {
            String gridCellValue = e.Value.ToString();
            // check the index of search text into grid cell.  
            int startIndexInCellValue = gridCellValue.IndexOf(txtSearch.Text.Trim());
            // IF search text is exists inside grid cell then startIndexInCellValue value will be greater then 0 or equal to 0  
            if (startIndexInCellValue >= 0)
            {
                e.Handled = true;
                e.PaintBackground(e.CellBounds, true);
                //the highlite rectangle  
                Rectangle hl_rect = new Rectangle();
                hl_rect.Y = e.CellBounds.Y + 2;
                hl_rect.Height = e.CellBounds.Height - 5;
                //find the size of the text before the search word in grid cell data.  
                String sBeforeSearchword = gridCellValue.Substring(0, startIndexInCellValue);
                //size of the search word in the grid cell data  
                String sSearchWord = gridCellValue.Substring(startIndexInCellValue, txtSearch.Text.Trim().Length);
                Size s1 = TextRenderer.MeasureText(e.Graphics, sBeforeSearchword, e.CellStyle.Font, e.CellBounds.Size);
                Size s2 = TextRenderer.MeasureText(e.Graphics, sSearchWord, e.CellStyle.Font, e.CellBounds.Size);
                if (s1.Width > 5)
                {
                    hl_rect.X = e.CellBounds.Right + s1.Width - e.CellBounds.X - e.CellBounds.Left;
                    hl_rect.Width = s2.Width - 6;
                }
                else
                {
                    hl_rect.X = e.CellBounds.X + 2;
                    hl_rect.Width = s2.Width - 6;
                }
                //color for showing highlighted text in grid cell  
                SolidBrush hl_brush;
                hl_brush = new SolidBrush(Color.Yellow);
                //paint the background behind the search word  
                e.Graphics.FillRectangle(hl_brush, hl_rect);
                hl_brush.Dispose();
                e.PaintContent(e.CellBounds);
            }
        }
    }
}

1 Ответ

1 голос
/ 03 апреля 2020

Задача


Для каждой ячейки необходимо учитывать несколько факторов:

  • DataGridViewContentAlignment .
  • Точный размер выделенных символов.
  • Символы нулевой ширины (пробелы).
  • Размер содержимого.
  • Пустое пространство.
  • Индекс первого вхождения строки поиска.

Все перечисленное необходимо для вычисления и корректировки как местоположения, так и размера выделения. прямоугольник.

Вот пример:

RTL Languages ​​- RTL Layout


private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (txtSearch.TextLength < 1 
        || e.RowIndex < 0 
        || e.ColumnIndex < 1
        || e.Value == null)
        return;

    var zeroWidth = "|";
    var v = e.Value.ToString().Replace(" ", zeroWidth);
    var f = txtSearch.Text.Replace(" ", zeroWidth);
    var i = v.IndexOf(f, StringComparison.InvariantCultureIgnoreCase);

    if (i < 0) return;

    e.Handled = true;
    var g = e.Graphics;

    using (var sf = ToStringFormat(e.CellStyle.Alignment))
    {
        var zw = g.MeasureString(zeroWidth, e.CellStyle.Font, e.CellBounds.Width, sf).Width;
        var valWidth = g.MeasureString(v, e.CellStyle.Font, e.CellBounds.Width, sf).Width;
        var w = g.MeasureString(f, e.CellStyle.Font, e.CellBounds.Width, sf).Width;
        var x = e.CellBounds.Right - ((e.CellBounds.Width - valWidth) / 2);

        x -= g.MeasureString(v.Substring(0, i), e.CellStyle.Font,
            e.CellBounds.Width, sf).Width;
        x -= w;

        switch (e.CellStyle.Alignment)
        {
            case DataGridViewContentAlignment.BottomLeft:
            case DataGridViewContentAlignment.MiddleLeft:
            case DataGridViewContentAlignment.TopLeft:
                x += ((e.CellBounds.Width - valWidth) / 2) - zw;
                break;
            case DataGridViewContentAlignment.MiddleRight:
            case DataGridViewContentAlignment.BottomRight:
            case DataGridViewContentAlignment.TopRight:
                x -= ((e.CellBounds.Width - valWidth) / 2) - zw;
                break;
            default:                        
                break;
        }

        var r = new RectangleF(
            x, 
            e.CellBounds.Y + 3, 
            w, 
            e.CellBounds.Height - 7);

        e.PaintBackground(e.CellBounds, true);
        g.FillRectangle(Brushes.Yellow, r);
        e.PaintContent(e.CellBounds);
    }
}

private StringFormat ToStringFormat(DataGridViewContentAlignment ca)
{
    var sf = StringFormat.GenericTypographic;

    switch (ca)
    {
        case DataGridViewContentAlignment.MiddleCenter:
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            break;
        case DataGridViewContentAlignment.MiddleLeft:
            sf.Alignment = StringAlignment.Near;
            sf.LineAlignment = StringAlignment.Center;
            break;
        case DataGridViewContentAlignment.MiddleRight:
            sf.Alignment = StringAlignment.Far;
            sf.LineAlignment = StringAlignment.Center;
            break;
        case DataGridViewContentAlignment.BottomCenter:
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Far;
            break;
        case DataGridViewContentAlignment.BottomLeft:
            sf.Alignment = StringAlignment.Near;
            sf.LineAlignment = StringAlignment.Far;
            break;
        case DataGridViewContentAlignment.BottomRight:
            sf.Alignment = StringAlignment.Far;
            sf.LineAlignment = StringAlignment.Far;
            break;
        case DataGridViewContentAlignment.TopLeft:
            sf.Alignment = StringAlignment.Near;
            sf.LineAlignment = StringAlignment.Near;
            break;
        case DataGridViewContentAlignment.TopRight:
            sf.Alignment = StringAlignment.Far;
            sf.LineAlignment = StringAlignment.Near;
            break;
        case DataGridViewContentAlignment.TopCenter:
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Near;
            break;
    }

    sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;

    return sf;
}

Вот демонстрация .

SOQ60983817A

Примечание: Только DGV настроен на макет RTL в демонстрационной версии.

Языки LTR - макет LTR


Возможно, выходит за рамки, но может быть кому-то полезно.

private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (txtSearch.TextLength < 1
        || e.RowIndex < 0
        || e.ColumnIndex < 1
        || e.Value == null)
        return;

    var zeroWidth = "|";
    var v = e.Value.ToString().Replace(" ", zeroWidth);
    var f = txtSearch.Text.Replace(" ", zeroWidth);
    var i = v.IndexOf(f, StringComparison.InvariantCultureIgnoreCase);

    if (i < 0) return;

    e.Handled = true;

    var g = e.Graphics;

    using (var sf = ToStringFormat(e.CellStyle.Alignment))
    {
        var zs = g.MeasureString(zeroWidth, e.CellStyle.Font, 
            e.CellBounds.Width, sf).Width;
        var valWidth = g.MeasureString(v, e.CellStyle.Font, 
            e.CellBounds.Width, sf).Width;
        var x = g.MeasureString(v.Substring(0, i), e.CellStyle.Font, 
            e.CellBounds.Width, sf).Width;
        var w = g.MeasureString(v.Substring(i, f.Length), e.CellStyle.Font, 
            e.CellBounds.Width, sf).Width;


        switch (e.CellStyle.Alignment)
        {
            case DataGridViewContentAlignment.MiddleCenter:
            case DataGridViewContentAlignment.BottomCenter:
            case DataGridViewContentAlignment.TopCenter:
                x += (e.CellBounds.Width - valWidth) / 2;
                x -= zs / 2;
                break;
            case DataGridViewContentAlignment.MiddleRight:
            case DataGridViewContentAlignment.BottomRight:
            case DataGridViewContentAlignment.TopRight:
                x += (e.CellBounds.Width - valWidth);
                x -= zs * 1.5f;
                break;
            default:
                x += zs / 2;
                break;
        }

        var r = new RectangleF(
            e.CellBounds.X + x,
            e.CellBounds.Y + 3,
            w,
            e.CellBounds.Height - 7);

        e.PaintBackground(e.CellBounds, true);
        g.FillRectangle(Brushes.Yellow, r);
        e.PaintContent(e.CellBounds);
    }
}

private StringFormat ToStringFormat(DataGridViewContentAlignment ca)
{
    var sf = StringFormat.GenericTypographic;

    switch (ca)
    {
        case DataGridViewContentAlignment.MiddleCenter:
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            break;
        case DataGridViewContentAlignment.MiddleLeft:
            sf.Alignment = StringAlignment.Near;
            sf.LineAlignment = StringAlignment.Center;
            break;
        case DataGridViewContentAlignment.MiddleRight:
            sf.Alignment = StringAlignment.Far;
            sf.LineAlignment = StringAlignment.Center;
            break;
        case DataGridViewContentAlignment.BottomCenter:
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Far;
            break;
        case DataGridViewContentAlignment.BottomLeft:
            sf.Alignment = StringAlignment.Near;
            sf.LineAlignment = StringAlignment.Far;
            break;
        case DataGridViewContentAlignment.BottomRight:
            sf.Alignment = StringAlignment.Far;
            sf.LineAlignment = StringAlignment.Far;
            break;
        case DataGridViewContentAlignment.TopLeft:
            sf.Alignment = StringAlignment.Near;
            sf.LineAlignment = StringAlignment.Near;
            break;
        case DataGridViewContentAlignment.TopRight:
            sf.Alignment = StringAlignment.Far;
            sf.LineAlignment = StringAlignment.Near;
            break;
        case DataGridViewContentAlignment.TopCenter:
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Near;
            break;
    }

    return sf;
}

SOQ60983817B

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...