ItemsControl 内的 WPF 自定义控件
WPF Custom Control inside ItemsControl
我有一个自定义控件,大致如下所示:
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 控件,但我特别想将它基于较低级别的控件作为性能实验。请有人指点我一种将自定义控件正确放置在屏幕上的方法吗?
您的最小自定义 TextBlock 至少还应覆盖 MeasureOverride
方法以 return 其大小。否则控件的宽度和高度为零,并且 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());
}
}
}
我有一个自定义控件,大致如下所示:
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 控件,但我特别想将它基于较低级别的控件作为性能实验。请有人指点我一种将自定义控件正确放置在屏幕上的方法吗?
您的最小自定义 TextBlock 至少还应覆盖 MeasureOverride
方法以 return 其大小。否则控件的宽度和高度为零,并且 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());
}
}
}