Frage

Wie bewerbe Sie Hub (Umriss um Text) zu einem Textblock in XAML in WPF?

War es hilfreich?

Lösung

Im Folgenden finden Sie meint mehr idiomatisch WPF, mit vollem Funktionsumfang nehmen zu diesem Thema. Es unterstützt so ziemlich alles, was man erwarten würde, einschließlich:

  • alle Schriftbezogenen Eigenschaften einschließlich Dehnungs- und Stil
  • Textausrichtung (links, rechts, Mitte, rechtfertigen)
  • Textumbruch
  • Text Trimmen
  • Textdekorationen (unterstreichen, Streik durch etcetera)

Hier ist ein einfaches Beispiel dafür, was mit ihr erreicht werden:

<local:OutlinedTextBlock FontFamily="Verdana" FontSize="20pt" FontWeight="ExtraBold" TextWrapping="Wrap" StrokeThickness="1" Stroke="{StaticResource TextStroke}" Fill="{StaticResource TextFill}">
    Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
</local:OutlinedTextBlock>

Was ergibt:

eingeben Bild Beschreibung hier

Hier ist der Code für die Steuerung:

using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;

[ContentProperty("Text")]
public class OutlinedTextBlock : FrameworkElement
{
    public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
        "Fill",
        typeof(Brush),
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
        "Stroke",
        typeof(Brush),
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
        "StrokeThickness",
        typeof(double),
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty FontStretchProperty = TextElement.FontStretchProperty.AddOwner(
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty FontStyleProperty = TextElement.FontStyleProperty.AddOwner(
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner(
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        "Text",
        typeof(string),
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextInvalidated));

    public static readonly DependencyProperty TextAlignmentProperty = DependencyProperty.Register(
        "TextAlignment",
        typeof(TextAlignment),
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty TextDecorationsProperty = DependencyProperty.Register(
        "TextDecorations",
        typeof(TextDecorationCollection),
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty TextTrimmingProperty = DependencyProperty.Register(
        "TextTrimming",
        typeof(TextTrimming),
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty TextWrappingProperty = DependencyProperty.Register(
        "TextWrapping",
        typeof(TextWrapping),
        typeof(OutlinedTextBlock),
        new FrameworkPropertyMetadata(TextWrapping.NoWrap, OnFormattedTextUpdated));

    private FormattedText formattedText;
    private Geometry textGeometry;

    public OutlinedTextBlock()
    {
        this.TextDecorations = new TextDecorationCollection();
    }

    public Brush Fill
    {
        get { return (Brush)GetValue(FillProperty); }
        set { SetValue(FillProperty, value); }
    }

    public FontFamily FontFamily
    {
        get { return (FontFamily)GetValue(FontFamilyProperty); }
        set { SetValue(FontFamilyProperty, value); }
    }

    [TypeConverter(typeof(FontSizeConverter))]
    public double FontSize
    {
        get { return (double)GetValue(FontSizeProperty); }
        set { SetValue(FontSizeProperty, value); }
    }

    public FontStretch FontStretch
    {
        get { return (FontStretch)GetValue(FontStretchProperty); }
        set { SetValue(FontStretchProperty, value); }
    }

    public FontStyle FontStyle
    {
        get { return (FontStyle)GetValue(FontStyleProperty); }
        set { SetValue(FontStyleProperty, value); }
    }

    public FontWeight FontWeight
    {
        get { return (FontWeight)GetValue(FontWeightProperty); }
        set { SetValue(FontWeightProperty, value); }
    }

    public Brush Stroke
    {
        get { return (Brush)GetValue(StrokeProperty); }
        set { SetValue(StrokeProperty, value); }
    }

    public double StrokeThickness
    {
        get { return (double)GetValue(StrokeThicknessProperty); }
        set { SetValue(StrokeThicknessProperty, value); }
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public TextAlignment TextAlignment
    {
        get { return (TextAlignment)GetValue(TextAlignmentProperty); }
        set { SetValue(TextAlignmentProperty, value); }
    }

    public TextDecorationCollection TextDecorations
    {
        get { return (TextDecorationCollection)this.GetValue(TextDecorationsProperty); }
        set { this.SetValue(TextDecorationsProperty, value); }
    }

    public TextTrimming TextTrimming
    {
        get { return (TextTrimming)GetValue(TextTrimmingProperty); }
        set { SetValue(TextTrimmingProperty, value); }
    }

    public TextWrapping TextWrapping
    {
        get { return (TextWrapping)GetValue(TextWrappingProperty); }
        set { SetValue(TextWrappingProperty, value); }
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        this.EnsureGeometry();

        drawingContext.DrawGeometry(this.Fill, new Pen(this.Stroke, this.StrokeThickness), this.textGeometry);
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        this.EnsureFormattedText();

        // constrain the formatted text according to the available size
        // the Math.Min call is important - without this constraint (which seems arbitrary, but is the maximum allowable text width), things blow up when availableSize is infinite in both directions
        // the Math.Max call is to ensure we don't hit zero, which will cause MaxTextHeight to throw
        this.formattedText.MaxTextWidth = Math.Min(3579139, availableSize.Width);
        this.formattedText.MaxTextHeight = Math.Max(0.0001d, availableSize.Height);

        // return the desired size
        return new Size(this.formattedText.Width, this.formattedText.Height);
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        this.EnsureFormattedText();

        // update the formatted text with the final size
        this.formattedText.MaxTextWidth = finalSize.Width;
        this.formattedText.MaxTextHeight = finalSize.Height;

        // need to re-generate the geometry now that the dimensions have changed
        this.textGeometry = null;

        return finalSize;
    }

    private static void OnFormattedTextInvalidated(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var outlinedTextBlock = (OutlinedTextBlock)dependencyObject;
        outlinedTextBlock.formattedText = null;
        outlinedTextBlock.textGeometry = null;

        outlinedTextBlock.InvalidateMeasure();
        outlinedTextBlock.InvalidateVisual();
    }

    private static void OnFormattedTextUpdated(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var outlinedTextBlock = (OutlinedTextBlock)dependencyObject;
        outlinedTextBlock.UpdateFormattedText();
        outlinedTextBlock.textGeometry = null;

        outlinedTextBlock.InvalidateMeasure();
        outlinedTextBlock.InvalidateVisual();
    }

    private void EnsureFormattedText()
    {
        if (this.formattedText != null || this.Text == null)
        {
            return;
        }

        this.formattedText = new FormattedText(
            this.Text,
            CultureInfo.CurrentUICulture,
            this.FlowDirection,
            new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, FontStretches.Normal),
            this.FontSize,
            Brushes.Black);

        this.UpdateFormattedText();
    }

    private void UpdateFormattedText()
    {
        if (this.formattedText == null)
        {
            return;
        }

        this.formattedText.MaxLineCount = this.TextWrapping == TextWrapping.NoWrap ? 1 : int.MaxValue;
        this.formattedText.TextAlignment = this.TextAlignment;
        this.formattedText.Trimming = this.TextTrimming;

        this.formattedText.SetFontSize(this.FontSize);
        this.formattedText.SetFontStyle(this.FontStyle);
        this.formattedText.SetFontWeight(this.FontWeight);
        this.formattedText.SetFontFamily(this.FontFamily);
        this.formattedText.SetFontStretch(this.FontStretch);
        this.formattedText.SetTextDecorations(this.TextDecorations);
    }

    private void EnsureGeometry()
    {
        if (this.textGeometry != null)
        {
            return;
        }

        this.EnsureFormattedText();
        this.textGeometry = this.formattedText.BuildGeometry(new Point(0, 0));
    }
}

Andere Tipps

Es gefunden. Gar nicht so einfach scheinbar zu tun, gibt es keine in Stroke Text in WPF gebaut (eine Art großer fehlenden Funktion, wenn Sie mich fragen). Erstellen Sie zunächst die benutzerdefinierte Klasse:

using System;
using System.Windows.Media;
using System.Globalization;
using System.Windows;
using System.Windows.Markup;

namespace CustomXaml
{

public class OutlinedText : FrameworkElement, IAddChild
{
    #region Private Fields

    private Geometry _textGeometry;

    #endregion

    #region Private Methods

    /// <summary>
    /// Invoked when a dependency property has changed. Generate a new FormattedText object to display.
    /// </summary>
    /// <param name="d">OutlineText object whose property was updated.</param>
    /// <param name="e">Event arguments for the dependency property.</param>
    private static void OnOutlineTextInvalidated(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((OutlinedText)d).CreateText();
    }

    #endregion


    #region FrameworkElement Overrides

    /// <summary>
    /// OnRender override draws the geometry of the text and optional highlight.
    /// </summary>
    /// <param name="drawingContext">Drawing context of the OutlineText control.</param>
    protected override void OnRender(DrawingContext drawingContext)
    {
        CreateText();
        // Draw the outline based on the properties that are set.
        drawingContext.DrawGeometry(Fill, new Pen(Stroke, StrokeThickness), _textGeometry);

    }

    /// <summary>
    /// Create the outline geometry based on the formatted text.
    /// </summary>
    public void CreateText()
    {
        FontStyle fontStyle = FontStyles.Normal;
        FontWeight fontWeight = FontWeights.Medium;

        if (Bold == true) fontWeight = FontWeights.Bold;
        if (Italic == true) fontStyle = FontStyles.Italic;

        // Create the formatted text based on the properties set.
        FormattedText formattedText = new FormattedText(
            Text,
            CultureInfo.GetCultureInfo("en-us"),                
            FlowDirection.LeftToRight,
            new Typeface(Font, fontStyle, fontWeight, FontStretches.Normal),                
            FontSize,
            Brushes.Black // This brush does not matter since we use the geometry of the text. 
            );

        // Build the geometry object that represents the text.
        _textGeometry = formattedText.BuildGeometry(new Point(0, 0));




        //set the size of the custome control based on the size of the text
        this.MinWidth = formattedText.Width;
        this.MinHeight = formattedText.Height;

    }

    #endregion

    #region DependencyProperties

    /// <summary>
    /// Specifies whether the font should display Bold font weight.
    /// </summary>
    public bool Bold
    {
        get
        {
            return (bool)GetValue(BoldProperty);
        }

        set
        {
            SetValue(BoldProperty, value);
        }
    }

    /// <summary>
    /// Identifies the Bold dependency property.
    /// </summary>
    public static readonly DependencyProperty BoldProperty = DependencyProperty.Register(
        "Bold",
        typeof(bool),
        typeof(OutlinedText),
        new FrameworkPropertyMetadata(
            false,
            FrameworkPropertyMetadataOptions.AffectsRender,
            new PropertyChangedCallback(OnOutlineTextInvalidated),
            null
            )
        );

    /// <summary>
    /// Specifies the brush to use for the fill of the formatted text.
    /// </summary>
    public Brush Fill
    {
        get
        {
            return (Brush)GetValue(FillProperty);
        }

        set
        {
            SetValue(FillProperty, value);
        }
    }

    /// <summary>
    /// Identifies the Fill dependency property.
    /// </summary>
    public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
        "Fill",
        typeof(Brush),
        typeof(OutlinedText),
        new FrameworkPropertyMetadata(
            new SolidColorBrush(Colors.LightSteelBlue),
            FrameworkPropertyMetadataOptions.AffectsRender,
            new PropertyChangedCallback(OnOutlineTextInvalidated),
            null
            )
        );

    /// <summary>
    /// The font to use for the displayed formatted text.
    /// </summary>
    public FontFamily Font
    {
        get
        {
            return (FontFamily)GetValue(FontProperty);
        }

        set
        {
            SetValue(FontProperty, value);
        }
    }

    /// <summary>
    /// Identifies the Font dependency property.
    /// </summary>
    public static readonly DependencyProperty FontProperty = DependencyProperty.Register(
        "Font",
        typeof(FontFamily),
        typeof(OutlinedText),
        new FrameworkPropertyMetadata(
            new FontFamily("Arial"),
            FrameworkPropertyMetadataOptions.AffectsRender,
            new PropertyChangedCallback(OnOutlineTextInvalidated),
            null
            )
        );

    /// <summary>
    /// The current font size.
    /// </summary>
    public double FontSize
    {
        get
        {
            return (double)GetValue(FontSizeProperty);
        }

        set
        {
            SetValue(FontSizeProperty, value);
        }
    }

    /// <summary>
    /// Identifies the FontSize dependency property.
    /// </summary>
    public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
        "FontSize",
        typeof(double),
        typeof(OutlinedText),
        new FrameworkPropertyMetadata(
             (double)48.0,
             FrameworkPropertyMetadataOptions.AffectsRender,
             new PropertyChangedCallback(OnOutlineTextInvalidated),
             null
             )
        );


    /// <summary>
    /// Specifies whether the font should display Italic font style.
    /// </summary>
    public bool Italic
    {
        get
        {
            return (bool)GetValue(ItalicProperty);
        }

        set
        {
            SetValue(ItalicProperty, value);
        }
    }

    /// <summary>
    /// Identifies the Italic dependency property.
    /// </summary>
    public static readonly DependencyProperty ItalicProperty = DependencyProperty.Register(
        "Italic",
        typeof(bool),
        typeof(OutlinedText),
        new FrameworkPropertyMetadata(
             false,
             FrameworkPropertyMetadataOptions.AffectsRender,
             new PropertyChangedCallback(OnOutlineTextInvalidated),
             null
             )
        );

    /// <summary>
    /// Specifies the brush to use for the stroke and optional hightlight of the formatted text.
    /// </summary>
    public Brush Stroke
    {
        get
        {
            return (Brush)GetValue(StrokeProperty);
        }

        set
        {
            SetValue(StrokeProperty, value);
        }
    }

    /// <summary>
    /// Identifies the Stroke dependency property.
    /// </summary>
    public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
        "Stroke",
        typeof(Brush),
        typeof(OutlinedText),
        new FrameworkPropertyMetadata(
             new SolidColorBrush(Colors.Teal),
             FrameworkPropertyMetadataOptions.AffectsRender,
             new PropertyChangedCallback(OnOutlineTextInvalidated),
             null
             )
        );

    /// <summary>
    ///     The stroke thickness of the font.
    /// </summary>
    public ushort StrokeThickness
    {
        get
        {
            return (ushort)GetValue(StrokeThicknessProperty);
        }

        set
        {
            SetValue(StrokeThicknessProperty, value);
        }
    }

    /// <summary>
    /// Identifies the StrokeThickness dependency property.
    /// </summary>
    public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
        "StrokeThickness",
        typeof(ushort),
        typeof(OutlinedText),
        new FrameworkPropertyMetadata(
             (ushort)0,
             FrameworkPropertyMetadataOptions.AffectsRender,
             new PropertyChangedCallback(OnOutlineTextInvalidated),
             null
             )
        );

    /// <summary>
    /// Specifies the text string to display.
    /// </summary>
    public string Text
    {
        get
        {
            return (string)GetValue(TextProperty);
        }

        set
        {
            SetValue(TextProperty, value);
        }
    }

    /// <summary>
    /// Identifies the Text dependency property.
    /// </summary>
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        "Text",
        typeof(string),
        typeof(OutlinedText),
        new FrameworkPropertyMetadata(
             "",
             FrameworkPropertyMetadataOptions.AffectsRender,
             new PropertyChangedCallback(OnOutlineTextInvalidated),
             null
             )
        );

    public void AddChild(Object value)
    {

    }

    public void AddText(string value)
    {
        Text = value;
    }

    #endregion
}
}

Das können Sie es in Ihrem XAML verweisen.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:customControls="clr-namespace:CustomXaml;assembly=CustomXaml">
    <Grid>
        <customControls:OutlinedText x:Name="TextContent" Fill="#ffffffff" FontSize="28"     
Bold="True" Stroke="Black" StrokeThickness="1" Text="Back" Margin="10,0,10,0" 
HorizontalAlignment="Center" VerticalAlignment="Center" Height="Auto" Width="Auto" />
    </Grid>
</Page>

I modifiziert, um die meisten Stimmen Antwort mit mehreren Fehlerbehebungen, einschließlich:

  • Fix so Texte mit einer einzigen Zeile würden bei Verwendung von UseLayoutRounding.

  • Outlines würde außerhalb des Textes zeigt, statt in der Mitte des Rand.

  • Der Stift nur einmal erstellt wird, anstatt auf jedem machen.

  • Fix, damit es nicht zum Absturz bringen, wenn der Text auf null gesetzt wird.

  • Fix so Umriss richtige Rundkappen verwendet.

using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;

[ContentProperty("Text")]
public class OutlinedTextBlock : FrameworkElement
{
    private void UpdatePen() {
        _Pen = new Pen(Stroke, StrokeThickness) {
            DashCap = PenLineCap.Round,
            EndLineCap = PenLineCap.Round,
            LineJoin = PenLineJoin.Round,
            StartLineCap = PenLineCap.Round
        };

        InvalidateVisual();
    }

    public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
      "Fill",
      typeof(Brush),
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
      "Stroke",
      typeof(Brush),
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender, StrokePropertyChangedCallback));

    private static void StrokePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) {
        (dependencyObject as OutlinedTextBlock)?.UpdatePen();
    }

    public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
      "StrokeThickness",
      typeof(double),
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender, StrokePropertyChangedCallback));

    public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty FontStretchProperty = TextElement.FontStretchProperty.AddOwner(
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty FontStyleProperty = TextElement.FontStyleProperty.AddOwner(
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner(
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
      "Text",
      typeof(string),
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextInvalidated));

    public static readonly DependencyProperty TextAlignmentProperty = DependencyProperty.Register(
      "TextAlignment",
      typeof(TextAlignment),
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty TextDecorationsProperty = DependencyProperty.Register(
      "TextDecorations",
      typeof(TextDecorationCollection),
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty TextTrimmingProperty = DependencyProperty.Register(
      "TextTrimming",
      typeof(TextTrimming),
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(OnFormattedTextUpdated));

    public static readonly DependencyProperty TextWrappingProperty = DependencyProperty.Register(
      "TextWrapping",
      typeof(TextWrapping),
      typeof(OutlinedTextBlock),
      new FrameworkPropertyMetadata(TextWrapping.NoWrap, OnFormattedTextUpdated));

    private FormattedText _FormattedText;
    private Geometry _TextGeometry;
    private Pen _Pen;

    public Brush Fill
    {
        get { return (Brush)GetValue(FillProperty); }
        set { SetValue(FillProperty, value); }
    }

    public FontFamily FontFamily
    {
        get { return (FontFamily)GetValue(FontFamilyProperty); }
        set { SetValue(FontFamilyProperty, value); }
    }

    [TypeConverter(typeof(FontSizeConverter))]
    public double FontSize
    {
        get { return (double)GetValue(FontSizeProperty); }
        set { SetValue(FontSizeProperty, value); }
    }

    public FontStretch FontStretch
    {
        get { return (FontStretch)GetValue(FontStretchProperty); }
        set { SetValue(FontStretchProperty, value); }
    }

    public FontStyle FontStyle
    {
        get { return (FontStyle)GetValue(FontStyleProperty); }
        set { SetValue(FontStyleProperty, value); }
    }

    public FontWeight FontWeight
    {
        get { return (FontWeight)GetValue(FontWeightProperty); }
        set { SetValue(FontWeightProperty, value); }
    }

    public Brush Stroke
    {
        get { return (Brush)GetValue(StrokeProperty); }
        set { SetValue(StrokeProperty, value); }
    }

    public double StrokeThickness
    {
        get { return (double)GetValue(StrokeThicknessProperty); }
        set { SetValue(StrokeThicknessProperty, value); }
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public TextAlignment TextAlignment
    {
        get { return (TextAlignment)GetValue(TextAlignmentProperty); }
        set { SetValue(TextAlignmentProperty, value); }
    }

    public TextDecorationCollection TextDecorations
    {
        get { return (TextDecorationCollection)GetValue(TextDecorationsProperty); }
        set { SetValue(TextDecorationsProperty, value); }
    }

    public TextTrimming TextTrimming
    {
        get { return (TextTrimming)GetValue(TextTrimmingProperty); }
        set { SetValue(TextTrimmingProperty, value); }
    }

    public TextWrapping TextWrapping
    {
        get { return (TextWrapping)GetValue(TextWrappingProperty); }
        set { SetValue(TextWrappingProperty, value); }
    }

    public OutlinedTextBlock() {
        UpdatePen();
        TextDecorations = new TextDecorationCollection();
    }

    protected override void OnRender(DrawingContext drawingContext) {
        EnsureGeometry();

        drawingContext.DrawGeometry(null, _Pen, _TextGeometry);
        drawingContext.DrawGeometry(Fill, null, _TextGeometry);
    }

    protected override Size MeasureOverride(Size availableSize) {
        EnsureFormattedText();

        // constrain the formatted text according to the available size

        double w = availableSize.Width;
        double h = availableSize.Height;

        // the Math.Min call is important - without this constraint (which seems arbitrary, but is the maximum allowable text width), things blow up when availableSize is infinite in both directions
        // the Math.Max call is to ensure we don't hit zero, which will cause MaxTextHeight to throw
        _FormattedText.MaxTextWidth = Math.Min(3579139, w);
        _FormattedText.MaxTextHeight = Math.Max(0.0001d, h);

        // return the desired size
        return new Size(Math.Ceiling(_FormattedText.Width), Math.Ceiling(_FormattedText.Height));
    }

    protected override Size ArrangeOverride(Size finalSize) {
        EnsureFormattedText();

        // update the formatted text with the final size
        _FormattedText.MaxTextWidth = finalSize.Width;
        _FormattedText.MaxTextHeight = Math.Max(0.0001d, finalSize.Height);

        // need to re-generate the geometry now that the dimensions have changed
        _TextGeometry = null;

        return finalSize;
    }

    private static void OnFormattedTextInvalidated(DependencyObject dependencyObject,
      DependencyPropertyChangedEventArgs e) {
        var outlinedTextBlock = (OutlinedTextBlock)dependencyObject;
        outlinedTextBlock._FormattedText = null;
        outlinedTextBlock._TextGeometry = null;

        outlinedTextBlock.InvalidateMeasure();
        outlinedTextBlock.InvalidateVisual();
    }

    private static void OnFormattedTextUpdated(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) {
        var outlinedTextBlock = (OutlinedTextBlock)dependencyObject;
        outlinedTextBlock.UpdateFormattedText();
        outlinedTextBlock._TextGeometry = null;

        outlinedTextBlock.InvalidateMeasure();
        outlinedTextBlock.InvalidateVisual();
    }

    private void EnsureFormattedText() {
        if (_FormattedText != null) {
            return;
        }

        _FormattedText = new FormattedText(
          Text ?? "",
          CultureInfo.CurrentUICulture,
          FlowDirection,
          new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
          FontSize,
          Brushes.Black);

        UpdateFormattedText();
    }

    private void UpdateFormattedText() {
        if (_FormattedText == null) {
            return;
        }

        _FormattedText.MaxLineCount = TextWrapping == TextWrapping.NoWrap ? 1 : int.MaxValue;
        _FormattedText.TextAlignment = TextAlignment;
        _FormattedText.Trimming = TextTrimming;

        _FormattedText.SetFontSize(FontSize);
        _FormattedText.SetFontStyle(FontStyle);
        _FormattedText.SetFontWeight(FontWeight);
        _FormattedText.SetFontFamily(FontFamily);
        _FormattedText.SetFontStretch(FontStretch);
        _FormattedText.SetTextDecorations(TextDecorations);
    }

    private void EnsureGeometry() {
        if (_TextGeometry != null) {
            return;
        }

        EnsureFormattedText();
        _TextGeometry = _FormattedText.BuildGeometry(new Point(0, 0));
    }
}

I modifizierte @Javier G. Antwort

  • Stroke Position kann sein: Mitte, außen oder innen, der Standard ist draußen.

  • Fill kann transparent sein.

Center:

 image description hier

Außenbereich:

 image description hier

Innen:

 image description hier

Code:

using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;

namespace WpfApp2
{
    public enum StrokePosition
    {
        Center,
        Outside,
        Inside
    }

    [ContentProperty("Text")]
    public class OutlinedTextBlock : FrameworkElement
    {
        private void UpdatePen()
        {
            _Pen = new Pen(Stroke, StrokeThickness)
            {
                DashCap = PenLineCap.Round,
                EndLineCap = PenLineCap.Round,
                LineJoin = PenLineJoin.Round,
                StartLineCap = PenLineCap.Round
            };

            if (StrokePosition == StrokePosition.Outside || StrokePosition == StrokePosition.Inside)
            {
                _Pen.Thickness = StrokeThickness * 2;
            }

            InvalidateVisual();
        }

        public StrokePosition StrokePosition
        {
            get { return (StrokePosition)GetValue(StrokePositionProperty); }
            set { SetValue(StrokePositionProperty, value); }
        }

        public static readonly DependencyProperty StrokePositionProperty =
            DependencyProperty.Register("StrokePosition", 
                typeof(StrokePosition),
                typeof(OutlinedTextBlock),
                new FrameworkPropertyMetadata(StrokePosition.Outside, FrameworkPropertyMetadataOptions.AffectsRender));

        public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
          "Fill",
          typeof(Brush),
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender));

        public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
          "Stroke",
          typeof(Brush),
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender));

        public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
          "StrokeThickness",
          typeof(double),
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender));

        public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextUpdated));

        public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextUpdated));

        public static readonly DependencyProperty FontStretchProperty = TextElement.FontStretchProperty.AddOwner(
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextUpdated));

        public static readonly DependencyProperty FontStyleProperty = TextElement.FontStyleProperty.AddOwner(
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextUpdated));

        public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner(
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextUpdated));

        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
          "Text",
          typeof(string),
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextInvalidated));

        public static readonly DependencyProperty TextAlignmentProperty = DependencyProperty.Register(
          "TextAlignment",
          typeof(TextAlignment),
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextUpdated));

        public static readonly DependencyProperty TextDecorationsProperty = DependencyProperty.Register(
          "TextDecorations",
          typeof(TextDecorationCollection),
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextUpdated));

        public static readonly DependencyProperty TextTrimmingProperty = DependencyProperty.Register(
          "TextTrimming",
          typeof(TextTrimming),
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(OnFormattedTextUpdated));

        public static readonly DependencyProperty TextWrappingProperty = DependencyProperty.Register(
          "TextWrapping",
          typeof(TextWrapping),
          typeof(OutlinedTextBlock),
          new FrameworkPropertyMetadata(TextWrapping.NoWrap, OnFormattedTextUpdated));

        private FormattedText _FormattedText;
        private Geometry _TextGeometry;
        private Pen _Pen;
        private PathGeometry _clipGeometry;

        public Brush Fill
        {
            get { return (Brush)GetValue(FillProperty); }
            set { SetValue(FillProperty, value); }
        }

        public FontFamily FontFamily
        {
            get { return (FontFamily)GetValue(FontFamilyProperty); }
            set { SetValue(FontFamilyProperty, value); }
        }

        [TypeConverter(typeof(FontSizeConverter))]
        public double FontSize
        {
            get { return (double)GetValue(FontSizeProperty); }
            set { SetValue(FontSizeProperty, value); }
        }

        public FontStretch FontStretch
        {
            get { return (FontStretch)GetValue(FontStretchProperty); }
            set { SetValue(FontStretchProperty, value); }
        }

        public FontStyle FontStyle
        {
            get { return (FontStyle)GetValue(FontStyleProperty); }
            set { SetValue(FontStyleProperty, value); }
        }

        public FontWeight FontWeight
        {
            get { return (FontWeight)GetValue(FontWeightProperty); }
            set { SetValue(FontWeightProperty, value); }
        }

        public Brush Stroke
        {
            get { return (Brush)GetValue(StrokeProperty); }
            set { SetValue(StrokeProperty, value); }
        }

        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public TextAlignment TextAlignment
        {
            get { return (TextAlignment)GetValue(TextAlignmentProperty); }
            set { SetValue(TextAlignmentProperty, value); }
        }

        public TextDecorationCollection TextDecorations
        {
            get { return (TextDecorationCollection)GetValue(TextDecorationsProperty); }
            set { SetValue(TextDecorationsProperty, value); }
        }

        public TextTrimming TextTrimming
        {
            get { return (TextTrimming)GetValue(TextTrimmingProperty); }
            set { SetValue(TextTrimmingProperty, value); }
        }

        public TextWrapping TextWrapping
        {
            get { return (TextWrapping)GetValue(TextWrappingProperty); }
            set { SetValue(TextWrappingProperty, value); }
        }

        public OutlinedTextBlock()
        {
            UpdatePen();
            TextDecorations = new TextDecorationCollection();
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            EnsureGeometry();

            drawingContext.DrawGeometry(Fill, null, _TextGeometry);

            if (StrokePosition == StrokePosition.Outside)
            {
                drawingContext.PushClip(_clipGeometry);
            }
            else if (StrokePosition == StrokePosition.Inside)
            {
                drawingContext.PushClip(_TextGeometry);
            }

            drawingContext.DrawGeometry(null, _Pen, _TextGeometry);

            if (StrokePosition == StrokePosition.Outside || StrokePosition == StrokePosition.Inside)
            {
                drawingContext.Pop();
            }
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            EnsureFormattedText();

            // constrain the formatted text according to the available size

            double w = availableSize.Width;
            double h = availableSize.Height;

            // the Math.Min call is important - without this constraint (which seems arbitrary, but is the maximum allowable text width), things blow up when availableSize is infinite in both directions
            // the Math.Max call is to ensure we don't hit zero, which will cause MaxTextHeight to throw
            _FormattedText.MaxTextWidth = Math.Min(3579139, w);
            _FormattedText.MaxTextHeight = Math.Max(0.0001d, h);

            // return the desired size
            return new Size(Math.Ceiling(_FormattedText.Width), Math.Ceiling(_FormattedText.Height));
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            EnsureFormattedText();

            // update the formatted text with the final size
            _FormattedText.MaxTextWidth = finalSize.Width;
            _FormattedText.MaxTextHeight = Math.Max(0.0001d, finalSize.Height);

            // need to re-generate the geometry now that the dimensions have changed
            _TextGeometry = null;
            UpdatePen();

            return finalSize;
        }

        private static void OnFormattedTextInvalidated(DependencyObject dependencyObject,
          DependencyPropertyChangedEventArgs e)
        {
            var outlinedTextBlock = (OutlinedTextBlock)dependencyObject;
            outlinedTextBlock._FormattedText = null;
            outlinedTextBlock._TextGeometry = null;

            outlinedTextBlock.InvalidateMeasure();
            outlinedTextBlock.InvalidateVisual();
        }

        private static void OnFormattedTextUpdated(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var outlinedTextBlock = (OutlinedTextBlock)dependencyObject;
            outlinedTextBlock.UpdateFormattedText();
            outlinedTextBlock._TextGeometry = null;

            outlinedTextBlock.InvalidateMeasure();
            outlinedTextBlock.InvalidateVisual();
        }

        private void EnsureFormattedText()
        {
            if (_FormattedText != null)
            {
                return;
            }

            _FormattedText = new FormattedText(
              Text ?? "",
              CultureInfo.CurrentUICulture,
              FlowDirection,
              new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
              FontSize,
              Brushes.Black);

            UpdateFormattedText();
        }

        private void UpdateFormattedText()
        {
            if (_FormattedText == null)
            {
                return;
            }

            _FormattedText.MaxLineCount = TextWrapping == TextWrapping.NoWrap ? 1 : int.MaxValue;
            _FormattedText.TextAlignment = TextAlignment;
            _FormattedText.Trimming = TextTrimming;

            _FormattedText.SetFontSize(FontSize);
            _FormattedText.SetFontStyle(FontStyle);
            _FormattedText.SetFontWeight(FontWeight);
            _FormattedText.SetFontFamily(FontFamily);
            _FormattedText.SetFontStretch(FontStretch);
            _FormattedText.SetTextDecorations(TextDecorations);
        }

        private void EnsureGeometry()
        {
            if (_TextGeometry != null)
            {
                return;
            }

            EnsureFormattedText();
            _TextGeometry = _FormattedText.BuildGeometry(new Point(0, 0));

            if (StrokePosition == StrokePosition.Outside)
            {
                var boundsGeo = new RectangleGeometry(new Rect(0, 0, ActualWidth, ActualHeight));
                _clipGeometry = Geometry.Combine(boundsGeo, _TextGeometry, GeometryCombineMode.Exclude, null);
            }           
        }
    }
}

Usege:

<Grid Margin="12" Background="Bisque">
    <local:OutlinedTextBlock Stroke="Red" 
                             ClipToBounds="False"
                             FontSize="56" 
                             Fill="Transparent"
                             StrokePosition="Inside"
                             StrokeThickness="1" Text=" abc">
    </local:OutlinedTextBlock>
</Grid>

Sie sollten den Textblock mit einem Border .. so etwas wie dies wickeln:

    <Border BorderBrush="Purple" BorderThickness="2">
        <TextBlock>My fancy TextBlock</TextBlock>
    </Border>

in der vagen Hoffnung, Sie zu fragen, wie um den tatsächlichen Buchstaben einen Schlaganfall zu setzen (und nicht das ganze Textblock) können Sie bei Verwendung eines Bitmap von Glow aussehen soll und die Einstellung der Parameter auf dem Glühen der Hub sein Farbe, die Sie Ansonsten wollen usw. Sie müssen möglicherweise etwas benutzerdefinierte erstellen.

"Gewusst wie: Erstellen Beschriebenen Text" auf MSDN hat alle Informationen, die Sie benötigen.

In Mischung können Sie den Textblock auf einen Pfad, konvertieren und dann die normalen Stroke Eigenschaften verwenden. Aber ich nehme an, Sie wollten etwas, das Sie dynamisch machen könnte ...

Sonst hätte ich denke, es würde eine Art von Bitmap-Effekt oder spezieller Bürste sein.

Könnte nur ein Label stattdessen verwenden. Es hat mehrere Eigenschaften, die Sie mit spielen können. Beispiel:

  <Style x:Key="LeftBorderLabel" TargetType="{x:Type Label}">
            <Setter Property="Margin"  Value="0" />
            <Setter Property="BorderThickness" Value="1,0,0,0" />
            <Setter Property="BorderBrush" Value="Blue" />
  </Style>

Ich hatte dies zu MeasureOverride hinzufügen, damit es einzelne Textzeilen zeigen würde, während das Layout Runden verwenden. Es funktionierte gut, wenn der Text allerdings wickelt.

// return the desired size
return new Size(Math.Ceiling(_FormattedText.Width), Math.Ceiling(_FormattedText.Height));

Wenn Sie für jedermann angewendet wird, hier eine einfache Lösung, die nur XAML verwenden. Ich bin nicht sicher, ob es besser oder schlechter durchführt, aber meiner Meinung nach, sieht es besser als jede andere Lösung oben. Ich wickle es in einem ContentControl Stil (und Template), im Anschluss an diese Old School Beispiel :) http: // oldschooldotnet. blogspot.co.il/2009/02/fancy-fonts-in-xaml-silverlight-and-wpf.html

<Style x:Key="OutlinedText" TargetType="{x:Type ContentControl}">
    <!-- Some Style Setters -->
    <Setter Property="Content" Value="Outlined Text"/>
    <Setter Property="Padding" Value="0"/>
    <!-- Border Brush Must be equal '0' because TextBlock that emulate the stroke will using the BorderBrush as to define 'Stroke' color-->
    <Setter Property="BorderThickness" Value="0"/>
    <!-- Border Brush define 'Stroke' Color-->
    <Setter Property="BorderBrush" Value="White"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="FontSize" Value="24"/>
    <Setter Property="FontFamily" Value="Seoge UI Bold"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContentControl}">
                <Canvas Width="{Binding ActualWidth, ElementName=FillText}" Height="{Binding ActualHeight, ElementName=FillText}">
                    <Canvas.Resources>
                        <!-- Style to ease the duplication of Text Blocks that emulate the stroke: Binding to one element (or to template) is the first part of the Trick -->
                        <Style x:Key="OutlinedTextStrokeTextBlock_Style" TargetType="{x:Type TextBlock}">
                            <Setter Property="Text" Value="{Binding Text, ElementName=FillText}"/>
                            <Setter Property="FontSize" Value="{Binding FontSize, ElementName=FillText}"/>
                            <Setter Property="FontFamily" Value="{Binding FontFamily, ElementName=FillText}"/>
                            <Setter Property="FontStyle" Value="{Binding FontStyle, ElementName=FillText}"/>
                            <Setter Property="FontWeight" Value="{Binding FontWeight, ElementName=FillText}"/>
                            <Setter Property="Padding" Value="{Binding TextAlignment, ElementName=Padding}"/>
                            <Setter Property="TextAlignment" Value="{Binding TextAlignment, ElementName=FillText}"/>
                            <Setter Property="VerticalAlignment" Value="{Binding VerticalAlignment, ElementName=FillText}"/>
                        </Style>
                    </Canvas.Resources>
                    <!-- Offseting the Text block will create the outline, the margin is the Stroke Width-->
                    <TextBlock Foreground="{TemplateBinding BorderBrush}" Margin="-1,0,0,0" Style="{DynamicResource OutlinedTextStrokeTextBlock_Style}"/>
                    <TextBlock Foreground="{TemplateBinding BorderBrush}" Margin="0,-1,0,0" Style="{DynamicResource OutlinedTextStrokeTextBlock_Style}"/>
                    <TextBlock Foreground="{TemplateBinding BorderBrush}" Margin="0,0,-1,0" Style="{DynamicResource OutlinedTextStrokeTextBlock_Style}"/>
                    <TextBlock Foreground="{TemplateBinding BorderBrush}" Margin="0,0,0,-1" Style="{DynamicResource OutlinedTextStrokeTextBlock_Style}"/>
                    <!-- Base TextBlock Will be the Fill -->
                    <TextBlock x:Name="FillText" Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}"
                               FontStyle="{TemplateBinding FontStyle}" FontWeight="{TemplateBinding FontWeight}" Padding="0" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                               TextAlignment="{TemplateBinding HorizontalContentAlignment}"
                               Style="{DynamicResource TbMediaOverlay_Style}"/>
                </Canvas>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Wie bereits erwähnt, wird Text auf Pfad

FormattedText t = new FormattedText
(
    "abcxyz",
    CultureInfo.GetCultureInfo("en-us"),
    FlowDirection.LeftToRight,
    new Typeface(
    new FontFamily("Arial"),
    new FontStyle(),
    new FontWeight(),
    new FontStretch()),
    20,
    Brushes.Transparent
);

Geometry g = t.BuildGeometry(new System.Windows.Point(0, 0));

Path p = new Path();
p.Fill = Brushes.White;
p.Stroke = Brushes.Black;
p.StrokeThickness = 1;
p.Data = g;

hat keine dekorativen Eigenschaften selbst. Ich würde es auf einem setzen mit und den Hub dort gelten.

Das half mir enorm! jeder kann es in der Zukunft braucht nur für den Fall, hier ist die VB-Version (hergestellt StrokeThickness ein Doppel- und hinzugefügt, um eine Unterstrichen Eigenschaft):

Imports System
Imports System.Windows.Media
Imports System.Globalization
Imports System.Windows
Imports System.Windows.Markup

Namespace CustomXaml

    Public Class OutlinedText
        Inherits FrameworkElement
        Implements IAddChild

        Private _textGeometry As Geometry

        Private Shared Sub OnOutlineTextInvalidated(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
            DirectCast(d, OutlinedText).CreateText()
        End Sub

        Protected Overrides Sub OnRender(drawingContext As System.Windows.Media.DrawingContext)
            CreateText()
            drawingContext.DrawGeometry(Fill, New Pen(Stroke, StrokeThickness), _textGeometry)
        End Sub

        Public Sub CreateText()
            Dim fontStyle = FontStyles.Normal
            Dim fontWeight = FontWeights.Medium
            Dim fontDecoration = New TextDecorationCollection()

            If Bold Then fontWeight = FontWeights.Bold
            If Italic Then fontStyle = FontStyles.Italic
            If Underline Then fontDecoration.Add(TextDecorations.Underline)

            Dim formattedText = New FormattedText( _
                                Text, _
                                CultureInfo.GetCultureInfo("en-us"), _
                                FlowDirection.LeftToRight, _
                                New Typeface(Font, fontStyle, fontWeight, FontStretches.Normal), _
                                FontSize, _
                                Brushes.Black _
                                )
            formattedText.SetTextDecorations(fontDecoration)

            _textGeometry = formattedText.BuildGeometry(New Point(0, 0))

            Me.MinWidth = formattedText.Width
            Me.MinHeight = formattedText.Height
        End Sub

        Public Property Bold As Boolean
            Get
                Return CType(GetValue(BoldProperty), Boolean)
            End Get
            Set(value As Boolean)
                SetValue(BoldProperty, value)
            End Set
        End Property

        Public Shared ReadOnly BoldProperty As DependencyProperty = DependencyProperty.Register( _
            "Bold", _
            GetType(Boolean), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                False, _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Property Underline As Boolean
            Get
                Return CType(GetValue(UnderlineProperty), Boolean)
            End Get
            Set(value As Boolean)
                SetValue(UnderlineProperty, value)
            End Set
        End Property

        Public Shared ReadOnly UnderlineProperty As DependencyProperty = DependencyProperty.Register( _
            "Underline", _
            GetType(Boolean), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                False, _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Property Fill As Brush
            Get
                Return CType(GetValue(FillProperty), Brush)
            End Get
            Set(value As Brush)
                SetValue(FillProperty, value)
            End Set
        End Property

        Public Shared ReadOnly FillProperty As DependencyProperty = DependencyProperty.Register( _
            "Fill", _
            GetType(Brush), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                New SolidColorBrush(Colors.LightSteelBlue), _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Property Font As FontFamily
            Get
                Return CType(GetValue(FontProperty), FontFamily)
            End Get
            Set(value As FontFamily)
                SetValue(FontProperty, value)
            End Set
        End Property

        Public Shared ReadOnly FontProperty As DependencyProperty = DependencyProperty.Register( _
            "Font", _
            GetType(FontFamily), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                New FontFamily("Arial"), _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Property FontSize As Double
            Get
                Return CType(GetValue(FontSizeProperty), Double)
            End Get
            Set(value As Double)
                SetValue(FontSizeProperty, value)
            End Set
        End Property

        Public Shared ReadOnly FontSizeProperty As DependencyProperty = DependencyProperty.Register( _
            "FontSize", _
            GetType(Double), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                CDbl(48.0), _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Property Italic As Boolean
            Get
                Return CType(GetValue(ItalicProperty), Boolean)
            End Get
            Set(value As Boolean)
                SetValue(ItalicProperty, value)
            End Set
        End Property

        Public Shared ReadOnly ItalicProperty As DependencyProperty = DependencyProperty.Register( _
            "Italic", _
            GetType(Boolean), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                False, _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Property Stroke As Brush
            Get
                Return CType(GetValue(StrokeProperty), Brush)
            End Get
            Set(value As Brush)
                SetValue(StrokeProperty, value)
            End Set
        End Property

        Public Shared ReadOnly StrokeProperty As DependencyProperty = DependencyProperty.Register( _
            "Stroke", _
            GetType(Brush), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                New SolidColorBrush(Colors.Teal), _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Property StrokeThickness As Double
            Get
                Return CType(GetValue(StrokeThicknessProperty), Double)
            End Get
            Set(value As Double)
                SetValue(StrokeThicknessProperty, value)
            End Set
        End Property

        Public Shared ReadOnly StrokeThicknessProperty As DependencyProperty = DependencyProperty.Register( _
            "StrokeThickness", _
            GetType(Double), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                CDbl(0), _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Property Text As String
            Get
                Return CType(GetValue(TextProperty), String)
            End Get
            Set(value As String)
                SetValue(TextProperty, value)
            End Set
        End Property

        Public Shared ReadOnly TextProperty As DependencyProperty = DependencyProperty.Register( _
            "Text", _
            GetType(String), _
            GetType(OutlinedText), _
            New FrameworkPropertyMetadata( _
                "", _
                FrameworkPropertyMetadataOptions.AffectsRender, _
                New PropertyChangedCallback(AddressOf OnOutlineTextInvalidated), _
                Nothing _
            ) _
        )

        Public Sub AddChild(value As Object) Implements System.Windows.Markup.IAddChild.AddChild

        End Sub

        Public Sub AddText(text As String) Implements System.Windows.Markup.IAddChild.AddText
            Me.Text = text
        End Sub
    End Class
End Namespace

Ich war mit Kent-Lösung in meiner benutzerdefinierten Kontrolle. Es führte zu einer Null-Ausnahme, wenn Template gegen den Text Eigenschaft.

Ich hatte die MeasureOverride Funktion ändern wie folgt:

    protected override Size MeasureOverride(Size availableSize)
    {
        this.EnsureFormattedText();

        if (this.formattedText == null)
        {
            this.formattedText = new FormattedText(
                                (this.Text == null) ? "" : this.Text,
                                CultureInfo.CurrentUICulture,
                                this.FlowDirection,
                                new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, FontStretches.Normal),
                                this.FontSize,
                                Brushes.Black);
        }

        // constrain the formatted text according to the available size
        // the Math.Min call is important - without this constraint (which seems arbitrary, but is the maximum allowable text width), things blow up when availableSize is infinite in both directions
        this.formattedText.MaxTextWidth = Math.Min(3579139, availableSize.Width);
        this.formattedText.MaxTextHeight = availableSize.Height;

        // return the desired size
        return new Size(this.formattedText.Width, this.formattedText.Height);
    }

Es ist zu beachten, dass ich dies nicht gründlich prüfte.

Leichte Änderung Kent Boogaart Code, die zwar fantastisch, ist ein kleines Detail fehlt. Dies ist wahrscheinlich ein wenig ungenau, dass es nur die Füllung messen wird und nicht den Hub aber ein paar Zeilen hinzugefügt werden OnRender() Viewbox der Lage sein, den Griff zu bekommen, was damit zu tun (obwohl, wie mit TextBox, nicht in der Vorschau ).

protected override void OnRender(DrawingContext drawingContext)
{
    this.EnsureGeometry();

    this.Width = this.formattedText.Width;
    this.Height = this.formattedText.Height;

    drawingContext.DrawGeometry(this.Fill, new Pen(this.Stroke, this.StrokeThickness), this.textGeometry);
}

Ich verwende diese mit zwei Schichten von Text so der Hub erscheint nur um die Außenseite zu sein, wie folgt. Dies wird sich natürlich nicht auf Anhieb funktioniert, wie es auf bestimmte Bilder und Schriften bezeichnet.

<Viewbox Stretch="UniformToFill" Margin="0" Grid.Column="1">
    <bd:OutlinedText x:Name="LevelTitleStroke" Text="Level" FontSize="80pt" FontFamily="/fonts/papercuts-2.ttf#Paper Cuts 2" Grid.Row="1" TextAlignment="Center" IsHitTestVisible="False" StrokeThickness="15">
        <bd:OutlinedText.Stroke>
            <ImageBrush ImageSource="/WpfApplication1;component/GrungeMaps/03DarkBlue.jpg" Stretch="None" />
        </bd:OutlinedText.Stroke>
    </bd:OutlinedText>
</Viewbox>
<Viewbox Stretch="UniformToFill" Margin="0" Grid.Column="1">
    <bd:OutlinedText x:Name="LevelTitleFill" Text="Level" FontSize="80pt" FontFamily="/fonts/papercuts-2.ttf#Paper Cuts 2" Grid.Row="1" TextAlignment="Center" IsHitTestVisible="False">
        <bd:OutlinedText.Fill>
            <ImageBrush ImageSource="/WpfApplication1;component/GrungeMaps/03Red.jpg" Stretch="None" />
        </bd:OutlinedText.Fill>
    </bd:OutlinedText>
</Viewbox>

Ich habe versucht, auch etwas ähnliches wie dieses Ziel zu erreichen. Die Klassen hier erwähnt waren großartig, aber sie waren nicht genau das, was ich suchte, weil es wirklich nur sah richtig, wenn der Text groß genug war. Der Text, den ich versuchte, war etwa 10 angezeigt werden - Größe 11 Schriftart und der Hub war so groß, die Buchstaben sortieren Zusammen gemischt.

Nur um klären, dieser Text sollte auf einem benutzerdefiniertes Bild überlagert werden, die Farben variiert haben könnte, und ich wollte diesen Text, um sicherzustellen, auftauchen würde.

Ich weiß nicht, ob dies am beste Praxis ist oder nicht, aber dies zumindest erreichte das Aussehen I (basierend auf dieser Artikel ):

<Style x:Key="OutlinedTextBlockOuter" TargetType="TextBlock">
    <Setter Property="Foreground" Value="Black" />
    <Setter Property="FontSize" Value="10"/>
    <Setter Property="Effect">
        <Setter.Value>
            <BlurEffect Radius="3.0"/>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="OutlinedTextBlockInner" TargetType="TextBlock">
    <Setter Property="Foreground" Value="White" />
    <Setter Property="FontSize" Value="10"/>
</Style>

Dann für die eigentlichen Textblocks, ich kombiniert zwei Outer Textblocks Stil, weil man zu leicht war, und ein Innen gestylt TextBlock-:

<Grid Margin="5">
    <TextBlock Style="{StaticResource OutlinedTextBlockOuter}" Text="This is outlined text using BlurEffect"/>
    <TextBlock Style="{StaticResource OutlinedTextBlockOuter}" Text="This is outlined text using BlurEffect"/>
    <TextBlock Style="{StaticResource OutlinedTextBlockInner}" Text="This is outlined text using BlurEffect"/>
</Grid>

Alternativ können Sie die DropShadowEffect verwenden, die mit der Verwendung von nur zwei Textfelder in Ordnung sah (obwohl mehr DropShadowEffects mit unterschiedlichen Richtungen Zugabe und abgesenkt Opazität noch besser aussehen können):

<Grid Margin="5">
    <TextBlock  Text="This is my outlined text using the DropShadowEffect" FontSize="10" Foreground="White">
        <TextBlock.Effect>
            <DropShadowEffect ShadowDepth="1" BlurRadius="2" Opacity="0.75" Direction="315"/>
        </TextBlock.Effect>
    </TextBlock>
    <TextBlock  Text="This is my outlined text using the DropShadowEffect" FontSize="10" Foreground="White">
        <TextBlock.Effect>
            <DropShadowEffect ShadowDepth="1" BlurRadius="2" Opacity="0.75" Direction="135"/>
        </TextBlock.Effect>
    </TextBlock>
</Grid>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top