首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态格式化的TextBlock

动态格式化的TextBlock
EN

Stack Overflow用户
提问于 2014-01-16 22:48:36
回答 3查看 3.1K关注 0票数 3

我想动态地格式化TextBlock中的特定单词,因为它绑定到我的对象。我正在考虑使用Converter,但是使用下面的解决方案,只将标签直接添加到文本中(而不是显示格式化的文本)。

代码语言:javascript
复制
public class TextBlockFormatter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        string regexp = @"\p{L}+#\d{4}";

        if (value != null) {
            return Regex.Replace(value as string, regexp, m => string.Format("<Bold>{0}</Bold>", m.Value));
        } 

        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
EN

回答 3

Stack Overflow用户

发布于 2014-01-17 00:15:24

这不是在试图回答这个问题...它是对问题评论中的问题的回答的演示。

Yes @Blam,你可以格式化单个单词,甚至TextBlock中的字符...您需要使用Run (或者您可以用TextBlock替换Run )类。无论采用哪种方法,您都可以将数据绑定到这两种方法的Text属性:

代码语言:javascript
复制
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
    <Run Text="This" FontWeight="Bold" Foreground="Red" />
    <Run Text="text" FontSize="18" />
    <Run Text="is" FontStyle="Italic" />
    <Run Text="in" FontWeight="SemiBold" Background="LightGreen" />
    <Run Text="one" FontFamily="Candara" FontSize="20" />
    <Run Text="TextBlock" FontWeight="Bold" Foreground="Blue" />
</TextBlock>

更新>>>

关于这个问题,我认为可以在DataTemplate中使用这些Run元素,并从数据中生成它们……这种情况下的数据必须是具有(显然) Text属性的类,但也必须是格式化属性,您可以使用这些属性将数据绑定到Run样式属性。

不过,这会很尴尬,因为TextBlock没有ItemsSource属性,您可以将word类的集合绑定到...也许你可以使用Converter来处理这一部分。只是在这里大声思考..。我现在要停下来了。

更新>>>

@KrzysztofBzowski,不幸的是,TextBlock.Inlines属性不是一个DependencyProperty,所以你不能将数据绑定到它。然而,这让我开始思考,我又做了一次搜索,找到了关于Jevgeni Tsaikin的.NET实验室的Binding text containing tags to TextBlock inlines using attached property in Silverlight for Windows Phone 7文章。

它需要你声明一个附加的属性和一个Converter,但是它看起来很有希望……试一试。别担心这是为了Silverlight..。如果它能在Silverlight中工作,那么它也能在WPF中工作。

票数 3
EN

Stack Overflow用户

发布于 2014-11-05 19:23:36

我最近不得不解决这个问题,我可以通过为TextBlocks编写一个混合行为来解决这个问题。

它可以在XAML中使用一系列突出显示元素来声明,您可以在其中指定要突出显示的文本、所需文本的颜色和字体粗细(可以根据需要轻松添加更多格式属性)。

它的工作原理是循环遍历所需的亮点,扫描从TextBlock.ContentStart TextPointer开始的每个短语的TextBlock。一旦找到短语,它就可以构建一个TextRange,其中可以应用格式化选项。

如果TextBlock Text属性也是数据绑定的,那么它应该可以工作,因为我附加到了bindings Target updated事件。

有关行为代码和XAML示例,请参阅下面的内容

代码语言:javascript
复制
public class TextBlockHighlightBehaviour : Behavior<TextBlock>
{
    private EventHandler<DataTransferEventArgs> targetUpdatedHandler;
    public List<Highlight> Highlights { get; set; }

    public TextBlockHighlightBehaviour()
    {
        this.Highlights = new List<Highlight>();
    }

    #region Behaviour Overrides

    protected override void OnAttached()
    {
        base.OnAttached();
        targetUpdatedHandler = new EventHandler<DataTransferEventArgs>(TextBlockBindingUpdated);
        Binding.AddTargetUpdatedHandler(this.AssociatedObject, targetUpdatedHandler);

        // Run the initial behaviour logic
        HighlightTextBlock(this.AssociatedObject);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        Binding.RemoveTargetUpdatedHandler(this.AssociatedObject, targetUpdatedHandler);
    }

    #endregion

    #region Private Methods

    private void TextBlockBindingUpdated(object sender, DataTransferEventArgs e)
    {
        var textBlock = e.TargetObject as TextBlock;
        if (textBlock == null)
            return;

        if(e.Property.Name == "Text")
            HighlightTextBlock(textBlock);
    }

    private void HighlightTextBlock(TextBlock textBlock)
    {
        foreach (var highlight in this.Highlights)
        {
            foreach (var range in FindAllPhrases(textBlock, highlight.Text))
            {
                if (highlight.Foreground != null)
                    range.ApplyPropertyValue(TextElement.ForegroundProperty, highlight.Foreground);

                if(highlight.FontWeight != null)
                    range.ApplyPropertyValue(TextElement.FontWeightProperty, highlight.FontWeight);
            }
        }
    }

    private List<TextRange> FindAllPhrases(TextBlock textBlock, string phrase)
    {
        var result = new List<TextRange>();
        var position = textBlock.ContentStart;

        while (position != null)
        {
            var range = FindPhrase(position, phrase);
            if (range != null)
            {
                result.Add(range);
                position = range.End;
            }
            else
                position = null;
        }

        return result;
    }

    // This method will search for a specified phrase (string) starting at a specified position.
    private TextRange FindPhrase(TextPointer position, string phrase)
    {
        while (position != null)
        {
            if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
            {
                string textRun = position.GetTextInRun(LogicalDirection.Forward);

                // Find the starting index of any substring that matches "phrase".
                int indexInRun = textRun.IndexOf(phrase);
                if (indexInRun >= 0)
                {
                    TextPointer start = position.GetPositionAtOffset(indexInRun);
                    TextPointer end = start.GetPositionAtOffset(phrase.Length);
                    return new TextRange(start, end);
                }
            }

            position = position.GetNextContextPosition(LogicalDirection.Forward);
        }

        // position will be null if "phrase" is not found.
        return null;
    }

    #endregion
}

public class Highlight
{
    public string Text { get; set; }
    public Brush Foreground { get; set; }
    public FontWeight FontWeight { get; set; }
}

XAML中的示例用法:

代码语言:javascript
复制
<TextBlock Text="Here is some text">
   <i:Interaction.Behaviors>
      <behaviours:TextBlockHighlightBehaviour>
         <behaviours:TextBlockHighlightBehaviour.Highlights>
            <behaviours:Highlight Text="some" Foreground="{StaticResource GreenBrush}" FontWeight="Bold" />
            </behaviours:TextBlockHighlightBehaviour.Highlights>
         </behaviours:TextBlockHighlightBehaviour>
   </i:Interaction.Behaviors>
</TextBlock>

您需要导入Blend interactivity名称空间和行为的名称空间:

代码语言:javascript
复制
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:behaviours="clr-namespace:YourProject.Behviours"
票数 2
EN

Stack Overflow用户

发布于 2018-05-19 00:55:39

我有一个类似的用例,需要用RichTextBox构建一个文本编辑器。但是,所有文本格式的更改:字体、颜色、斜体、粗体必须动态反映在TextBlock上。我发现很少有文章指向Textblock.inlines.Add(),它似乎很有帮助,但一次只允许一个更改或附加到现有文本。

然而,可以利用要格式化的现有文本的Textblock.inlines.ElementAt(index )来将期望的文本格式应用于位于该索引处的文本。下面是我解决这个问题的伪方法。我希望这能有所帮助:

代码语言:javascript
复制
For RichTextBox:    
selectedText.ApplyPropertyValue(TextElement.FontFamilyProperty, cbFontFamily.SelectedValue.ToString());

但是,要使Textblock格式化起作用,我必须使用Run run = new Run()概念,它允许并使用:

代码语言:javascript
复制
Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString(SelectedColorText))
FontFamily = new FontFamily(cbFontFamily.SelectedValue.ToString())
FontStyle = FontStyles.Italic
TextDecorations = TextDecorations.Underline
TextDecorations = TextDecorations.Strikethrough
FontWeight = (FontWeight)new FontWeightConverter().ConvertFromString(cbFontWeightBox.SelectedItem.ToString())

此外,我创建了一个具有各种字段和构造函数的类。我还创建了一个基于自定义的类字典来捕获RichTextbbox中所做的所有更改。最后,我通过一个forloop应用了字典中所有捕获的信息。

代码语言:javascript
复制
TextBlock.Inlines.ElementAt(mItemIndex).Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString(dictionaryItem.Value._applyColor.ToString()));

TextBlock.Inlines.ElementAt(mItemIndex).FontFamily = new FontFamily(ftItem.Value._applyFontFamily.ToString());

TextBlock.Inlines.ElementAt(mItemIndex).FontStyle = FontStyles.Italic;

TextBlock.Inlines.ElementAt(mItemIndex).TextDecorations = TextDecorations.Underline;

TextBlock.Inlines.ElementAt(mItemIndex).TextDecorations = TextDecorations.Strikethrough;

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21165012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档