在 TextBlock 的绑定文本中更改子字符串的颜色 [英] Changing the colors of substrings within the bound Text of a TextBlock

查看:33
本文介绍了在 TextBlock 的绑定文本中更改子字符串的颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一些属性绑定到我的 TextBlock:

I am binding some property into my TextBlock:

<TextBlock 
    Text="{Binding Status}" 
    Foreground="{Binding RealTimeStatus,Converter={my:RealTimeStatusToColorConverter}}" 
    />

Status 是简单的文本,RealTimeStatusenum.对于每个 enum 值,我正在更改我的 TextBlock Foreground 颜色.

Status is simple text and RealTimeStatus is enum. For each enum value I am changing my TextBlock Foreground color.

有时我的 Status 消息包含数字.该消息根据 enum 值获得适当的颜色,但我想知道是否可以更改此消息中数字的颜色,这样数字的颜色将与文本的其余部分不同.

Sometimes my Status message contains numbers. That message gets the appropriate color according to the enum value, but I wonder if I can change the colors of the numbers inside this message, so the numbers will get different color from the rest of the text.

编辑.

XAML

<TextBlock my:TextBlockExt.XAMLText="{Binding Status, Converter={my:RealTimeStatusToColorConverter}}"/>

转换器:

public class RealTimeStatusToColorConverter : MarkupExtension, IValueConverter
{
    // One way converter from enum RealTimeStatus to color. 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is RealTimeStatus && targetType == typeof(Brush))
        {
            switch ((RealTimeStatus)value)
            {
                case RealTimeStatus.Cancel:
                case RealTimeStatus.Stopped:
                    return Brushes.Red;

                case RealTimeStatus.Done:
                    return Brushes.White;

                case RealTimeStatus.PacketDelay:
                    return Brushes.Salmon;

                default:
                    break;
            }
        }

        return null;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public RealTimeStatusToColorConverter()
    {
    }

    // MarkupExtension implementation
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}

推荐答案

这里有一个附加属性,可以将任意文本解析为 XAML TextBlock 内容,包括 RunSpanBold 等.这具有普遍有用的优点.

Here's an attached property which parses arbitrary text as XAML TextBlock content, including Run, Span, Bold, etc. This has the advantage of being generally useful.

我建议您编写一个 ValueConverter 用适当的标记替换 Status 文本中的数字,这样当你给它这个文本时......

I recommend you write a ValueConverter which replaces the numbers in your Status text with appropriate markup, such that when you give it this text...

错误编号 34:猴子小猫没有奶油冻.

Error number 34: No custard for monkey kitty.

...它将把它转换成这个文本:

...it would convert that into this text:

错误编号 <Span Foreground="Red">34</Span>:猴子小猫没有奶油冻.

Error number <Span Foreground="Red">34</Span>: No custard for monkey kitty.

您已经知道如何进行值转换器,使用正则表达式进行文本替换是完全不同的主题.

You already know how to do value converters, and text substitution with regular expressions is a different subject entirely.

XAML 用法:

<TextBlock
    soex:TextBlockExt.XAMLText={Binding Status, Converter={my:redNumberConverter}}"
    />

如果是我,我会疯狂地将颜色设为 ConverterParameter.

If it were me I'd go hog wild and make the color a ConverterParameter.

这是该附加属性的 C#:

Here's the C# for that attached property:

using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace StackOverflow.Examples
{
    public static class TextBlockExt
    {
        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 from ViewModel 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(TextBlockExt),
                                                 new PropertyMetadata("", XAMLText_PropertyChanged));

        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(GenerateStreamFromString(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 Ability.CAPS.WPF.UIExtensions.TextBlock.XAMLText_PropertyChanged: {0}", ex.Message));
                    throw;
                }
            }
        }

        public static Stream GenerateStreamFromString(string s)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(s);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }
    }
}

这篇关于在 TextBlock 的绑定文本中更改子字符串的颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆