You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不清空Inlines的情况下解决DataGridTemplateColumn中TextBlock重复数据问题

问题:DataGrid中TextBlockFormatter导致文本重复的解决方法

我正在使用TextBlockFormatter对DataGridTemplateColumn中的TextBlock文本进行特定部分高亮处理,但当DataGrid加载约12行后,TextBlock的Inlines开始出现数据重复现象。目前注释掉了textblock.Inlines.Clear();,想知道有没有无需清空Inlines就能避免重复的方法?

相关代码

DataGridTemplateColumn代码

<DataGridTemplateColumn Width="2.5*" Header="{DynamicResource TEXT}" >
    <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
             <TextBlock base:TextBlockFormatter.FormattedText="{Binding prettyText}" TextWrapping="Wrap" />
         </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

TextBlockFormatter代码

public class TextBlockFormatter
{
    public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
        "FormattedText",
        typeof(string),
        typeof(RequestTextBlockFormatter), // 注意:此处OwnerType错误,应为typeof(TextBlockFormatter)
        new FrameworkPropertyMetadata(null, OnFormattedTextChanged));

    public static void SetFormattedText(UIElement element, string value)
    {
        element.SetValue(FormattedTextProperty, value);
    }

    private static void OnFormattedTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        TextBlock textblock = (TextBlock)d;
        //textblock.Inlines.Clear();
        List<SplitText> splitTexts = TranslationActions.getSplitetTextFromString(e.NewValue.ToString());

        Color textColor = SomeColor;

        foreach (SplitText splitText in splitTexts)
        {
            FontWeight fontWeight = Convert.ToBoolean(splitText.isBold) ? FontWeights.Bold : FontWeights.Normal;
            FontStyle fontStyle = splitText.isItalic ? FontStyles.Italic : FontStyles.Normal;
                
            if(splitText.isColor) 
            {
                textblock.Inlines.Add(new Run(splitText.text){Foreground = new SolidColorBrush(textColor), FontWeight = fontWeight,FontStyle = fontStyle });
            }
            else
            {
                textblock.Inlines.Add(new Run(splitText.text){FontWeight = fontWeight,FontStyle = fontStyle });
            }
       }
    }
}

解决方法

文本重复是DataGrid的UI虚拟化导致的控件复用问题:滚动加载新行时,旧行的TextBlock会被重新绑定到新数据,但未清除的旧Inlines会和新内容叠加,最终出现重复。

不存在完全不清空Inlines就能避免重复的方法,但可以通过替换整个Inlines集合的方式,避免手动调用Clear(),同时更高效地更新内容:

修改OnFormattedTextChanged方法如下:

private static void OnFormattedTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    TextBlock textblock = (TextBlock)d;
    // 创建新集合存放内容
    var newInlines = new InlineCollection();
    
    string newValue = e.NewValue?.ToString();
    if (string.IsNullOrEmpty(newValue))
    {
        textblock.Inlines = newInlines;
        return;
    }

    List<SplitText> splitTexts = TranslationActions.getSplitetTextFromString(newValue);
    Color textColor = SomeColor;

    foreach (SplitText splitText in splitTexts)
    {
        FontWeight fontWeight = splitText.isBold ? FontWeights.Bold : FontWeights.Normal;
        FontStyle fontStyle = splitText.isItalic ? FontStyles.Italic : FontStyles.Normal;
        
        var run = new Run(splitText.text)
        {
            FontWeight = fontWeight,
            FontStyle = fontStyle
        };
        
        if (splitText.isColor)
        {
            run.Foreground = new SolidColorBrush(textColor);
        }
        
        newInlines.Add(run);
    }

    // 直接替换整个Inlines集合,无需手动清空
    textblock.Inlines = newInlines;
}

同时必须修正附加属性注册时的OwnerType错误:

public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
    "FormattedText",
    typeof(string),
    typeof(TextBlockFormatter), // 修正为当前类的Type
    new FrameworkPropertyMetadata(null, OnFormattedTextChanged));

内容的提问来源于stack exchange,提问作者atnaf99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 10:28:14