我正在尝试扩展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类)呈现?
在哪个类(以及通过哪个方法)是一个呈现为文本的字符串?
答案 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
值动态创建的模板。
你如何改变这取决于你,虽然我个人并不是搞乱默认功能(特别是如果它影响键盘可访问性)。