none
RichTextBox里面的某一段字符串用控件来替换,怎么做。 RRS feed

  • 问题

  • 假如我现在有一个RichTextBox,RichTextBox的内容为 AAAAAABBBBBCCCCC<image source="">

    我想把BBBBB替换成一个控件,譬如Button,Label 要怎么做呢?



    • 已编辑 dane- 2012年4月5日 1:42
    2012年4月4日 13:25

答案

  • 你要理解WPF中RichTextBox中的内容是FlowDocument, 不是一般的纯文本结构,也不是我们WPF的Visual/Content结构,而是流文档结构,它里面有着下面的文档中描述的一些成员:http://msdn.microsoft.com/zh-cn/library/aa970909.aspx 

    我们的Text在FlowDocument中也是以Run形式存在。 我们要替换成一个控件,就必须用到 InlineUIContainer 或者 BlockUIContainer 。 具体怎么操作和使用,希望你能够完整地去学习和看一下http://msdn.microsoft.com/zh-cn/library/ms754030.aspx 里面的How-to的内容。我这里给你一个简单的例子:

      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="auto"/>
          <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="Replace Text in FlowDocument" Click="Button_Click"/>
        <RichTextBox x:Name="rtb" Grid.Row="1">
          <FlowDocument>
            <Paragraph>
              <Run>Hello WPF, hello world!</Run>
            </Paragraph>
          </FlowDocument>
        </RichTextBox>
      </Grid>

    C#:

      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          FlowDocument doc = rtb.Document as FlowDocument;
          TextRange textrange = DocumentHelper.FindText(doc.ContentStart, doc.ContentEnd, "Hello", FindFlags.None, CultureInfo.CurrentCulture);
          InlineUIContainer container = new InlineUIContainer(new TextBlock() { Text = "Hello", Foreground = Brushes.Red });
          textrange.End.Paragraph.Inlines.Add(container);
          textrange.Text = "";
        }
      }
    
    
      [Flags]
      public enum FindFlags
      {
        FindInReverse = 2,
        FindWholeWordsOnly = 4,
        MatchAlefHamza = 0x20,
        MatchCase = 1,
        MatchDiacritics = 8,
        MatchKashida = 0x10,
        None = 0
      }
    
    
      public static class DocumentHelper
      {
        private static MethodInfo findMethod = null;
    
        public static TextRange FindText(TextPointer findContainerStartPosition,
          TextPointer findContainerEndPosition,
          String input, FindFlags flags,
          CultureInfo cultureInfo)
        {
          TextRange textRange = null;
          if (findContainerStartPosition.CompareTo(findContainerEndPosition) < 0)
          {
            try
            {
              if (findMethod == null)
              {
                findMethod = typeof(FrameworkElement).Assembly.GetType("System.Windows.Documents.TextFindEngine").
                       GetMethod("Find", BindingFlags.Static | BindingFlags.Public);
              }
              Object result = findMethod.Invoke(null, new Object[] { findContainerStartPosition, 
                        findContainerEndPosition, 
                        input, flags, cultureInfo });
              textRange = result as TextRange;
            }
            catch (ApplicationException)
            {
              textRange = null;
            }
          }
    
          return textRange;
        }
      }

    P.S. @MainTao, 你提供的链接是Silverlight的 , (v=vs.95)。 :)


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    • 已标记为答案 dane- 2012年4月5日 9:47
    2012年4月5日 6:15
    版主

全部回复

  • 我意思是RichTextBox里面的内容
    2012年4月5日 1:43
  • 你要理解WPF中RichTextBox中的内容是FlowDocument, 不是一般的纯文本结构,也不是我们WPF的Visual/Content结构,而是流文档结构,它里面有着下面的文档中描述的一些成员:http://msdn.microsoft.com/zh-cn/library/aa970909.aspx 

    我们的Text在FlowDocument中也是以Run形式存在。 我们要替换成一个控件,就必须用到 InlineUIContainer 或者 BlockUIContainer 。 具体怎么操作和使用,希望你能够完整地去学习和看一下http://msdn.microsoft.com/zh-cn/library/ms754030.aspx 里面的How-to的内容。我这里给你一个简单的例子:

      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="auto"/>
          <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="Replace Text in FlowDocument" Click="Button_Click"/>
        <RichTextBox x:Name="rtb" Grid.Row="1">
          <FlowDocument>
            <Paragraph>
              <Run>Hello WPF, hello world!</Run>
            </Paragraph>
          </FlowDocument>
        </RichTextBox>
      </Grid>

    C#:

      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          FlowDocument doc = rtb.Document as FlowDocument;
          TextRange textrange = DocumentHelper.FindText(doc.ContentStart, doc.ContentEnd, "Hello", FindFlags.None, CultureInfo.CurrentCulture);
          InlineUIContainer container = new InlineUIContainer(new TextBlock() { Text = "Hello", Foreground = Brushes.Red });
          textrange.End.Paragraph.Inlines.Add(container);
          textrange.Text = "";
        }
      }
    
    
      [Flags]
      public enum FindFlags
      {
        FindInReverse = 2,
        FindWholeWordsOnly = 4,
        MatchAlefHamza = 0x20,
        MatchCase = 1,
        MatchDiacritics = 8,
        MatchKashida = 0x10,
        None = 0
      }
    
    
      public static class DocumentHelper
      {
        private static MethodInfo findMethod = null;
    
        public static TextRange FindText(TextPointer findContainerStartPosition,
          TextPointer findContainerEndPosition,
          String input, FindFlags flags,
          CultureInfo cultureInfo)
        {
          TextRange textRange = null;
          if (findContainerStartPosition.CompareTo(findContainerEndPosition) < 0)
          {
            try
            {
              if (findMethod == null)
              {
                findMethod = typeof(FrameworkElement).Assembly.GetType("System.Windows.Documents.TextFindEngine").
                       GetMethod("Find", BindingFlags.Static | BindingFlags.Public);
              }
              Object result = findMethod.Invoke(null, new Object[] { findContainerStartPosition, 
                        findContainerEndPosition, 
                        input, flags, cultureInfo });
              textRange = result as TextRange;
            }
            catch (ApplicationException)
            {
              textRange = null;
            }
          }
    
          return textRange;
        }
      }

    P.S. @MainTao, 你提供的链接是Silverlight的 , (v=vs.95)。 :)


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    • 已标记为答案 dane- 2012年4月5日 9:47
    2012年4月5日 6:15
    版主
  • 谢谢你的答案, 你的答案给我很大的帮助,我已经解决了我要实现的功能。非常感谢。
    2012年4月5日 9:48