2016-10-17 2 views
0

그래서 긴 줄의 텍스트에 바인딩되는 WPF RichTextBox이 있습니다.RichTextBox 내에서 텍스트의 부분 스타일을 동적으로 지정하십시오.

내가 원하는 것은 두 개의 TextPointer 객체 집합을 사용하기 때문에 주어진 시점에 두 포인터 사이의 텍스트에 적용된 스타일이 있습니다. (예를 들어, 텍스트의 배경/전경색을 변경하십시오.) 사용자가 선택 항목을 이동할 때. 텍스트가 더 이상 두 포인터 사이에 없으면 스타일을 원래 스타일로 재설정해야합니다.

원하는 동작은 예를 들어 웹 사이트의 텍스트를 강조 표시하거나 선택하기 위해 클릭하고 끌 수있는 것과 비슷합니다 (동일하지는 않지만). 클릭 및 드래그 대신 (사용자가이를 수행 할 수 없어야합니다. 끝점을 프로그래밍 방식으로 결정해야합니다.)

나는 그것을 수행하는 방법을 알아낼 수 없습니다. 나는 내가 필요한 스타일을 <Run></Run>에 적용 할 수 있다는 것을 알고 있지만 컨트롤 내에서 텍스트의 특정 부분 문자열을 가져 와서 프로그래밍 방식으로 Run 태그를 적용 (제거)하는 방법을 알아낼 수 없습니다.

이상적인 솔루션은 select 메서드로 적용된 스타일을 변경하는 것입니다. 나는 (마우스를 사용하지 않고) 사용자로부터 선택을 해제하는 것이 가능하고 프로그래밍 방식의 선택을 여전히 사용할 수 있는지 확실치 않아이 일을 조금 조심스럽게 생각한다.

+0

은 이미지와 설명하려고합니다. RTB에서 이미 텍스트 선택을 이동하는 것이 가능합니다. – AnjumSKhan

답변

1

업데이트 : 원래는 RichTextBox이 아니라 TextBlock에 대해 이야기하고 있었던 것 같습니다. 솔루션에 RichTextBox이 절대적으로 필요한 경우 어딘가에서 유용한 RTF 파서를 찾아야합니다.

할 수있는 한 가지는 RTF 또는 HTML 컨트롤을 사용하는 것입니다.

또는 다음 코드를 사용하여 머리에 총을 썼습니다 (실제로 내가 할 수 있는지 알아보기 위해 썼습니다). 아마 MVVM에 대한 죄이지만, 눈을 감고 <Bold> 태그 등은 XAML이 아닌 임의의 마크 업 언어 일뿐입니다.

아무튼 : 서식을 지정할 범위가 변경되면 FormattedText 속성을 업데이트하고 PropertyChanged을 올립니다.

C#

namespace HollowEarth.AttachedProperties 
{ 
    public static class TextProperties 
    { 
     #region TextProperties.XAMLText Attached Property 
     public static String GetXAMLText(TextBlock obj) 
     { 
      return (String)obj.GetValue(XAMLTextProperty); 
     } 

     public static void SetXAMLText(TextBlock obj, String value) 
     { 
      obj.SetValue(XAMLTextProperty, value); 
     } 

     /// <summary> 
     /// Convert raw string into formatted text in a TextBlock: 
     /// 
     /// @"This <Bold>is a test <Italic>of the</Italic></Bold> text." 
     /// 
     /// Text will be parsed as XAML TextBlock content. 
     /// 
     /// See WPF TextBlock documentation for full formatting. It supports spans and all kinds of things. 
     /// 
     /// </summary> 
     public static readonly DependencyProperty XAMLTextProperty = 
      DependencyProperty.RegisterAttached("XAMLText", typeof(String), typeof(TextProperties), 
               new PropertyMetadata("", XAMLText_PropertyChanged)); 

     // I don't recall why this was necessary; maybe it wasn't. 
     public static Stream GetStream(String s) 
     { 
      MemoryStream stream = new MemoryStream(); 
      StreamWriter writer = new StreamWriter(stream); 

      writer.Write(s); 
      writer.Flush(); 
      stream.Position = 0; 

      return stream; 
     } 

     private static void XAMLText_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      if (d is TextBlock) 
      { 
       var ctl = d as TextBlock; 

       try 
       { 
        // XAML needs a containing tag with a default namespace. We're parsing 
        // TextBlock content, so make the parent a TextBlock to keep the schema happy. 
        // TODO: If you want any content not in the default schema, you're out of luck. 
        var strText = String.Format(@"<TextBlock xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">{0}</TextBlock>", e.NewValue); 

        TextBlock parsedContent = System.Windows.Markup.XamlReader.Load(GetStream(strText)) as TextBlock; 

        // The Inlines collection contains the structured XAML content of a TextBlock 
        ctl.Inlines.Clear(); 

        // UI elements are removed from the source collection when the new parent 
        // acquires them, so pass in a copy of the collection to iterate over. 
        ctl.Inlines.AddRange(parsedContent.Inlines.ToList()); 
       } 
       catch (Exception ex) 
       { 
        System.Diagnostics.Trace.WriteLine(String.Format("Error in HollowEarth.AttachedProperties.TextProperties.XAMLText_PropertyChanged: {0}", ex.Message)); 
        throw; 
       } 
      } 
     } 
     #endregion TextProperties.XAMLText Attached Property 
    } 
} 

다른 C#을

// This `SpanStyle` resource is in scope for the `TextBlock` I attached 
// the property to. This works for me with a number of properties, but 
// it's not changing the foreground. If I apply the same style conventionally 
// to a Span in the real XAML, the foreground color is set. Very curious. 
// StaticResource threw an exception for me. I couldn't figure out what to give 
// XamlReader.Load for a ParserContext. 
FormattedText = "Text <Span Style=\"{DynamicResource SpanStyle}\">Span Text</Span>"; 

XAML

<TextBlock 
     xmlns:heap="clr-namespace:HollowEarth.AttachedProperties" 
     heap:TextProperties.XAMLText="{Binding FormattedText}" 
     /> 

    <TextBlock 
     xmlns:heap="clr-namespace:HollowEarth.AttachedProperties" 
     heap:TextProperties.XAMLText="This is &lt;Italic Foreground=&quot;Red&quot;&gt;italic and &lt;Bold&gt;bolded&lt;/Bold&gt;&lt;/Italic&gt; text" 
     /> 
+0

그래, 필자는 본질적으로'TextBlock'을'RichTextBox'로 바꾸는 방법을 묻고 있다는 것을 깨달았다. 그에 따라 내 질문을 편집하여 온 전성을 존중합니다. – Airhead

+1

@Airhead 선량이 과대 평가되었습니다. 내 대답은'TextBlock'으로 그것을합니다. –

관련 문제