ОБНОВЛЕНИЕ:
Я постарался создать как можно более минимальный пример. В более сложных сценариях вам придется расширить это. Вот как это выглядит:

это соответствующий xaml:
<AdornerDecorator>
<StackPanel>
<TextBlock>
<Run>this is normal Text</Run><LineBreak/>
<Run local:DiagonalStrikeThroughAdorner.StrikeThroughBrush="Red">Some text with diagonal decoration</Run><LineBreak/>
<Run>more normal text yeah</Run>
</TextBlock>
<FlowDocumentScrollViewer>
<FlowDocument>
<Paragraph>
<Run>this is normal Text</Run>
<LineBreak/>
<Run local:DiagonalStrikeThroughAdorner.StrikeThroughBrush="Red">Some text with diagonal decoration</Run>
<LineBreak/>
<Run>more normal text yeah</Run>
</Paragraph>
</FlowDocument>
</FlowDocumentScrollViewer>
</StackPanel>
</AdornerDecorator>
и это код:
public class DiagonalStrikeThroughAdorner : Adorner
{
private readonly Inline _inline;
private readonly Pen _pen;
public DiagonalStrikeThroughAdorner(UIElement adornedElement, Inline inline, Brush brush) : base(adornedElement)
{
_inline = inline;
_pen = new Pen(brush, 2);
}
protected override void OnRender(DrawingContext drawingContext)
{
if(!(_inline.ContentStart.HasValidLayout && _inline.ContentEnd.HasValidLayout))
return;
var startrect = _inline.ContentStart.GetCharacterRect(LogicalDirection.Forward);
var endrect = _inline.ContentEnd.GetCharacterRect(LogicalDirection.Backward);
drawingContext.DrawLine(_pen,startrect.BottomLeft,endrect.TopRight);
}
public static Brush GetStrikeThroughBrush(DependencyObject obj)
{
return (Brush)obj.GetValue(StrikeThroughBrushProperty);
}
public static void SetStrikeThroughBrush(DependencyObject obj, Brush value)
{
obj.SetValue(StrikeThroughBrushProperty, value);
}
public static readonly DependencyProperty StrikeThroughBrushProperty =
DependencyProperty.RegisterAttached("StrikeThroughBrush", typeof(Brush), typeof(DiagonalStrikeThroughAdorner), new UIPropertyMetadata((o, args) =>
{
if(!(o is TextElement)) return;
var parent = ((TextElement)o).Parent;
while (parent is FrameworkContentElement)
parent = ((FrameworkContentElement) parent).Parent;
if (parent == null || !(parent is Visual)) return;
var adornerLayer = AdornerLayer.GetAdornerLayer((Visual) parent);
if(adornerLayer == null) return;
adornerLayer.Add(new DiagonalStrikeThroughAdorner((UIElement) parent,o as Inline,(Brush) args.NewValue));
}));
}
развлекайся!
исходное сообщение:
это вообще довольно тяжело. Мне удалось прикрепить украшение к определенным элементам в потоковых документах, но есть много крайних случаев, которые следует учитывать. например: что должно произойти, если этот Inline обернут? далее: если этот потоковый документ находится в расширенном текстовом поле, его внутренности продолжают переупорядочивать прогоны (объединяя или разделяя их), что в значительной степени все портит. вы должны настроить вещи тщательно.
Пожалуйста, расскажите подробнее о том, где будет находиться эта строчка. Внутри FlowdocumentScrollviewer? Или текстовый блок? Или Richtextbox? Так как вам необходимо прикрепить элемент оформления к управляющему элементу FrameworkElement (как вы, наверное, уже заметили, элемент оформления нельзя присоединить непосредственно к элементу FrameworkContentElement), нам нужно знать, где находится встроенный элемент.
Я опишу общий путь, как это сделать: создайте прикрепленное свойство, которое создаст украшение. присоединенное свойство устанавливается на строку, которая будет украшена. adorner хранит ссылку на встроенный элемент и прикрепляется к управляющему элементу FrameworkElement. подпишитесь на layoutupdated на этом элементе фреймворка и сделайте InvalidateVisual на Adorner. Декораторы OnRender рисуют линию с координатами в зависимости от Inlines ContentStart и ContentEnd GetCharacterRect а> прямоугольники. Выполнено.
person
Markus Hütter
schedule
26.03.2011