c# - 双向文本中点右侧的字符串宽度
问题描述
*对不起,如果标题不是很好。我不知道如何用几句话来概括这个问题。
我有一个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
之后。
那么如何获取位于查询右侧的字符串部分的宽度呢?
解决方案
注意:这不是问题的直接答案。这是一个替代方案。
作为一个选项,您可以在 HTML 表格中显示搜索结果并在WebBrowser
控件中显示它并使用 javascript 突出显示搜索文本。
要将搜索结果显示为 HTML,我将使用T4 运行时文本模板。这样,我可以将数据传递给 html 模板,并通过将模板的输出字符串分配给控件的DocumentText
属性来轻松呈现报表。WebBrowser
我已经使用这个想法来创建简单快速的打印文档,例如看看这篇文章。
要突出显示文本,您可以使用一些 javascript 代码或插件。例如,您可以看看这篇文章。
这是我将在这篇文章中分享的示例的结果:
例子
创建一个
Form
并在其上放置一个WebBrowser
控件和一个ToolStrip
控件,就像您在上图中看到的那样。将以下
.cs
文件添加到项目中,并将以下代码粘贴到文件中:namespace Sample { public class ReportModel { public string RTL { get; set; } public string LTR { get; set; } } }
向项目中添加一个新
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>
处理
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 متن" } , }; }
处理
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(); }
处理对象的和调用方法的
DocumentCompleted
事件并调用我们已经在html中创建的javascript函数:WebBrowser
InvokeScript
Document
highlight
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { var txt = searchTextBox.Text; if (!string.IsNullOrEmpty(txt)) webBrowser1.Document.InvokeScript("highlight", new object[] { txt }); }
运行应用程序并
123
在文本框中键入,然后按搜索按钮查看结果。
推荐阅读
- python-3.x - Tkinter - 你如何在 LabelFrame 上居中文本?
- arrays - C 混淆中的存储、语义和字符串文字
- python-3.8 - 检查文件中是否出现特定单词,如果没有打印文件中没有单词
- javascript - 通过用 Electron/React/TS 编写的应用程序发送电子邮件
- php - PHP artisan migrate 在 XAMPP 下找不到驱动程序
- python - 如何找出 url 是否包含 img 或其他文件?以及如何排除这些文件并仅下载图像?
- node.js - Angular 单元测试卡在 GitHub Action CI 上
- c - 结构程序在编译时给出错误
- c# - ASP .Net Core:使用 Cors 发布 API,请求正文给出 400 个错误请求
- c# - C# 使用 SourceGenerator 和 CSharpCompilation