在显示少量数据时,我一直在使用 WPF DataGrid 和列表框 GridView 性能问题。我虽然这个问题只是 WPF 一般性能不佳,但问题似乎仅在于文本块控件。
我创建了一个示例面板,向其中添加了几个项目。如果我添加简单填充的矩形,调整大小/滚动性能是完美的,但是一旦我使用文本块,性能就会消失。
看起来性能问题源于:
child.Measure(constraint);
当文本块被测量时,它会使性能停滞不前。有什么我可以覆盖文本块的测量或提高性能的方法吗? (我会明确设置 child 的大小)
编辑:我现在已经创建了简化的代码来根据需要安排项目。
这段代码的性能很好,除了……当文本块内的文本宽度超过文本块的实际宽度时。这使我的表现回到了爬行状态 - 可能是因为它试图再次测量元素?
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)。一个 Rectangle 很可能只知道它想要的大小。另一方面,TextBox 在计算所需大小时需要考虑许多不同的因素,例如所需的实际文本大小(我猜这是真正的瓶颈)。
话虽如此,您可能想尝试一些优化。测量通过的目标是确定您想要的尺寸。此外,您可以通过在所有子元素上调用 measure 来传播度量传递。但是,仅当您希望更改所需大小时才需要执行此操作。您似乎对具有 _rowHeight 和 _columnWidth 字段的布局了解很多。因此,请执行以下操作:
child.Measure(new Size(_columnWidth, _rowHeight))
.这是实际的约束吗? numberOfColumns * _columnWidth...
)但是,这种方法不考虑 TextBox 元素的所需大小。您可以不关心或单独解决此问题:
除了改进您的 MeasureOverride/ArrangeOverride 实现之外,您还可以为 TextBox 使用不同的(例如更轻量级的)ControlTemplate。我会选择重写 MeasureOverride/ArrangeOverride。
关于WPF 文本 block 性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6808642/