首页 > 解决方案 > 双向文本中点右侧的字符串宽度

问题描述

*对不起,如果标题不是很好。我不知道如何用几句话来概括这个问题。


我有一个DataGridView和一个搜索框。当用户键入查询时,DataGridView单元格中的任何匹配结果都会突出显示。为了实现这一点,我使用了CellPainting事件DataGridView并在结果后面绘制了一个矩形。

一些单元格是从右到左的:

在此处输入图像描述

有些是从左到右的:

在此处输入图像描述

当方向为 RTL 时,我使用以下公式计算高亮矩形 X 坐标:

e.CellBounds.Right - queryWidth - stringBeforeQueryWidth;

stringBeforeQueryWidth指的是:

在此处输入图像描述

当方向为 LTR 时,我使用以下公式:

e.CellBounds.Left + stringBeforeQueryWidth;

stringBeforeQueryWidth指的是:

在此处输入图像描述

我的计算方式stringBeforeQueryWidth如下:

var stringBeforeQuery = cellValue.Substring(0, cellValue.IndexOf(query));
var stringBeforeQueryWidth =
    e.Graphics.MeasureString(stringBeforeQuery, font, e.CellBounds.Width, format).Width;

所以当方向是 RTL 时,我使用查询本身之前的所有字符都将绘制到它的右侧的事实,当方向是 LTR 时,我使用查询之前的所有字符的事实本身将被绘制到它的左侧。

当单元格包含一个组合 LTR 和 RTL 文本的字符串时,问题就开始了。例如: 在此处输入图像描述

假设查询是13. 要计算stringBeforeQueryWidth我需要的宽度רחוב ישראל ישראלי和宽度/5。我不能用它cellValue.Substring(0, cellValue.IndexOf(query))来检索它们,就像我在只有一个方向时所做的那样,因为רחוב ישראל ישראלי它在查询之前,在查询/5之后。

在此处输入图像描述

那么如何获取位于查询右侧的字符串部分的宽度呢?

标签: c#stringwinformsright-to-leftleft-to-right

解决方案


注意:这不是问题的直接答案。这是一个替代方案。

作为一个选项,您可以在 HTML 表格中显示搜索结果并在WebBrowser控件中显示它并使用 javascript 突出显示搜索文本。

要将搜索结果显示为 HTML,我将使用T4 运行时文本模板。这样,我可以将数据传递给 html 模板,并通过将模板的输出字符串分配给控件的DocumentText属性来轻松呈现报表。WebBrowser我已经使用这个想法来创建简单快速的打印文档,例如看看这篇文章

要突出显示文本,您可以使用一些 javascript 代码或插件。例如,您可以看看这篇文章

这是我将在这篇文章中分享的示例的结果:

在此处输入图像描述

例子

  1. 创建一个Form并在其上放置一个WebBrowser控件和一个ToolStrip控件,就像您在上图中看到的那样。

  2. 将以下.cs文件添加到项目中,并将以下代码粘贴到文件中:

    namespace Sample
    {
        public class ReportModel
        {
            public string RTL { get; set; }
            public string LTR { get; set; }
        }
    }
    
  3. 向项目中添加一个新RunTime Text Template项目并将其命名ReportTemplate.tt。打开文件并粘贴以下内容。在这里,我使用了这个插件来突出显示文本。并将模型传递给 t4 模板以轻松生成 HTML:

    <#@ template language="C#"#>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ parameter name="Model" type="System.Collections.Generic.List<Sample.ReportModel>"#>
    <!DOCTYPE html>
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=11" />
        <title></title>
        <style type="text/css">
            body { font-family: Calibri;}
            table { text-align:center; border-collapse: collapse;}
            table, th, td { border: 1px solid black; }
            th {background-color: #EEEEEE;}
            th , td {padding: 2px;}
            .container { width:100%; height:100%; }
            .highlight { background: yellow; }
            .rtl {direction: rtl; text-align: right;}
            .ltr {direction: ltr; text-align: left;}
        </style>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://johannburkard.de/resources/Johann/jquery.highlight-5.js"></script>
        <script>
        function highlight(text) {
            $('#container').highlight(text);
        }
        </script>
    </head>
    <body>
    <div id ="container" class="container">
    <table style="width:100%">
        <tr>
            <th style="width:50%">LTR</th>
            <th style="width:50%">RTL</th>
        </tr>
        <#
        foreach(var item in Model) 
        {
        #>
        <tr>
            <td class="ltr"><#=item.LTR#></td>
            <td class="rtl"><#=item.RTL#></td>
        </tr>
        <#
        }
        #>
    </table>
    <div>
    </body>
    </html>
    
  4. 处理Load表单事件并关闭脚本错误并初始化示例数据:

    List<ReportModel> list;
    private void Form1_Load(object sender, EventArgs e)
    {
        webBrowser1.ScriptErrorsSuppressed = true;
        list = new List<ReportModel>()
        {
            new ReportModel(){ LTR = "Text 123 text", RTL = "متن 123 متن" }  ,
            new ReportModel(){ LTR = "Text 123 text", RTL = "متن 123 متن" }  ,
            new ReportModel(){ LTR = "Text 456 text", RTL = "متن 456 متن" }  ,
            new ReportModel(){ LTR = "Text 456 text", RTL = "متن 456 متن" }  ,
            new ReportModel(){ LTR = "Text 456 text", RTL = "متن 456 متن" }  ,
            new ReportModel(){ LTR = "Text 456 text", RTL = "متن 456 متن" }  ,
        };
    }
    
  5. 处理Click搜索按钮和搜索的事件,并将搜索结果传递给模板并运行模板并在WebBrowser控件中显示结果:

    private void searchButton_Click(object sender, EventArgs e)
    {
        var txt = searchTextBox.Text;
        var rpt = new ReportTemplate();
        rpt.Session = new Dictionary<string, object>();
        rpt.Session["Model"] = list.Where(x => x.LTR.Contains(txt) ||
            x.RTL.Contains(txt)).ToList();
        rpt.Initialize();
        webBrowser1.DocumentText = rpt.TransformText();
    }
    
  6. 处理对象的和调用方法的DocumentCompleted事件并调用我们已经在html中创建的javascript函数:WebBrowserInvokeScriptDocumenthighlight

    private void webBrowser1_DocumentCompleted(object sender,
        WebBrowserDocumentCompletedEventArgs e)
    {
        var txt = searchTextBox.Text;
        if (!string.IsNullOrEmpty(txt))
            webBrowser1.Document.InvokeScript("highlight",
                new object[] { txt });
    }
    
  7. 运行应用程序并123在文本框中键入,然后按搜索按钮查看结果。


推荐阅读