我创建了一个示例面板,我添加了几个项目.如果我添加简单填充的矩形,调整大小/滚动性能是完美的,但是一旦我使用了文本块,性能就会消失.
看起来性能问题来自于:
child.Measure(constraint);
当测量文本块时,它会使性能停止.有什么我可以覆盖文本块的测量或某些东西来提高性能吗? (我会明确设置孩子的大小)
编辑:我现在已经创建了简化的代码来安排我想要的项目.
此代码的性能很好,除了…当文本块内的文本宽度超过文本块的实际宽度时.这使我的表现回归到爬行 – 可能是因为它试图再次测量元素?
public class TestPanel : Panel
{
private int _rowHeight = 20;
private int _columnWidth = 50;
public TestPanel()
{
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 20; j++)
{
TextBlock cell = new TextBlock();
cell.ClipToBounds = true;
cell.Width = _columnWidth;
cell.Height = _rowHeight;
cell.Text = i.ToString() + ":" + j.ToString();
this.Children.Add(cell);
}
}
}
protected override Size MeasureOverride(Size constraint)
{
return new Size(_columnWidth*20,_rowHeight*100);
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
UIElementCollection children = InternalChildren;
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 20; j++)
{
UIElement child = children[i*20+j];
child.Arrange(new Rect(j * _columnWidth, i * 20, _columnWidth, 20));
}
}
return arrangeBounds;
}
}
public MainWindow()
{
InitializeComponent();
TestPanel myPanel = new TestPanel();
ScrollViewer scroll = new ScrollViewer();
myPanel.Background = Brushes.Aqua;
scroll.Content = myPanel;
this.Content = scroll;
}
TextBox和Rectangle之间的性能差异是由于这些控件的复杂性不同.只需比较结果可视树的复杂性(即使用XamlPad).矩形很可能只知道它所需的大小.另一方面,TextBox在计算所需大小时需要考虑许多不同的因素,例如所需的实际文本大小(我猜这是真正的瓶颈).
话虽如此,您可能需要尝试一些优化.度量通过的目标是确定您想要的大小.此外,通过在所有子元素上调用measure来传播度量传递.但是,如果您希望更改所需大小,则只需执行此操作.您似乎对包含_rowHeight和_columnWidth字段的布局了解很多.所以做以下事情:
>使用以下方法测量您的孩子:child.Measure(新尺寸(_columnWidth,_rowHeight)).这是实际的约束吗?
>减少子元素的度量运行次数.通过将所有这些代码移出MeasureOverride并仅在_rowHeight或_lineWidth更改时调用此函数来执行此操作(此外,这将是在子元素上调用Measure的方法).将这些字段实现为DependencyProperties以便能够监听更改(如果您不喜欢DependencyProperties,则可以使用INotifyPropertyChanged)
>最有可能的是,您可以在常量时间内实现MeasureOverride(现在无需测量子元素)(例如numberOfColumns * _columnWidth …)
>为ArrangeOverride实现类似的逻辑.
>换句话说:不要在MeasureOverride / ArrangeOverride中做布局逻辑(即决定诸如“这个元素是否适合这一行”这样的问题)
但是,这种方法不符合TextBox元素的所需大小.您可以不关心或单独解决此问题:
>收听文字更改,选择合适的活动.
>如果TextBox中的文本发生更改,请仅为此特定文本框调用“测量”. (您可以使用正无穷大作为约束来测量此文本框)
>调整ColumnWidth和RowHeight属性
除了改进MeasureOverride / ArrangeOverride实现之外,您还可以为TextBox使用不同的(例如,更轻量级)ControlTemplate.我会选择重写MeasureOverride / ArrangeOverride.
