我有一个自定义控件,看起来大致如下:
public class MyTextBlockTest : Control
{
static MyTextBlockTest()
{
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string),
typeof(MyTextBlockTest), new FrameworkPropertyMetadata(""));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
FontFamily font = new FontFamily("Times New Roman");
Typeface typeface = new Typeface(font, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
FormattedText ft = new FormattedText(Text,
System.Globalization.CultureInfo.CurrentCulture,
System.Windows.FlowDirection.LeftToRight,
typeface,
15.0,
Brushes.Black);
var point = this.PointToScreen(new Point(0, 0));
drawingContext.DrawText(ft, point);
}
}
我正在尝试在ItemsControl
:
<ScrollViewer>
<ItemsControl ItemsSource="{Binding BigList, ElementName=MainWindowView}" Margin="0,-1,0,1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--<TextBlock Text="{Binding}"/>-->
<controls:MyTextBlockTest Text="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
如果我启用了已注释掉的TextBlock
,则列表显示正常;但是,使用我的自定义控件,WPF不会将文本放在正确的位置;更具体地说,它似乎只是简单地将所有元素打印在彼此之上。
this.PointToScreen
调用是我最初给它提示的一个想法,但我不确定(即使这样做有效,但事实并非如此)是否会对ScrollViewer做出有利的反应。
我意识到我可以简单地将这个控件基于TextBlock控件,但我特别希望将它作为性能实验以较低级别的控件为基础。请有人指出我正确地将自定义控件放在屏幕上的方法吗?
答案 0 :(得分:2)
您的最小自定义TextBlock至少应该覆盖MeasureOverride
方法以返回其大小。否则,控件的宽度和高度为零,ItemsControl中的所有项目都是相互重叠的。
因此,Text
属性应使用FrameworkPropertyMetadataOptions.AffectsMeasure
标志注册。
public class MyTextBlock : FrameworkElement
{
private FormattedText formattedText;
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text", typeof(string), typeof(MyTextBlock),
new FrameworkPropertyMetadata(
string.Empty,
FrameworkPropertyMetadataOptions.AffectsMeasure,
(o, e) => ((MyTextBlock)o).TextPropertyChanged((string)e.NewValue)));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
private void TextPropertyChanged(string text)
{
var typeface = new Typeface(
new FontFamily("Times New Roman"),
FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
formattedText = new FormattedText(
text, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight, typeface, 15, Brushes.Black);
}
protected override Size MeasureOverride(Size availableSize)
{
return formattedText != null
? new Size(formattedText.Width, formattedText.Height)
: new Size();
}
protected override void OnRender(DrawingContext drawingContext)
{
if (formattedText != null)
{
drawingContext.DrawText(formattedText, new Point());
}
}
}