如何在不清空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
相关产品推荐
相关产品推荐

