ObservableCollection 发生了一些奇怪的事情。
我有以下代码:
private readonly ObservableCollection<DisplayVerse> _display;
private readonly ListBox _box;
private void TransferToDisplay()
{
double elementsHeight = 0;
_display.Clear();
for (int i = 0; i < _source.Count; i++) {
DisplayVerse verse = _source[i];
_display.Add(verse);
elementsHeight += CalculateItemsHeight(i);
if (elementsHeight + Offset > _box.ActualHeight) {
_display.RemoveAt(_display.Count - 1);
break;
}
}
MessageBox.Show(elementsHeight.ToString());
}
private double CalculateItemsHeight(int index)
{
ListBoxItem lbi = _box.ItemContainerGenerator.ContainerFromIndex(index) as ListBoxItem;
return lbi != null ? lbi.ActualHeight : 0;
}
我在这里要做的是控制有多少项目进入 ObservableCollection _display。现在,在这个 for 循环中,您可以看到元素被添加,直到总元素高度(+偏移)大于列表框本身。
现在,这很奇怪,在这个 for 循环之后 elementsHeight 等于 0。(即使 lbi 不为空,CalculateItemsHeight 在所有循环迭代中都返回 0)似乎未创建数据模板中定义的 UI 元素......
然而。
现在,如果我在 _display.Add(verse) 之后放置一些 MessageBoxes,您可以看到 CalculateItemsHeight 实际上返回项目的高度。
for (int i = 0; i < _source.Count; i++) {
DisplayVerse verse = _source[i];
_display.Add(verse);
MessageBox.Show("pause"); // <----- PROBLEM?
elementsHeight += CalculateItemsHeight(i);
if (elementsHeight + Offset > _box.ActualHeight) {
_display.RemoveAt(_display.Count - 1);
break;
}
}
MessageBox.Show(elementsHeight.ToString());
如图所示修改 for 循环后,最后一个 MessageBox实际上显示了所有已处理元素的实际高度。
我的问题是 - UI 元素是什么时候真正创建的?似乎它是在 MessageBox 显示期间的某个地方完成的。这种行为对我来说很奇怪,也许它与线程有关,不确定。
添加到 _display ObservableCollection 显然会立即创建一个项目,而不是它的视觉元素(但是它们是在之后添加的,我只是不知道确切的时间)。如何在不必弹出消息框的情况下执行相同的行为?