2011-03-25 2 views

Répondre

4

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:

enter image description here

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é.

+0

oh! ça ressemble à un long chemin! Mon plan initial était de l'utiliser comme un Run, mais je voudrais maintenant le "Inside FlowDocument". –

+0

@shayan, s'il vous plaît voir ma mise à jour! –

+0

ouah! et pour un effet diagonal, il est logique de garder la partie entière non cassable (en boucle). Merci beaucoup. –

0

Mettez votre texte dans une toile ou grille (quelque chose qui permet des contrôles de chevauchement) et ajoutez un objet de ligne avec son X/Y points liés à votre position TextBlock

Quelque chose comme ceci:

<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Yellow"> 
    <TextBlock x:Name="TestText" Text="This is a Test" /> 
    <Line X1="{Binding ElementName=TestText, Path=ActualWidth}" 
      Y1="{Binding ElementName=TestText, Path=ActualHeight}" 
      X2="{Binding ElementName=TestText, Path=Canvas.Left}" 
      Y2="{Binding ElementName=TestText, Path=Canvas.Top}" 
      Stroke="Red" StrokeThickness="2" /> 
</Canvas> 
+0

Merci Rachel, bien sûr, cela ferait l'affaire mais la question est plus de ** étendre les décorations ** que de tracer une ligne. –

+0

Personnellement, je créer un UserControl personnalisé qui implémente ce style et l'utilise simplement à la place d'un TextBlock ou Label lorsque vous voulez ce comportement. Comme alternative, vous pourriez écrire un AttachedProperty qui fait la même chose. – Rachel

+0

C'est en quelque sorte mon point: il est facile d'étendre un contrôle mais pas un contrôle Inline (au cas où vous préférez l'utiliser directement au lieu de l'encapsuler dans un InlineUIContainer). En outre, quelque chose comme dessiner une ligne sur le texte est plus comme une décoration, ou un effet. Vous ne pouvez même pas utiliser Adorners avec un élément Inline. –

1
<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> 

le Adorner ne sera pas affiché parce que

var adornerLayer = AdornerLayer.GetAdornerLayer((Visual) parent); 
      if(adornerLayer == null) 

reviennent toujours nulle, nous devons définir la propriété attachée après la course est chargé.

Questions connexes