MISE À JOUR:
J'ai essayé de créer un exemple aussi minimal que possible. Dans des scénarios plus complexes, vous devrez l'étendre. Voici à quoi il ressemble:
c'est le XAML correspondant:
<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>
et qui est le codebehind:
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));
}));
}
have fun!
message original:
ce qui est généralement assez difficile. J'ai réussi à attacher un adorer à des éléments spécifiques dans flowdocuments mais il y a beaucoup de coins à considérer. Par exemple: que se passe-t-il si Inline est enroulé? plus loin: si ce flowdocument se trouve dans une riche zone de texte, ses internes continuent de réarranger les passages (les rejoignant ou les séparant), ce qui gâche tout. vous devez mettre les choses en place avec soin.
Pourriez-vous en dire plus sur l'emplacement de cette ligne. Dans un FlowdocumentScrollviewer? Ou un TextBlock? Ou une Richtextbox? Comme vous devez attacher l'adorer à FrameworkElement (comme vous l'avez probablement déjà remarqué, vous ne pouvez pas attacher directement un Adorner à un FrameworkContentElement), nous devons savoir où se trouve l'inline.
Je vais décrire la route générale pour y parvenir: créer une propriété jointe qui va créer l'adorner. la propriété attachée est définie sur l'inline qui va être ornée. l'adorateur garde une référence à l'inline et est attaché au FrameworkElement qui le régit. Subscibe à layoutupdated sur ce frameworkelement et faire un InvalidateVisual sur l'Adorner. Les ornements OnRender dessine la ligne avec des coordonnées en fonction des rectangles Inlines ContentStart et ContentEnd GetCharacterRect. terminé.
oh! ça ressemble à un long chemin! Mon plan initial était de l'utiliser comme un Run, mais je voudrais maintenant le "Inside FlowDocument". –
@shayan, s'il vous plaît voir ma mise à jour! –
ouah! et pour un effet diagonal, il est logique de garder la partie entière non cassable (en boucle). Merci beaucoup. –