WPF标签如何将字符串呈现为文本?

时间:2016-03-12 00:46:31

标签: c# wpf inheritance text label

我正在尝试扩展Label控件以支持抚摸文本(有点像this问题的答案,但我想扩展一个Label来做而不是写一个全新的(ish)控件)

我已经取得了一定程度的成功,但是我遇到了一块墙,我无法找到标签如何呈现文字。如果我能弄清楚它是如何发生的(并覆盖它),那么我可以在我的扩展Label类(画笔和双精度)中添加一些属性,然后全部设置。

这是我到目前为止所做的:

public class StrokedLabel : Label {
    public static readonly DependencyProperty
        StrokeProperty = DependencyProperty.Register(
            "Stroke",
            typeof( Brush ),
            typeof( StrokedLabel ),
            new PropertyMetadata(
                Brushes.Red,
                ( S, E ) => ( S as StrokedLabel ).InvalidateVisual( ) ) ),
        StrokeWidthProperty = DependencyProperty.Register(
            "StrokeWidth",
            typeof( double ),
            typeof( StrokedLabel ),
            new PropertyMetadata(
                2.0D,
                ( S, E ) => ( S as StrokedLabel ).InvalidateVisual( ) ) );

    /// <summary>
    /// Get or Set Stroke Brush.
    /// </summary>
    public Brush Stroke {
        get { return this.GetValue( StrokeProperty ) as Brush; }
        set { this.SetValue( StrokeProperty, value ); }
    }

    /// <summary>
    /// Get or Set Stroke Width
    /// </summary>
    public double StrokeWidth {
        get { return ( double )this.GetValue( StrokeWidthProperty ); }
        set { this.SetValue( StrokeWidthProperty, value ); }
    }

    protected override void OnRender( DrawingContext drawingContext ) {
        if ( !( this.Content is string ) )
            base.OnRender( drawingContext );
        else {
            drawingContext.DrawGeometry(
                this.Foreground,
                new Pen(
                    this.Stroke,
                    this.StrokeWidth ),
                new FormattedText(
                    this.Content.ToString( ),
                    CultureInfo.CurrentUICulture,
                    this.FlowDirection,
                    new Typeface(
                        this.FontFamily,
                        this.FontStyle,
                        this.FontWeight,
                        this.FontStretch ),
                    this.FontSize,
                    this.Foreground ).BuildGeometry( new Point( 0.0D, 0.0D ) ) );
        }
    }
}

我试过跟踪继承链,我已经把它定义为UIElement定义了OnRender方法,但我无法找到继承链中的哪个方法实际使用(或者如果它甚至涉及)。

我觉得文本是在ContentControl中呈现的(Label直接从中继承)但是我找不到该控件中文本的呈现位置。它是在Content Control中呈现的,还是以Content Control继承的内容(Control类)呈现?

在哪个类(以及通过哪个方法)是一个呈现为文本的字符串?

1 个答案:

答案 0 :(得分:0)

由于我有点好奇,我再次正确地看了一遍。这是静态ContentPresenter构造函数中发生的事情:

// Default template for strings when hosted in ContentPresener with RecognizesAccessKey=true
template = new DataTemplate();
text = CreateAccessTextFactory();
text.SetValue(AccessText.TextProperty, new TemplateBindingExtension(ContentProperty));
template.VisualTree = text;
template.Seal();
s_AccessTextTemplate = template;
// Default template selector
s_DefaultTemplateSelector = new DefaultSelector();

它创建了一个AccessText模板,该模板存储在一个私有字段中,该字段具有内部属性访问器(以及一些其他默认模板)和默认模板选择器。

解析模板后,会调用ChooseTemplate,其中包含:

...
// if that failed, try the default TemplateSelector
if (template == null)
{
    template = DefaultTemplateSelector.SelectTemplate(content, this);
}

DefaultSelector SelectTemplate方法中,如果找不到模板,则会进行以下调用:

...
if ((s = item as string) != null)
    template = ((ContentPresenter)container).SelectTemplateForString(s);

SelectTemplateForString

...
if (this.RecognizesAccessKey && s.IndexOf(AccessText.AccessKeyMarker) > -1)
{
    template = (String.IsNullOrEmpty(format)) ?
        AccessTextContentTemplate : FormattingAccessTextContentTemplate;
}

所以这里选择在构造函数中创建的静态模板,或者使用ContentStringFormat值动态创建的模板。

你如何改变这取决于你,虽然我个人并不是搞乱默认功能(特别是如果它影响键盘可访问性)。