using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Media; namespace ComPDFKit.Controls.PDFControlUI { public partial class CPDFSearchResultUI : UserControl { public event EventHandler SelectionChanged; private ObservableCollection searchResults; public CPDFSearchResultUI() { InitializeComponent(); searchResults = new ObservableCollection(); ICollectionView groupView = CollectionViewSource.GetDefaultView(searchResults); groupView.GroupDescriptions.Add(new PropertyGroupDescription(nameof(TextBindData.ShowPageIndex))); } private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { InvokeSelectionChangedEvent(ResultListControl.SelectedIndex); } public void SetSearchResult(List results) { searchResults.Clear(); if (results == null || results.Count == 0) { ResultListControl.ItemsSource = null; NoResultText.Visibility = Visibility.Visible; return; } foreach (BindSearchResult item in results) { searchResults.Add(new TextBindData() { BindProperty = item }); } ResultListControl.ItemsSource = searchResults; ResultListControl.Visibility = Visibility.Visible; NoResultText.Visibility = Visibility.Collapsed; } public void ClearSearchResult() { searchResults.Clear(); ResultListControl.ItemsSource = null; ResultListControl.Visibility = Visibility.Collapsed; NoResultText.Visibility = Visibility.Visible; } public void AddSearchResult(BindSearchResult result) { if (result == null) { return; } searchResults.Add(new TextBindData() { BindProperty = result }); ResultListControl.ItemsSource = searchResults; ResultListControl.Visibility = Visibility.Visible; NoResultText.Visibility = Visibility.Collapsed; } public BindSearchResult GetSelectItem() { TextBindData bindData = ResultListControl.SelectedItem as TextBindData; if (bindData != null) { return bindData.BindProperty; } return null; } public BindSearchResult GetItem(int index) { if (index < 0) { return null; } if (ResultListControl.HasItems && ResultListControl.Items.Count > index) { TextBindData bindData = ResultListControl.Items[index] as TextBindData; if (bindData != null) { return bindData.BindProperty; } } return null; } /// /// Clear selected results. /// public void ClearSelection() { int oldSelectionIndex = ResultListControl.SelectedIndex; ResultListControl.UnselectAll(); if (oldSelectionIndex != ResultListControl.SelectedIndex) { InvokeSelectionChangedEvent(ResultListControl.SelectedIndex); } } /// /// Set selected results. /// /// The selected index. public void SelectItem(int selectIndex) { if (ResultListControl.SelectedIndex != selectIndex) { ResultListControl.SelectedIndex = selectIndex; } } internal void InvokeSelectionChangedEvent(int selectionIndex) { SelectionChanged?.Invoke(this, selectionIndex); } } public class BindSearchResult { /// /// Page index. /// public int PageIndex { get; set; } /// /// The search text results. /// public string TextContent { get; set; } /// /// Search highlight color. /// public Color HighLightColor { get; set; } /// /// Search keywords. /// public string SearchWord { get; set; } /// /// Search result range area. /// public Rect TextRect { get; set; } /// /// The page rotation angle. /// public int PageRotate { get; set; } public object RefData { get; set; } } internal class TextBindData { public int ShowPageIndex { get { return BindProperty.PageIndex + 1; } set { BindProperty.PageIndex = value; } } public BindSearchResult BindProperty { get; set; } public TextBindData() { BindProperty = new BindSearchResult(); } } internal class SearchResultBindHelper : DependencyObject { public static FlowDocument GetDocumentBind(DependencyObject obj) { return (FlowDocument)obj.GetValue(DocumentBindProperty); } public static void SetDocumentBind(DependencyObject obj, FlowDocument value) { obj.SetValue(DocumentBindProperty, value); } public static readonly DependencyProperty DocumentBindProperty = DependencyProperty.RegisterAttached("DocumentBind", typeof(BindSearchResult), typeof(SearchResultBindHelper), new FrameworkPropertyMetadata { BindsTwoWayByDefault = false, PropertyChangedCallback = (obj, e) => { RichTextBox richTextBox = obj as RichTextBox; BindSearchResult bindItem = e.NewValue as BindSearchResult; if (richTextBox != null && bindItem != null) { richTextBox.Document = GetFlowDocument(bindItem.TextContent.Trim(), bindItem.SearchWord, bindItem.HighLightColor); } } }); /// /// Get document stream data /// /// Search text results /// Search for keywords /// Highlight text color /// Document flow data public static FlowDocument GetFlowDocument(string content, string keyword, Color textColor) { FlowDocument Document = new FlowDocument(); Paragraph textPara = new Paragraph(); Document.Blocks.Add(textPara); List indexList = new List(); content = Regex.Replace(content, "[\r\n]", " "); if (keyword.Length > 0) { for (int i = 0; i < content.Length && i >= 0;) { i = content.IndexOf(keyword, i, StringComparison.OrdinalIgnoreCase); if (i == -1) { break; } if (indexList.Contains(i) == false) { indexList.Add(i); } i += keyword.Length; } } List splitList = new List(); int lastIndex = -1; foreach (int index in indexList) { string prevStr = string.Empty; if (lastIndex == -1) { prevStr = content.Substring(0, index); } else { prevStr = content.Substring(lastIndex + keyword.Length, index - lastIndex - 1); } if (prevStr != string.Empty) { splitList.Add(prevStr); } splitList.Add(content.Substring(index, keyword.Length)); lastIndex = index; } if (indexList.Count > 0) { lastIndex = indexList[indexList.Count - 1]; if (content.Length > lastIndex + keyword.Length) { splitList.Add(content.Substring(lastIndex + keyword.Length)); } } TextBlock addBlock = new TextBlock(); foreach (string textappend in splitList) { Run textRun = new Run(textappend); if (textappend.Equals(keyword, StringComparison.OrdinalIgnoreCase)) { textRun.Background = new SolidColorBrush(textColor); } addBlock.Inlines.Add(textRun); } addBlock.TextTrimming = TextTrimming.CharacterEllipsis; textPara.Inlines.Add(addBlock); return Document; } } }