我在 WPF 中有一个要求,其中...
- 我希望富文本框用作一个特定列的列表视图的 dateTemplate(有备注)
- 我有一组关键字(添加、搜索、位置等)。在该列中,我希望所有这些关键字都以黄色突出显示。
- 我有另一个 TextBox 。如果我在该文本框中键入任何用于搜索的单词并且它存在于列表视图中,那么它应该以绿色突出显示。
- 如果我搜索黄色的关键字,那么它们不应该用绿色突出显示,它们应该是黄色的。
- 如果我有“add”字样,其中 add 以黄色突出显示,那么当我搜索“add”时,“add”应该是黄色的,“ed”应该是绿色的。
任何帮助表示赞赏。我尝试了几种方法,但在上面的最后一点失败了。
//代码片段
// Xaml 文件
<Window x:Class="RichtextBoxhighlight.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:RichtextBoxhighlight"
Title="MainWindow" Height="406" Width="855"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<src:ContentPlainConverter x:Key="typeConverter" />
<src:TestConvertor x:Key="spaceRem"/>
<Style x:Key="RichTextBoxWithRoundedCorners" TargetType="{x:Type RichTextBox}">
<Style.Resources>
<Style x:Key="{x:Type FlowDocument}" TargetType="{x:Type FlowDocument}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
</Style>
</Style.Resources>
</Style>
</Window.Resources>
<Grid>
<TextBox Margin="114,14,130,255" Name="txtText" />
<Grid>
<ListView Height="241" ItemsSource="{Binding CollRemarks}" HorizontalAlignment="Left" Margin="0,126,0,0" Name="listView1" VerticalAlignment="Top" Width="827" >
<ListView.View >
<GridView >
<GridViewColumn Header="Type" Width="80" DisplayMemberBinding="{Binding Path=type}"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Operatorid}" Width="70">
<GridViewColumnHeader Tag="CreatedEmployeeId" Content="Operator"/>
</GridViewColumn>
<GridViewColumn Width="710">
<GridViewColumn.CellTemplate>
<DataTemplate>
<src:BindableRichTextBox Document ="{Binding Path=remarks, Converter= {StaticResource typeConverter}}" HighlightPhrase="{Binding ElementName=txtText, Path=Text,Converter={StaticResource spaceRem}}" IsReadOnly="True" Background="Transparent" BorderBrush="Transparent" BorderThickness="0"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumnHeader Tag="CommentText" Content="Remark" />
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Grid>
</Window>
//BindableRichTextBox class :
namespace RichtextBoxhighlight
{
public class BindableRichTextBox : RichTextBox
{
public static string oldstring;
public static readonly DependencyProperty DocumentProperty =
DependencyProperty.Register("Document", typeof(FlowDocument),
typeof(BindableRichTextBox), new FrameworkPropertyMetadata
(null, new PropertyChangedCallback(OnDocumentChanged)));
public static readonly DependencyProperty HighlightPhraseProperty =
DependencyProperty.Register("HighlightPhrase", typeof(string),
typeof(BindableRichTextBox), new FrameworkPropertyMetadata(String.Empty, FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(UpdateHighlighting)));
public string HighlightPhrase
{
get { return (string)GetValue(HighlightPhraseProperty); }
set { SetValue(HighlightPhraseProperty, value); }
}
private static void UpdateHighlighting(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//invoked on text box search
ApplyHighlight(d as BindableRichTextBox);
ApplyAllHighlight(d as BindableRichTextBox);
}
// Gets or sets the Document of RichtextBox
public new FlowDocument Document
{
get
{
return (FlowDocument)this.GetValue(DocumentProperty);
}
set
{
this.SetValue(DocumentProperty, value);
}
}
// Method invoked on documnet formation.
public static void OnDocumentChanged(DependencyObject obj,
DependencyPropertyChangedEventArgs args)
{
try
{
RichTextBox rtb = (RichTextBox)obj;
// ApplyHighlight(rtb as BindableRichTextBox);
rtb.Document = (FlowDocument)args.NewValue;
ApplyAllHighlight(rtb as BindableRichTextBox);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// Implementation logic for Text Changed search highlight
/// </summary>
private static void ApplyHighlight(BindableRichTextBox tb)
{
try
{
if (tb != null && tb.Document != null)
{
string highlightPhrase = tb.HighlightPhrase;
// Frame the highlight word to skip them from getting highlighted by searchtext
string highlightWords = "(";
for (int i = 0; i < MainWindow.Highlightwords.Count; i++)
{
highlightWords += MainWindow.Highlightwords[i];
if (i != MainWindow.Highlightwords.Count - 1)
highlightWords += "|";
}
highlightWords += ")";
var start = tb.Document.ContentStart;
TextRange range = new TextRange(start, tb.Document.ContentEnd);
range.ClearAllProperties();
Regex ignore = new Regex(highlightWords, RegexOptions.Compiled | RegexOptions.IgnoreCase);
string Text = range.Text;
int index_match = 0;
if (highlightPhrase != string.Empty && highlightPhrase != null)
{
while (start != null && start.CompareTo(tb.Document.ContentEnd) < 0)
{
// Comparison to skip the key words in the column to be highlighted
if (start.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
index_match = Text.IndexOf(highlightPhrase, StringComparison.OrdinalIgnoreCase);
if (index_match >= 0)
{
//Ignore all Keyword highlight by incrementing start and moving to next match
MatchCollection matches = ignore.Matches(start.GetTextInRun(LogicalDirection.Forward));
if (matches != null)
{
for (int i = 0; i < matches.Count; i++)
{
if ((index_match >= matches[i].Index && index_match <= matches[i].Index + matches[i].Length))
{
start = start.GetPositionAtOffset(matches[i].Index + matches[i].Length, LogicalDirection.Forward);
Text = new TextRange(start.GetInsertionPosition(LogicalDirection.Forward), start.DocumentEnd).Text;
//Highlight the search text if part before keyword
if (highlightPhrase.Length > matches[i].Length)
{
var textrange = new TextRange(start.GetPositionAtOffset(0, LogicalDirection.Forward), start.GetPositionAtOffset(highlightPhrase.Length - matches[i].Length, LogicalDirection.Backward));
textrange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Green));
}
if (start != null && start.CompareTo(tb.Document.ContentEnd) < 0)
{
index_match = Text.IndexOf(highlightPhrase, StringComparison.OrdinalIgnoreCase);
if (index_match >= 0)
{
matches = ignore.Matches(start.GetTextInRun(LogicalDirection.Forward));
if (matches != null && matches.Count > 0)
i--;
}
else
break;
}
}
else if ((highlightPhrase.Length - 1 >= matches[i].Index && highlightPhrase.Length + index_match <= matches[i].Index + matches[i].Length))
{
//Highlight the search text if part after keyword
var textrange = new TextRange(start.GetPositionAtOffset(index_match, LogicalDirection.Forward), start.GetPositionAtOffset(matches[i].Index, LogicalDirection.Backward));
textrange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Green));
start = start.GetPositionAtOffset(matches[i].Index + matches[i].Length, LogicalDirection.Forward);
Text = new TextRange(start.GetInsertionPosition(LogicalDirection.Forward), start.DocumentEnd).Text;
if (start != null && start.CompareTo(tb.Document.ContentEnd) < 0)
{
index_match = Text.IndexOf(highlightPhrase, StringComparison.OrdinalIgnoreCase);
if (index_match >= 0)
{
matches = ignore.Matches(start.GetTextInRun(LogicalDirection.Forward));
if (matches != null && matches.Count > 0)
i--;
}
else
break;
}
}
}
}
if (index_match >= 0 && start != null && (start.CompareTo(tb.Document.ContentEnd) < 0))
{
//Highlight the search text typed if not part of Keywords
var textrange = new TextRange(start.GetPositionAtOffset(index_match, LogicalDirection.Forward), start.GetPositionAtOffset(index_match + highlightPhrase.Length, LogicalDirection.Backward));
textrange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Green));
start = textrange.End;
Text = new TextRange(textrange.End, start.DocumentEnd).Text;
}
}
else
break;
}
if (start != null && start.CompareTo(tb.Document.ContentEnd) < 0)
start = start.GetNextContextPosition(LogicalDirection.Forward);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// Implementation logic for key words highlight
/// </summary>
private static void ApplyAllHighlight(BindableRichTextBox rtb)
{
try
{
if (rtb != null)
{
string highlightWords = "(";
for (int i = 0; i < MainWindow.Highlightwords.Count; i++)
{
highlightWords += MainWindow.Highlightwords[i];
if (i != MainWindow.Highlightwords.Count - 1)
highlightWords += "|";
}
highlightWords += ")";
Regex reg = new Regex(highlightWords, RegexOptions.Compiled | RegexOptions.IgnoreCase);
var start = rtb.Document.ContentStart;
while (start != null && start.CompareTo(rtb.Document.ContentEnd) < 0)
{
if (start.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
var match = reg.Match(start.GetTextInRun(LogicalDirection.Forward));
var textrange = new TextRange(start.GetPositionAtOffset(match.Index, LogicalDirection.Forward), start.GetPositionAtOffset(match.Index + match.Length, LogicalDirection.Backward));
textrange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
start = textrange.End;
}
start = start.GetNextContextPosition(LogicalDirection.Forward);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
//Content of list view remarks column and keywords to be highlighted
//Key word to be highlighted
Highlightwords = new List<string>();
Highlightwords.Add("mment");
Highlightwords.Add("ADD");
Highlightwords.Add("LOCATION");
Highlightwords.Add("arch");
// Remarks in list view
CollRemarks = new ObservableCollection<evcom>();
string remar = "search for added comments in location added";
CollRemarks.Add(new evcom { type = "Info", Operatorid = "1728", remarks = remar });
remar = "searched for added add comments in location added LOCATIONS";
CollRemarks.Add(new evcom { type = "Info", Operatorid = "1783", remarks = remar });