ACTUALIZACIÓN:
Traté de crear un ejemplo lo más mínimo posible. En escenarios más complejos, tendrás que extender esto. Aquí es como se ve:
este es el xaml correspondiente:
<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>
y ese es el código subyacente:
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));
}));
}
divertirse!
mensaje original:
esto es en general bastante duro. He logrado adjuntar un adorno a elementos específicos en documentos de flujo, pero hay muchos casos especiales a considerar. por ejemplo: ¿qué se supone que sucederá si ese Inline está envuelto? Además: si este documento de flujo se encuentra en un richtextbox, sus elementos internos siguen reorganizando ejecuciones (uniéndolos o separándolos), lo que prácticamente arruina todo. tienes que configurar las cosas cuidadosamente
Por favor, elabore más sobre dónde va a estar este en línea. ¿Dentro de FlowdocumentScrollviewer? ¿O un TextBlock? O un Richtextbox? Como tiene que adjuntar el adorno al FrameworkElement regulador (como probablemente ya haya notado que no puede adjuntar un Adorner a FrameworkContentElement directamente) necesitamos saber dónde se encuentra el en línea.
Describiré la ruta general de cómo lograr esto: cree una propiedad adjunta que va a crear el adorno. la propiedad adjunta se establece en la línea que se va a adornar. el adornador guarda una referencia al en línea y se adjunta al FrameworkElement que lo rige. subscibe a layoutupdated en ese frameworkelement y hacer un InvalidateVisual en Adorner. Los adornos OnRender trazan la línea con coordenadas dependiendo de los rectángulos ContentStart y ContentEnd GetCharacterRect. hecho.
¡oh! ¡parece una ruta larga! Mi plan inicial era usarlo como una ejecución, pero ahora elegiría el "Inside FlowDocument". –
@shayan, ¡mira mi actualización! –
¡guau! y para un efecto diagonal, tiene sentido mantener la parte entera no rompible (en envoltura). Muchas gracias. –