【问题标题】:Changing the colors of substrings within the bound Text of a TextBlock在 TextBlock 的绑定文本中更改子字符串的颜色
【发布时间】:2015-12-18 15:34:18
【问题描述】:

我将一些属性绑定到我的TextBlock

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

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

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

编辑。

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;
    }
}

【问题讨论】:

  • 这很复杂。一种方法是将您的状态消息分成多条消息,其中数字内容位于单独的视图模型属性中。但这太可怕了。更纯粹的 MVVM 方法是为 Status 编写另一个 ValueConverter,这将解析消息文本并动态创建具有适当属性的多个 XAML Run 实例。但这是相当多的工作。
  • 听起来不错,我可以提供代码示例吗? (我是新开发者...)

标签: wpf styles textblock


【解决方案1】:

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

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

错误号 34:猴子小猫没有蛋奶冻。

...它会将其转换为以下文本:

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

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

XAML 用法:

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

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

这是该附加属性的 C#:

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;
        }
    }
}

【讨论】:

  • 非常感谢您的回答,您可以发布 redNumberConverter 代码吗?我认为这个 TextBlockExt 类的用法也缺少一些东西。
  • @davidhol 你在使用上有什么问题?您编写的 ValueConverter 有什么问题?这应该是微不足道的。
  • 因为我是新开发人员并且对 WPF 几乎不熟悉,所以这个转换器对我来说并不是微不足道的。
  • @davidhol SO 的习惯是请人们帮助您完成您遇到的任务。当您甚至不愿意自己编写代码时,这里的人就会变得毫无帮助。
  • 我不明白什么是错误编号 34:猴子小猫没有蛋奶冻。意思是。
【解决方案2】:

您可以使用Span,尽管设置 TextBlock 需要更多的工作。

看看this page,我发现它相当简单但很全面,我从中提取了这个sn-p:

        <TextBlock Margin="10" TextWrapping="Wrap">
                This <Span FontWeight="Bold">is</Span> a
                <Span Background="Silver" Foreground="Maroon">TextBlock</Span>
                with <Span TextDecorations="Underline">several</Span>
                <Span FontStyle="Italic">Span</Span> elements,
                <Span Foreground="Blue">
                        using a <Bold>variety</Bold> of <Italic>styles</Italic>
                </Span>.
        </TextBlock>

【讨论】:

    猜你喜欢
    • 2014-02-02
    • 2014-07-22
    • 2017-10-30
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    相关资源
    最近更新 更多