{"id":280231,"date":"2016-10-31T18:10:03","date_gmt":"2016-10-31T15:10:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=280231"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=280231","title":{"rendered":"TextBlock \u0441 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u043e\u0439 \u0442\u0435\u043a\u0441\u0442\u0430 (WPF)"},"content":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442 \u0425\u0430\u0431\u0440! \u042f \u0441\u043e\u0437\u0434\u0430\u043b \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <i>TextBlock<\/i> \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u0430. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043f\u0440\u0438\u043c\u0435\u0440 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0437\u0430\u0442\u0435\u043c \u043e\u043f\u0438\u0448\u0443, \u043a\u0430\u043a \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0441\u044f.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;local:HighlightTextBlock TextWrapping=&quot;Wrap&quot;&gt;     &lt;local:HighlightTextBlock.HighlightRules&gt;         &lt;local:HighlightRule HightlightedText=&quot;{Binding Filter, Source={x:Reference thisWindow}}&quot;&gt;             &lt;local:HighlightRule.Highlights&gt;                 &lt;local:HighlightBackgroung Brush=&quot;Yellow&quot;\/&gt;                 &lt;local:HighlightForeground Brush=&quot;Black&quot;\/&gt;             &lt;\/local:HighlightRule.Highlights&gt;         &lt;\/local:HighlightRule&gt;     &lt;\/local:HighlightTextBlock.HighlightRules&gt;     &lt;Run FontWeight=&quot;Bold&quot;&gt;Property:&lt;\/Run&gt;     &lt;Run Text=&quot;{Binding Property}&quot;\/&gt; &lt;\/local:HighlightTextBlock&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<h3>\u041d\u0430\u0447\u0430\u043b\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/h3>\n<p>  \u041f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043c\u043d\u0435 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0432 <i>TextBlock<\/i>, \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u043f\u043e\u0438\u0441\u043a\u0430. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439. \u041f\u0440\u0438\u0448\u043b\u043e \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 3 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 <i>Run<\/i>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0438 \u0432 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440 \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442, \u0441\u0442\u0440\u043e\u043a\u0443 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u0441\u0432\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 (1\/2\/3). \u0421\u0440\u0435\u0434\u043d\u0438\u0439 <i>Run<\/i> \u0438\u043c\u0435\u0435\u0442 <i>Backgroung<\/i>. <\/p>\n<p>  \u041d\u0435 \u0443\u0441\u043f\u0435\u043b \u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u0430\u043a \u043f\u0440\u0438\u0448\u043b\u0430 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043c\u044b\u0441\u043b\u044c, \u0447\u0442\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e. \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>  \u0411\u044b\u043b\u0430 \u0435\u0449\u0435 \u043c\u044b\u0441\u043b\u044c \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c <i>Xaml<\/i> \u00ab\u043d\u0430 \u043b\u0435\u0442\u0443\u00bb, \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <i>XamlReader<\/i> \u0438 \u043a\u0438\u0434\u0430\u0442\u044c \u0432 <i>TextBlock<\/i>. \u041d\u043e \u044d\u0442\u0430 \u043c\u044b\u0441\u043b\u044c \u0442\u043e\u0436\u0435 \u0441\u0440\u0430\u0437\u0443 \u043e\u0442\u0432\u0430\u043b\u0438\u043b\u0430\u0441\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u043f\u0430\u0445\u0438\u0432\u0430\u0435\u0442.<\/p>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 (\u0438 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439) \u0438\u0434\u0435\u0435\u0439 \u0441\u0442\u0430\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0438 \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u0435\u0435 \u043a <i>TextBlock<\/i>. \u0422\u0443\u0442 2 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430: \u0441\u0432\u043e\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u0441 \u0431\u043b\u044d\u043a\u0434\u0436\u0435\u043a\u043e\u043c \u0438 \u0434\u0435\u0432\u043e\u0447\u043a\u0430\u043c\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <i>TextBlock<\/i> \u0438\u043b\u0438 <i>AttachedProperty<\/i>. \u041f\u043e\u0441\u043b\u0435 \u043d\u0435\u0434\u043e\u043b\u0433\u0438\u0445 \u0440\u0430\u0437\u0434\u0443\u043c\u0438\u0439, \u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0432\u0441\u0435 \u0442\u0430\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0430\u043c\u043e\u0433\u043e <i>TextBlock<\/i>, \u0430 \u0440\u0430\u0437\u0440\u0443\u043b\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u043e\u0449\u0435, \u0435\u0441\u043b\u0438 \u043e\u0442 \u043d\u0435\u0433\u043e \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h3>\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430<\/h3>\n<p>  \u0418\u0442\u0430\u043a, \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c. \u0421\u0440\u0430\u0437\u0443 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0443, \u0447\u0442\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u044f \u0434\u0435\u043b\u0430\u043b \u0432 \u0442\u043e\u043c \u0436\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0433\u0434\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u043b\u0441\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u0443\u044e \u0438\u0434\u0435\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0439\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u0435\u0439\u043c\u0441\u043f\u0435\u0439\u0441\u044b. \u0414\u043e \u0443\u043c\u0430 \u0442\u0430\u043a\u0438\u0435 \u0432\u0435\u0449\u0438 \u044f \u0434\u043e\u0432\u0435\u0434\u0443 \u0443\u0436\u0435, \u043a\u043e\u0433\u0434\u0430 \u0431\u0443\u0434\u0443 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 (\u0438\u043b\u0438 \u0431\u0443\u0434\u0443 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0433\u0438\u0442\u0445\u0430\u0431).<\/p>\n<p>  \u0412 <i>Xaml<\/i> \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430 \u0432\u0441\u0435 \u0447\u0438\u0441\u0442\u043e, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f <i>Loaded<\/i><\/p>\n<pre><code class=\"xml\">&lt;TextBlock x:Class=&quot;WpfApplication18.HighlightTextBlock&quot;              xmlns=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation&quot;              xmlns:x=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml&quot;              Loaded=&quot;TextBlock_Loaded&quot;&gt; &lt;\/TextBlock&gt; <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043a\u043e\u0434\u0443:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">    public partial class HighlightTextBlock : TextBlock     {         \/\/ \u0417\u0434\u0435\u0441\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 TextBlock          \/\/ (\u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0438 \u043f\u043e\u0442\u043e\u043c \u0443\u0436\u0435 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 TextBlock)         string _content;          \/\/ \u042d\u0442\u043e \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0438\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u0435\u0439 \u0437\u0430\u0434\u0430\u0447         Dictionary&lt;HighlightRule, TaskQueue&gt; _ruleTasks;          \/\/\/ &lt;summary&gt;         \/\/\/ \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438         \/\/\/ &lt;\/summary&gt;         public HighlightRulesCollection HighlightRules         {             get             {                 return (HighlightRulesCollection)GetValue(HighlightRulesProperty);             }             set             {                 SetValue(HighlightRulesProperty, value);             }         }          public static readonly DependencyProperty HighlightRulesProperty =             DependencyProperty.Register(&quot;HighlightRules&quot;, typeof(HighlightRulesCollection), typeof(HighlightTextBlock), new FrameworkPropertyMetadata(null) { PropertyChangedCallback = HighlightRulesChanged });           static void HighlightRulesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)         {             var col = e.NewValue as HighlightRulesCollection;             var tb = sender as HighlightTextBlock;             if (col != null && tb != null)             {                 col.CollectionChanged += tb.HighlightRules_CollectionChanged;                 foreach (var rule in col)                 {                     rule.HighlightTextChanged += tb.Rule_HighlightTextChanged;                 }             }         }          public HighlightTextBlock()         {             _ruleTasks = new Dictionary&lt;HighlightRule, TaskQueue&gt;();             HighlightRules = new HighlightRulesCollection();             InitializeComponent();         }          \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438         void HighlightRules_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)         {             switch (e.Action)             {                 case System.Collections.Specialized.NotifyCollectionChangedAction.Add:                     foreach (HighlightRule rule in e.NewItems)                     {                         _ruleTasks.Add(rule, new TaskQueue(1));                         SubscribeRuleNotifies(rule);                         BeginHighlight(rule);                     }                     break;                 case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:                     foreach (HighlightRule rule in e.OldItems)                     {                         rule.HightlightedText = string.Empty;                         _ruleTasks.Remove(rule);                         UnsubscribeRuleNotifies(rule);                     }                     break;                 case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:                     foreach (HighlightRule rule in e.OldItems)                     {                         rule.HightlightedText = string.Empty;                         _ruleTasks.Remove(rule);                         UnsubscribeRuleNotifies(rule);                     }                     break;             }         }          \/\/ \u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438         void SubscribeRuleNotifies(HighlightRule rule)         {             rule.HighlightTextChanged += Rule_HighlightTextChanged;         }          \/\/ \u041e\u0442\u043f\u0438\u0441\u043a\u0430 \u043e\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438         void UnsubscribeRuleNotifies(HighlightRule rule)         {             rule.HighlightTextChanged -= Rule_HighlightTextChanged;         }          \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442, \u043a\u043e\u0433\u0434\u0430 \u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f         void Rule_HighlightTextChanged(object sender, HighlightTextChangedEventArgs e)         {             BeginHighlight((HighlightRule)sender);         }          \/\/ \u0417\u0434\u0435\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u043c \u043c\u043d\u043e\u044e \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0435 \u0437\u0430\u0434\u0430\u0447.         \/\/ \u0421\u043c\u044b\u0441\u043b \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u0432\u0432\u043e\u0434\u0438\u0442\u0441\u044f\/\u0441\u0442\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u044b\u0441\u0442\u0440\u043e,         \/\/ \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430 \u043d\u0435 \u0443\u0441\u043f\u0435\u0435\u0442 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u043e\u0432\u0430\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430         \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c. \u0415\u0441\u043b\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0443\u0436\u0435 \u0447\u0442\u043e \u0442\u043e \u0435\u0441\u0442\u044c, \u0442\u043e \u044d\u0442\u043e \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438         \/\/ \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0432\u043e\u044f.         void BeginHighlight(HighlightRule rule)         {             _ruleTasks[rule].Add(new Action(() =&gt; Highlight(rule)));         }          \/\/ \u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438         void Highlight(HighlightRule rule)         {             \/\/ \u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043f\u043e\u043a\u0438\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443             if (rule == null)                 return;              \/\/ \u0422\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0443 \u043d\u0430\u0441 \u0437\u0430\u0434\u0430\u044e\u0442\u0441\u044f \u0432 Xaml \u043a\u043e\u0434\u0435, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u043f\u043e\u0442\u043e\u043a\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0430,             \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u044c\/\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c             ObservableCollection&lt;Highlight&gt; highlights = null;             Application.Current.Dispatcher.Invoke(new ThreadStart(() =&gt;             {                 highlights = rule.Highlights;             }));              \/\/ \u0414\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043d\u043e \u0432 \u043d\u0435\u043c \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u043e, \u0447\u0435\u043c \u043f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0442\u044c, \u043f\u043e\u043a\u0438\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438             if (highlights.Count == 0)                 return;              \/\/ \u0415\u0449\u0435 \u0440\u044f\u0434 \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0434\u043b\u044f \u0432\u044b\u0445\u043e\u0434\u0430 \u0438\u0437 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438             var exitFlag = false;             exitFlag = exitFlag || string.IsNullOrWhiteSpace(_content);             Application.Current.Dispatcher.Invoke(new ThreadStart(() =&gt;             {                 exitFlag = exitFlag || Inlines.IsReadOnly || Inlines.Count == 0 ||                  HighlightRules == null || HighlightRules.Count == 0;             }));              if (exitFlag)                 return;              \/\/ \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u0440\u0430\u0433\u0440\u0430\u0444. \u0412\u0441\u0435 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0438 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0433\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0447\u0442\u043e \u043b\u0438\u0431\u043e             \/\/ \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 TextBlock \u043d\u0435\u043b\u044c\u0437\u044f, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432             var par = new Paragraph();              \/\/ \u041f\u0430\u0440\u0441\u0438\u043c _content, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443 \u043d\u0430\u0441 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 Span \u0441 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c TextBlock'a.             var parsedSp = (Span)XamlReader.Parse(_content);              \/\/ \u0421\u0430\u043c Span \u043d\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u0435\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043b\u0438\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0432 \u043f\u0430\u0440\u0430\u0433\u0440\u0430\u0444             par.Inlines.AddRange(parsedSp.Inlines.ToArray());              \/\/ \u041e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e (\u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430) \u0438 \u0432\u044b\u0434\u0435\u0440\u0433\u0438\u0432\u0430\u0435\u043c \u0438\u0437 TextBlock'a \u0433\u043e\u043b\u044b\u0439 \u0442\u0435\u043a\u0441\u0442.              \/\/ \u0418\u0441\u043a\u0430\u0442\u044c \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0438\u0441\u043a\u043e\u043c\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u043d\u0435\u043c             var firstPos = par.ContentStart;             var curText = string.Empty;             Application.Current.Dispatcher.Invoke(new ThreadStart(() =&gt;             {                 curText = Text;             }));              \/\/ \u0412\u044b\u0434\u0435\u0440\u0433\u0438\u0432\u0430\u0435\u043c \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438             var hlText = string.Empty;             Application.Current.Dispatcher.Invoke(new ThreadStart(() =&gt;             {                 hlText = rule.HightlightedText;             }));              \/\/ \u0415\u0441\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439 \u0438 \u0435\u0433\u043e \u0434\u043b\u0438\u043d\u0430 \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u0434\u043b\u0438\u043d\u0443 \u0442\u0435\u043a\u0441\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438\u0449\u0435\u043c,              \/\/ \u0442\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c, \u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0432\u0435\u0434\u0435\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b             if (!string.IsNullOrEmpty(hlText) && hlText.Length &lt;= curText.Length)             {                 \/\/ \u0412\u044b\u0434\u0435\u0440\u0433\u0438\u0432\u0430\u0435\u043c \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u0438\u0437 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e IgnoreCase.                 \/\/ \u0420\u0435\u0448\u0438\u043b \u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0441\u0442\u0430\u0432\u0438\u044c\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043e\u0447\u0435\u043d\u044c \u043d\u0438\u0437\u043a\u0430\u044f                 \/\/ \u0438 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043c\u043e\u0435\u0433\u043e \u043f\u043e\u0442\u0430 :)                 var comparison = StringComparison.CurrentCulture;                 Application.Current.Dispatcher.Invoke(new ThreadStart(() =&gt;                 {                     comparison = rule.IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture;                 }));                  \/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u043e\u0442\u043a\u0443\u0434\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0438\u0441\u043a\u043e\u043c\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0442\u0435\u043a\u0441\u0442\u0435                 var indexes = new List&lt;int&gt;();                 var ind = curText.IndexOf(hlText, comparison);                 while (ind &gt; -1)                 {                     indexes.Add(ind);                     ind = curText.IndexOf(hlText, ind + hlText.Length, StringComparison.CurrentCultureIgnoreCase);                 }                  TextPointer lastEndPosition = null;                 \/\/ \u041f\u0440\u043e\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0432\u0441\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c \u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u0432 \u0442\u0435\u043a\u0441\u0442                 foreach (var index in indexes)                 {                     \/\/ \u042d\u0442\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043d\u0443\u0436\u043d\u0430 \u0431\u044b\u043b\u0430 \u0432 \u043c\u043e\u0438\u0445 \u0441\u043e\u0438\u0441\u043a\u0430\u043d\u0438\u044f\u0445 \u043d\u0430\u0438\u043b\u0443\u0447\u0448\u0435\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0438\u0441\u043a\u0430,                     \/\/ \u0432\u0435\u0434\u044c \u0438\u043d\u0434\u0435\u043a\u0441 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 string \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044e TextPointer'a.                     \/\/ \u041f\u043e\u0438\u0441\u043a \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u044f \u043e\u0441\u0442\u0430\u0432\u0438\u043b.                     var curIndex = index;                      \/\/ \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043f\u043e\u0438\u0441\u043a \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043b\u0438\u0431\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u043c TextPointer \u0432\u043f\u0435\u0440\u0435\u0434                      \/\/ \u043d\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0440\u0430\u0432\u043d\u043e\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0442\u0435\u043a\u0441\u0442                     var pstart = lastEndPosition ?? firstPos.GetInsertionPosition(LogicalDirection.Forward).GetPositionAtOffset(curIndex);                      \/\/ startInd \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u0438\u043d\u043e\u0439 \u0442\u0435\u043a\u0441\u0442\u0430 \u043c\u0435\u0436\u0434\u0443 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c TextPointer \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438                     var startInd = new TextRange(pstart, firstPos.GetInsertionPosition(LogicalDirection.Forward)).Text.Length;                      \/\/ \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b startInd \u0431\u044b\u043b \u0440\u0430\u0432\u0435\u043d curIndex                     while (startInd != curIndex)                     {                         \/\/ \u0415\u0441\u043b\u0438 \u0447\u0435\u0441\u0442\u043d\u043e, \u043c\u043d\u0435 \u043d\u0435\u0449\u0435 \u043d\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438\u0441\u044c \u0441\u043b\u0443\u0447\u0430\u0438, \u043a\u043e\u0433\u0434\u0430 \u044f \u043e\u0431\u0433\u043e\u043d\u044f\u043b startInd \u043e\u0431\u0433\u043e\u043d\u044f\u043b curIndex, \u043e\u0434\u043d\u0430\u043a\u043e                         \/\/ \u0440\u0435\u0448\u0438\u043b \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u0430\u0434 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 \u0431\u043e\u043b\u0435\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043f\u043e\u0438\u0441\u043a\u0430                         if (startInd &lt; curIndex)                         {                             \/\/ \u0421\u043c\u0435\u0449\u0430\u0435\u043c \u0442\u043e\u0447\u043a\u0443 \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u043d\u0430 \u0440\u0430\u0437\u043d\u0438\u0446\u0443 curIndex - startInd                             var newpstart = pstart.GetPositionAtOffset(curIndex - startInd);                              \/\/ \u0418\u043d\u043e\u0433\u0434\u0430 TextPointer \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \\r \u0438 \\n, \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0447\u0430\u043b\u043e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438                             \/\/ \u0441\u0434\u0432\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u0432\u043f\u0435\u0440\u0435\u0434. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0433\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c, \u0434\u0432\u0438\u0433\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438                             if (newpstart.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)                                 newpstart = newpstart.GetInsertionPosition(LogicalDirection.Forward);                              var len = new TextRange(pstart, newpstart).Text.Length;                             startInd += len;                             pstart = newpstart;                         }                         else                         {                             var newpstart = pstart.GetPositionAtOffset(curIndex - startInd);                             var len = new TextRange(pstart, newpstart).Text.Length;                             startInd -= len;                             pstart = newpstart;                         }                     }                      \/\/ \u0418\u0449\u0435\u043c \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u043a\u0430\u043a \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439                     var pend = pstart.GetPositionAtOffset(hlText.Length);                     var delta = new TextRange(pstart, pend).Text.Length;                     while (delta != hlText.Length)                     {                         if (delta &lt; hlText.Length)                         {                             var newpend = pend.GetPositionAtOffset(hlText.Length - delta);                             var len = new TextRange(pend, newpend).Text.Length;                             delta += len;                             pend = newpend;                         }                         else                         {                             var newpend = pend.GetPositionAtOffset(hlText.Length - delta);                             var len = new TextRange(pend, newpend).Text.Length;                             delta -= len;                             pend = newpend;                         }                     }                      \/\/ \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c Hyperlink.                     \/\/ \u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u043d\u043e \u043f\u043e\u043a\u0430 \u0442\u0430\u043a\u043e\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043d\u0435\u0442,                      \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043b\u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u043c\u044b \u0440\u0435\u0436\u0435\u043c \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0443,                     \/\/ \u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0432\u0438\u0433\u0430\u0435\u043c \u044d\u0442\u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u0438. \u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0430 \u043b\u0438\u0431\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0443,                     \/\/ \u043b\u0438\u0431\u043e \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0441\u043e\u0432\u0441\u0435\u043c                     var sHyp = (pstart?.Parent as Inline)?.Parent as Hyperlink;                     var eHyp = (pend?.Parent as Inline)?.Parent as Hyperlink;                     if (sHyp != null)                         pstart = pstart.GetNextContextPosition(LogicalDirection.Forward);                      if (eHyp != null)                         pend = pend.GetNextContextPosition(LogicalDirection.Backward);                      \/\/ \u041d\u0443 \u0430 \u0442\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u043a \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438.                     if (pstart.GetOffsetToPosition(pend) &gt; 0)                     {                         var sp = new Span(pstart, pend);                         foreach (var hl in highlights)                             hl.SetHighlight(sp);                     }                     lastEndPosition = pend;                 }             }              \/\/ \u0417\u0434\u0435\u0441\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0439\u0441\u044f \u043f\u0430\u0440\u0430\u0433\u0440\u0430\u0444 \u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0432 TextBlock             var parStr = XamlWriter.Save(par);             Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() =&gt;             {                 Inlines.Clear();                 Inlines.AddRange(((Paragraph)XamlReader.Parse(parStr)).Inlines.ToArray());             })).Wait();         }          void TextBlock_Loaded(object sender, RoutedEventArgs e)         {             \/\/ \u0417\u0434\u0435\u0441\u044c \u0434\u0435\u0440\u0433\u0430\u0435\u043c \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 TextBlock'a \u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u0432 \u0441\u0442\u0440\u043e\u043a\u0443,             \/\/ \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0443 \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b.             \/\/ \u042d\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a, \u043d\u043e \u043f\u043e\u043a\u0430 \u0438 \u0442\u0430\u043a \u0441\u043e\u0439\u0434\u0435\u0442.             var sp = new Span();             sp.Inlines.AddRange(Inlines.ToArray());             var tr = new TextRange(sp.ContentStart, sp.ContentEnd);             using (var stream = new MemoryStream())             {                 tr.Save(stream, DataFormats.Xaml);                 stream.Position = 0;                 using(var reader = new StreamReader(stream))                 {                     _content = reader.ReadToEnd();                 }             }             Inlines.AddRange(sp.Inlines.ToArray());              \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0443 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u0440\u0430\u0432\u0438\u043b             foreach (var rule in HighlightRules)                 BeginHighlight(rule);         }     } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0437\u0434\u0435\u0441\u044c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u0434, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b.<\/p>\n<p>  \u0412\u043e\u0442 \u043a\u043e\u0434 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">    public class TaskQueue     {         Task _worker;         Queue&lt;Action&gt; _queue;         int _maxTasks;         bool _deleteOld;         object _lock = new object();          public TaskQueue(int maxTasks, bool deleteOld = true)         {             if (maxTasks &lt; 1)                 throw new ArgumentException(&quot;TaskQueue: \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0437\u0430\u0434\u0430\u0447 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 0&quot;);             _maxTasks = maxTasks;             _deleteOld = deleteOld;             _queue = new Queue&lt;Action&gt;(maxTasks);         }          public bool Add(Action action)         {             if (_queue.Count() &lt; _maxTasks)             {                 _queue.Enqueue(action);                 DoWorkAsync();                 return true;             }             if (_deleteOld)             {                 _queue.Dequeue();                 return Add(action);             }             return false;         }          void DoWorkAsync()         {             if(_queue.Count&gt;0)                 _worker = Task.Factory.StartNew(DoWork);         }          void DoWork()         {             lock (_lock)             {                 if (_queue.Count &gt; 0)                 {                     var currentTask = Task.Factory.StartNew(_queue.Dequeue());                     currentTask.Wait();                     DoWorkAsync();                 }             }         }     }  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0417\u0434\u0435\u0441\u044c \u0432\u0441\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e. \u041f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043d\u043e\u0432\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0415\u0441\u043b\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0435\u0441\u0442\u044c \u043c\u0435\u0441\u0442\u043e, \u0442\u043e \u043e\u043d\u0430 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c. \u0418\u043d\u0430\u0447\u0435, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u0435 <i>_deleteOld == true<\/i>, \u0442\u043e \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 (\u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0437\u0434\u043d\u044e\u044e) \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e, \u0438\u043d\u0430\u0447\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c false (\u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430).<\/p>\n<p>  \u0412\u043e\u0442 \u043a\u043e\u0434 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043f\u0440\u0430\u0432\u0438\u043b. \u041f\u043e \u0438\u0434\u0435\u0435, \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c <i>ObservableCollection<\/i>, \u043d\u043e \u043e\u0442 \u044d\u0442\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">    public class HighlightRulesCollection : DependencyObject, INotifyCollectionChanged, ICollectionViewFactory, IList, IList&lt;HighlightRule&gt;     {         ObservableCollection&lt;HighlightRule&gt; _items;          public HighlightRulesCollection()         {             _items = new ObservableCollection&lt;HighlightRule&gt;();             _items.CollectionChanged += _items_CollectionChanged;         }          public HighlightRule this[int index]         {             get             {                 return ((IList&lt;HighlightRule&gt;)_items)[index];             }              set             {                 ((IList&lt;HighlightRule&gt;)_items)[index] = value;             }         }          object IList.this[int index]         {             get             {                 return ((IList)_items)[index];             }              set             {                 ((IList)_items)[index] = value;             }         }          public int Count         {             get             {                 return ((IList&lt;HighlightRule&gt;)_items).Count;             }         }          public bool IsFixedSize         {             get             {                 return ((IList)_items).IsFixedSize;             }         }          public bool IsReadOnly         {             get             {                 return ((IList&lt;HighlightRule&gt;)_items).IsReadOnly;             }         }          public bool IsSynchronized         {             get             {                 return ((IList)_items).IsSynchronized;             }         }          public object SyncRoot         {             get             {                 return ((IList)_items).SyncRoot;             }         }          public event NotifyCollectionChangedEventHandler CollectionChanged;          public int Add(object value)         {             return ((IList)_items).Add(value);         }          public void Add(HighlightRule item)         {             ((IList&lt;HighlightRule&gt;)_items).Add(item);         }          public void Clear()         {             ((IList&lt;HighlightRule&gt;)_items).Clear();         }          public bool Contains(object value)         {             return ((IList)_items).Contains(value);         }          public bool Contains(HighlightRule item)         {             return ((IList&lt;HighlightRule&gt;)_items).Contains(item);         }          public void CopyTo(Array array, int index)         {             ((IList)_items).CopyTo(array, index);         }          public void CopyTo(HighlightRule[] array, int arrayIndex)         {             ((IList&lt;HighlightRule&gt;)_items).CopyTo(array, arrayIndex);         }          public ICollectionView CreateView()         {             return new CollectionView(_items);         }          public IEnumerator&lt;HighlightRule&gt; GetEnumerator()         {             return ((IList&lt;HighlightRule&gt;)_items).GetEnumerator();         }          public int IndexOf(object value)         {             return ((IList)_items).IndexOf(value);         }          public int IndexOf(HighlightRule item)         {             return ((IList&lt;HighlightRule&gt;)_items).IndexOf(item);         }          public void Insert(int index, object value)         {             ((IList)_items).Insert(index, value);         }          public void Insert(int index, HighlightRule item)         {             ((IList&lt;HighlightRule&gt;)_items).Insert(index, item);         }          public void Remove(object value)         {             ((IList)_items).Remove(value);         }          public bool Remove(HighlightRule item)         {             return ((IList&lt;HighlightRule&gt;)_items).Remove(item);         }          public void RemoveAt(int index)         {             ((IList&lt;HighlightRule&gt;)_items).RemoveAt(index);         }          IEnumerator IEnumerable.GetEnumerator()         {             return ((IList&lt;HighlightRule&gt;)_items).GetEnumerator();         }          void _items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)         {             CollectionChanged?.Invoke(this, e);         }      } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412\u043e\u0442 \u043a\u043e\u0434 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">    public class HighlightRule : DependencyObject     {         public delegate void HighlightTextChangedEventHandler(object sender, HighlightTextChangedEventArgs e);          public event HighlightTextChangedEventHandler HighlightTextChanged;          public HighlightRule()         {             Highlights = new ObservableCollection&lt;Highlight&gt;();         }          \/\/\/ &lt;summary&gt;         \/\/\/ \u0422\u0435\u043a\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u0438\u0442\u044c         \/\/\/ &lt;\/summary&gt;         public string HightlightedText         {             get { return (string)GetValue(HightlightedTextProperty); }             set { SetValue(HightlightedTextProperty, value); }         }          public static readonly DependencyProperty HightlightedTextProperty =             DependencyProperty.Register(&quot;HightlightedText&quot;, typeof(string), typeof(HighlightRule), new FrameworkPropertyMetadata(string.Empty, HighlightPropertyChanged));          public static void HighlightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)         {             var me = d as HighlightRule;             if (me != null)                 me.HighlightTextChanged?.Invoke(me, new HighlightTextChangedEventArgs((string)e.OldValue, (string)e.NewValue));         }          \/\/\/ &lt;summary&gt;         \/\/\/ \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440?          \/\/\/ &lt;\/summary&gt;         public bool IgnoreCase         {             get { return (bool)GetValue(IgnoreCaseProperty); }             set { SetValue(IgnoreCaseProperty, value); }         }          public static readonly DependencyProperty IgnoreCaseProperty =             DependencyProperty.Register(&quot;IgnoreCase&quot;, typeof(bool), typeof(HighlightRule), new PropertyMetadata(true));           \/\/\/ &lt;summary&gt;         \/\/\/ \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043e\u043a         \/\/\/ &lt;\/summary&gt;         public ObservableCollection&lt;Highlight&gt; Highlights         {             get             {                 return (ObservableCollection&lt;Highlight&gt;)GetValue(HighlightsProperty);             }             set { SetValue(HighlightsProperty, value); }         }          public static readonly DependencyProperty HighlightsProperty =             DependencyProperty.Register(&quot;Highlights&quot;, typeof(ObservableCollection&lt;Highlight&gt;), typeof(HighlightRule), new PropertyMetadata(null));       }      public class HighlightTextChangedEventArgs : EventArgs     {         public string OldText { get; }          public string NewText { get; }          public HighlightTextChangedEventArgs(string oldText,string newText)         {             OldText = oldText;             NewText = newText;         }     } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041d\u0438\u043a\u0430\u043a\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0442\u0443\u0442 \u043d\u0435\u0442 \u043f\u043e\u0447\u0442\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0435\u0437 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432.<\/p>\n<p>  \u0412\u043e\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438:<\/p>\n<pre><code class=\"cs\">    public abstract class Highlight : DependencyObject     {         public abstract void SetHighlight(Span span);          public abstract void SetHighlight(TextRange range);     } <\/code><\/pre>\n<p>  \u041c\u043d\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e \u0434\u0432\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u0438\u0442\u044c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442. \u0427\u0435\u0440\u0435\u0437 <i>Span<\/i> \u0438 \u0447\u0435\u0440\u0435\u0437 <i>TextRange<\/i>. \u041f\u043e\u043a\u0430 \u0447\u0442\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0436\u0435\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d \u0432 \u043a\u043e\u0434\u0435 \u0432 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0435 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438, \u043d\u043e \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0412\u043e\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0444\u043e\u043d\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">    public class HighlightBackgroung : Highlight     {         public override void SetHighlight(Span span)         {             Brush brush = null;             Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() =&gt;             {                 brush = Brush;             })).Wait();             span.Background = brush;         }          public override void SetHighlight(TextRange range)         {             Brush brush = null;             Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() =&gt;             {                 brush = Brush;             })).Wait();             range.ApplyPropertyValue(TextElement.BackgroundProperty, brush);         }          \/\/\/ &lt;summary&gt;         \/\/\/ \u041a\u0438\u0441\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0444\u043e\u043d\u0430         \/\/\/ &lt;\/summary&gt;         public Brush Brush         {             get             {                 return (Brush)GetValue(BrushProperty);             }             set { SetValue(BrushProperty, value); }         }          public static readonly DependencyProperty BrushProperty =             DependencyProperty.Register(&quot;Brush&quot;, typeof(Brush), typeof(HighlightBackgroung), new PropertyMetadata(Brushes.Transparent));       } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041d\u0443 \u0442\u0443\u0442 \u043d\u0435\u0447\u0435\u0433\u043e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043a\u0440\u043e\u043c\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u043a\u0440\u0443\u0442\u0438\u0442\u044c\u0441\u044f \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u0430 \u043c\u0435\u0442\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d \u043e\u0442\u043a\u0443\u0434\u0430 \u0443\u0433\u043e\u0434\u043d\u043e.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0410 \u044d\u0442\u043e \u043a\u043e\u0434 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0446\u0432\u0435\u0442\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">    public class HighlightForeground : Highlight     {         public override void SetHighlight(Span span)         {             Brush brush = null;             Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() =&gt;             {                 brush = Brush;             })).Wait();             span.Foreground = brush;         }          public override void SetHighlight(TextRange range)         {             Brush brush = null;             Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() =&gt;             {                 brush = Brush;             })).Wait();             range.ApplyPropertyValue(TextElement.ForegroundProperty, brush);         }          \/\/\/ &lt;summary&gt;         \/\/\/ \u041a\u0438\u0441\u0442\u044c \u0434\u043b\u044f \u0446\u0432\u0435\u0442\u0430 \u0442\u0435\u043a\u0441\u0442\u0430         \/\/\/ &lt;\/summary&gt;         public Brush Brush         {             get { return (Brush)GetValue(BrushProperty); }             set { SetValue(BrushProperty, value); }         }          public static readonly DependencyProperty BrushProperty =             DependencyProperty.Register(&quot;Brush&quot;, typeof(Brush), typeof(HighlightForeground), new PropertyMetadata(Brushes.Black));     } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>  \u041d\u0443 \u0432\u043e\u0442 \u043f\u043e\u0436\u0430\u043b\u0443\u0439 \u0438 \u0432\u0441\u0435. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0443\u0441\u043b\u044b\u0448\u0430\u0442\u044c \u0432\u0430\u0448\u0435 \u043c\u043d\u0435\u043d\u0438\u0435.<br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/314060\/\"> https:\/\/habrahabr.ru\/post\/314060\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442 \u0425\u0430\u0431\u0440! \u042f \u0441\u043e\u0437\u0434\u0430\u043b \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <i>TextBlock<\/i> \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u0430. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043f\u0440\u0438\u043c\u0435\u0440 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0437\u0430\u0442\u0435\u043c \u043e\u043f\u0438\u0448\u0443, \u043a\u0430\u043a \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0441\u044f.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;local:HighlightTextBlock TextWrapping=&quot;Wrap&quot;&gt;     &lt;local:HighlightTextBlock.HighlightRules&gt;         &lt;local:HighlightRule HightlightedText=&quot;{Binding Filter, Source={x:Reference thisWindow}}&quot;&gt;             &lt;local:HighlightRule.Highlights&gt;                 &lt;local:HighlightBackgroung Brush=&quot;Yellow&quot;\/&gt;                 &lt;local:HighlightForeground Brush=&quot;Black&quot;\/&gt;             &lt;\/local:HighlightRule.Highlights&gt;         &lt;\/local:HighlightRule&gt;     &lt;\/local:HighlightTextBlock.HighlightRules&gt;     &lt;Run FontWeight=&quot;Bold&quot;&gt;Property:&lt;\/Run&gt;     &lt;Run Text=&quot;{Binding Property}&quot;\/&gt; &lt;\/local:HighlightTextBlock&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<h3>\u041d\u0430\u0447\u0430\u043b\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/h3>\n<p>  \u041f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043c\u043d\u0435 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0432 <i>TextBlock<\/i>, \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u043f\u043e\u0438\u0441\u043a\u0430. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439. \u041f\u0440\u0438\u0448\u043b\u043e \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 3 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 <i>Run<\/i>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0438 \u0432 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440 \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442, \u0441\u0442\u0440\u043e\u043a\u0443 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u0441\u0432\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 (1\/2\/3). \u0421\u0440\u0435\u0434\u043d\u0438\u0439 <i>Run<\/i> \u0438\u043c\u0435\u0435\u0442 <i>Backgroung<\/i>. <\/p>\n<p>  \u041d\u0435 \u0443\u0441\u043f\u0435\u043b \u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u0430\u043a \u043f\u0440\u0438\u0448\u043b\u0430 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043c\u044b\u0441\u043b\u044c, \u0447\u0442\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e. \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>  \u0411\u044b\u043b\u0430 \u0435\u0449\u0435 \u043c\u044b\u0441\u043b\u044c \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c <i>Xaml<\/i> \u00ab\u043d\u0430 \u043b\u0435\u0442\u0443\u00bb, \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <i>XamlReader<\/i> \u0438 \u043a\u0438\u0434\u0430\u0442\u044c \u0432 <i>TextBlock<\/i>. \u041d\u043e \u044d\u0442\u0430 \u043c\u044b\u0441\u043b\u044c \u0442\u043e\u0436\u0435 \u0441\u0440\u0430\u0437\u0443 \u043e\u0442\u0432\u0430\u043b\u0438\u043b\u0430\u0441\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u043f\u0430\u0445\u0438\u0432\u0430\u0435\u0442.<\/p>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 (\u0438 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439) \u0438\u0434\u0435\u0435\u0439 \u0441\u0442\u0430\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0438 \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u0435\u0435 \u043a <i>TextBlock<\/i>. \u0422\u0443\u0442 2 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430: \u0441\u0432\u043e\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u0441 \u0431\u043b\u044d\u043a\u0434\u0436\u0435\u043a\u043e\u043c \u0438 \u0434\u0435\u0432\u043e\u0447\u043a\u0430\u043c\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <i>TextBlock<\/i> \u0438\u043b\u0438 <i>AttachedProperty<\/i>. \u041f\u043e\u0441\u043b\u0435 \u043d\u0435\u0434\u043e\u043b\u0433\u0438\u0445 \u0440\u0430\u0437\u0434\u0443\u043c\u0438\u0439, \u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0432\u0441\u0435 \u0442\u0430\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0430\u043c\u043e\u0433\u043e <i>TextBlock<\/i>, \u0430 \u0440\u0430\u0437\u0440\u0443\u043b\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u043e\u0449\u0435, \u0435\u0441\u043b\u0438 \u043e\u0442 \u043d\u0435\u0433\u043e \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-280231","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/280231","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=280231"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/280231\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=280231"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=280231"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=280231"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}