当前位置:网站首页>WPF 实现 RichTextBox 关键字查询高亮
WPF 实现 RichTextBox 关键字查询高亮
2022-07-20 14:29:00 【太阳风暴】
导言:我想实现一个简单的载入RTF文件到RichTextBox 中并可以查找关键字,并高亮关键字,提供上一个关键字与下一个关键字之间相互切换的效果,目前还有些小问题,就是RichTextBox 窗口导航到关键字的位置有些问题。
- 建议先看 演示结果 再看看是不是你需要的
一、环境说明
- 系统:Windows 10.0.19044 家庭版
- 工具:Visual Stdio 2019 community
- .Net:.Net FrameWork 4.6.2
- 类型:WPF桌面应用
二、代码
1、前端代码
<Window x:Class="xx_MSS.Pages.IntroductionWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:xx_MSS.Pages" mc:Ignorable="d" FontSize="18" Title="测试测试" Height="680" Width="1028">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Column="0">
<Label Content="质谱仪:" FontWeight="Bold" VerticalAlignment="Top" Margin="40, 10, 0,0" />
<ComboBox Grid.Row="2" x:Name="m_combox" Width="150" Height="30" VerticalAlignment="Top" Margin="0, 10" SelectionChanged="upDateDoucument">
<ComboBoxItem Content="质谱仪器1" IsSelected="True"/>
<ComboBoxItem Content="质谱仪器2"/>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<Label Content="搜索:" FontWeight="Bold" VerticalAlignment="Top" Margin="10, 10, 0,0" />
<TextBox x:Name="m_SearchTextBox" Width="300" Height="30" VerticalAlignment="Top" Margin="0, 10" KeyUp="excetueSearch"/>
<Button x:Name="m_SearchBefore" Click="searchAfterBeforeBtnClicked" Height="30" Content="《" Width="40" Margin="0,10,0,20"/>
<Button x:Name="m_SearchAfter" Click="searchAfterBeforeBtnClicked" Height="30" Margin="0,10,0,20" Content="》" Width="40"/>
</StackPanel>
</Grid>
<RichTextBox x:Name="m_richText" Grid.Row="1" BorderThickness="0" Margin="60, 10, 60, 5" />
</Grid>
</Window>
2、后端代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Diagnostics;
namespace xx_MSS.Pages
{
public class CommonColorsHelp
{
public static Color KeyFontColor = Color.FromRgb(0, 0, 0);
public static Color DefaultFontColor = Color.FromRgb(0, 0, 0);
public static Color SelectedKeyBackGroundColor = Color.FromRgb(234, 167, 255);
public static Color SelectedKeyFontColor = Color.FromRgb(0, 0, 0);
public static Color DefaultBackGroundColor = Color.FromRgb(255, 255, 255);
}
/// <summary>
/// Introduction.xaml 的交互逻辑
/// </summary>
public partial class IntroductionWindow : Window
{
private Dictionary<string, string> m_mapBooksPairs;
public IntroductionWindow()
{
InitializeComponent();
m_richText.IsReadOnly = true;
//绑定页面而已,在根路径下放置几个rtf文件即可
m_mapBooksPairs = new Dictionary<string, string>();
m_mapBooksPairs.Add("质谱仪器1", "./Documents/one.rtf");
m_mapBooksPairs.Add("质谱仪器2", "./Documents/two.rtf");
loadFile(m_combox.Text, m_richText);
}
/// <summary>
/// 加载文件
/// </summary>
/// <param name="filename"></param>
/// <param name="richTextBox"></param>
private void loadFile(string filename, RichTextBox richTextBox)
{
filename = m_mapBooksPairs[filename];
if (string.IsNullOrEmpty(filename))
{
throw new ArgumentNullException();
}
if (!File.Exists(filename))
{
throw new FileNotFoundException();
}
using (FileStream stream = File.OpenRead(filename))
{
TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
string dataFormat = DataFormats.Text;
string ext = System.IO.Path.GetExtension(filename);
if (String.Compare(ext, ".xaml", true) == 0)
{
dataFormat = DataFormats.Xaml;
}
else if (String.Compare(ext, ".rtf", true) == 0)
{
dataFormat = DataFormats.Rtf;
}
documentTextRange.Load(stream, dataFormat);
}
}
private void upDateDoucument(object sender, SelectionChangedEventArgs e)
{
ComboBox comboBox = (ComboBox)sender;
var name = comboBox.SelectedItem.ToString().Split(':')[1].Trim();
if(m_mapBooksPairs != null)
{
loadFile(name, m_richText);
}
}
private void excetueSearch(object sender, KeyEventArgs e)
{
if(e.Key == Key.Enter)
{
string searchKey = m_SearchTextBox.Text.Trim();
if (searchKey != "")
{
ChangeSeachKeyWordsColor(searchKey);
}
else
{
ReSetBackGroundAll();
}
}
}
/// <summary>
/// 改变在文章中用户搜索的关键字的字体颜色
/// </summary>
/// <param name="keyword"></param>
public void ChangeSeachKeyWordsColor(string keyword)
{
ChangeColorWithResout(keyword);
}
/// <summary>
/// 改变关键字的字体颜色
/// </summary>
/// <param name="keyword">用户搜索关键字</param>
/// <returns></returns>
private List<TextRange> ChangeColorWithResout(string keyword)
{
if (!string.IsNullOrEmpty(m_ProSearchkey))
{
ChangeColor(CommonColorsHelp.DefaultFontColor, m_ProSearchkey);
ReSetBackGroundAll();
}
m_ProSearchkey = keyword;
return ChangeColor(CommonColorsHelp.KeyFontColor, keyword);
}
/// <summary>
/// 设置背景色
/// </summary>
/// <param name="l"></param>
/// <param name="textRange"></param>
public void SetBackGround(Color l, TextRange textRange)
{
textRange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(l));
textRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(CommonColorsHelp.SelectedKeyFontColor));
}
/// <summary>
/// 重新设置背景色
/// </summary>
/// <param name="textRange">关键字的的TextRange</param>
/// <param name="isCurrKeyWord">是否是当前的关键字</param>
public void ReSetBackGround(TextRange textRange, bool isCurrKeyWord)
{
textRange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(CommonColorsHelp.DefaultBackGroundColor));
if (isCurrKeyWord)
{
textRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(CommonColorsHelp.KeyFontColor));
}
else
{
textRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(CommonColorsHelp.DefaultFontColor));
}
}
/// <summary>
/// 上一处
/// </summary>
public void SetUpBackGround()
{
if (m_TextList != null && m_TextList.Count > 0)
{
//Rect r = m_TextList[currNumber].Start.GetCharacterRect(LogicalDirection.Backward);
//m_richText.ScrollToVerticalOffset(r.Y);
//FrameworkContentElement e = m_TextList[currNumber].Start.Parent as FrameworkContentElement;
//if (e != null)
// e.BringIntoView();
///滚动到指定位置
var characterRect = m_TextList[currNumber].Start.GetCharacterRect(LogicalDirection.Forward);
m_richText.ScrollToVerticalOffset(m_richText.VerticalOffset + characterRect.Top - m_richText.ActualHeight / 2d);
ReSetBackGround(m_TextList[currNumber], true);
currNumber--;
if (currNumber < 0)
{
currNumber = m_TextList.Count - 1;
}
SetBackGround(CommonColorsHelp.SelectedKeyBackGroundColor, m_TextList[currNumber]);
}
}
/// <summary>
/// 下一处
/// </summary>
public void SetDownBackGround()
{
if (m_TextList != null && m_TextList.Count > 0)
{
//Rect r = m_TextList[currNumber].Start.GetCharacterRect(LogicalDirection.Backward);
//m_richText.ScrollToVerticalOffset(r.Y);
//FrameworkContentElement e = m_TextList[currNumber].Start.Parent as FrameworkContentElement;
//if (e != null)
// e.BringIntoView();
var characterRect = m_TextList[currNumber].Start.GetCharacterRect(LogicalDirection.Forward);
m_richText.ScrollToVerticalOffset(m_richText.VerticalOffset + characterRect.Top - m_richText.ActualHeight / 2d);
ReSetBackGround(m_TextList[currNumber], true);
currNumber++;
if (currNumber >= m_TextList.Count)
{
currNumber = 0;
}
SetBackGround(CommonColorsHelp.SelectedKeyBackGroundColor, m_TextList[currNumber]);
}
}
/// <summary>
/// 改变关键字的具体实现
/// </summary>
/// <param name="l"></param>
/// <param name="richTextBox1"></param>
/// <param name="selectLength"></param>
/// <param name="tpStart"></param>
/// <param name="tpEnd"></param>
/// <returns></returns>
private TextPointer selecta(Color l, RichTextBox richTextBox1, int selectLength, TextPointer tpStart, TextPointer tpEnd)
{
TextRange range = richTextBox1.Selection;
range.Select(tpStart, tpEnd);
//高亮选择
range.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(l));
return tpEnd.GetNextContextPosition(LogicalDirection.Forward);
}
/// <summary>
/// 把所有背景恢复到默认
/// </summary>
private void ReSetBackGroundAll()
{
if (m_TextList != null)
{
foreach (TextRange textRange in m_TextList)
{
ReSetBackGround(textRange, false);
}
}
}
/// <summary>
/// 当前第几处关键字被选中
/// </summary>
private int currNumber = 0;
/// <summary>
/// 改变关键字字体颜色
/// </summary>
/// <param name="l">颜色</param>
/// <param name="keyword">关键字</param>
/// <returns></returns>
private List<TextRange> ChangeColor(Color l, string keyword)
{
m_TextList = new List<TextRange>();
//设置文字指针为Document初始位置
//richBox.Document.FlowDirection
TextPointer position = m_richText.Document.ContentStart;
while (position != null)
{
//向前搜索,需要内容为Text
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
//拿出Run的Text
string text = position.GetTextInRun(LogicalDirection.Forward);
//可能包含多个keyword,做遍历查找
int index = 0;
index = text.IndexOf(keyword, 0);
if (index != -1)
{
TextPointer start = position.GetPositionAtOffset(index);
TextPointer end = start.GetPositionAtOffset(keyword.Length);
m_TextList.Add(new TextRange(start, end));
position = selecta(l, m_richText, keyword.Length, start, end);
}
}
//文字指针向前偏移
position = position.GetNextContextPosition(LogicalDirection.Forward);
}
if (m_TextList != null && m_TextList.Count > 0)
{
//重置
currNumber = 0;
SetBackGround(CommonColorsHelp.SelectedKeyBackGroundColor, m_TextList[currNumber]);
}
return m_TextList;
}
/// <summary>
/// 当前关键字共搜索出的结果集合
/// </summary>
private List<TextRange> m_TextList;
private string m_ProSearchkey;
private void searchAfterBeforeBtnClicked(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
switch(button.Name)
{
case "m_SearchBefore":
SetUpBackGround();
break;
case "m_SearchAfter":
SetDownBackGround();
break;
}
}
}
}
三、演示结果
四、参考资料
WPF搜索关键字:https://www.cnblogs.com/shanranlei/p/3635317.html
RichTextBox滚动到关键字位置:https://stackoverflow.com/questions/6908983/wpf-richtextbox-scroll-to-textpointer
边栏推荐
猜你喜欢
随机推荐
7.15 - 每日一题 - 408
使用 SAP UI5 系统测试工具 UIVeri5 的一个具体例子
C语言词语翻译(通过单词基本含义帮助理解)不定期更新……
7.14 - 每日一题 - 408
Why does cloud speed live broadcast win the favor of enterprises?
瓜分30万奖金!DeepRec CTR模型性能优化天池挑战赛来啦
Mysql中的Enum数据类型实例分析
菜鸟教程之工具使用——IDEA 查看子类(实现类)类图
MySQL全局锁
About whether the processing of SSR will continue after SAP Spartacus CSR fallback
Gap Locks(间隙锁)
C语言:预处理
ESP32 OLED LVGL 显示常用中文字符
Codeforces Round #651 (Div. 2)ABCD题解
C语言中长度为零的数组详解 (1)【文章结尾有资料】
One of the learning tutorials of SAP Hana cloud: how to create an instance of SAP Hana cloud on SAP BTP
Stay away from the market
MySQL页锁
2022第十四届南京国际智慧工地展览会|智慧工地展
云速直播凭何荣获企业青睐?