好的,为了说明的目的,下面我创建了一个 的子类ListBoxItem
和 的一个子类,它通过覆盖和ListBox
来使用它作为它的容器。IsItemItsOwnContainerOverride
GetContainerForItemOverride
现在,当窗口首次出现时,正如预期的那样,MeasureOverride
在每个ListBoxItem
(使用 Infinity,Infinity)ArrangeOverride
上调用,然后在每个项目上调用。
但是,当调整ListBox
, only的大小时,不会ArrangeOverride
调用,即使 width 属性的元数据设置为。ListBoxItem
MeasureOverride
AffectsMeasure
注意:我知道我可以通过设置
ScrollViewer.HorizontalScrollbarVisibility
为“禁用”来解决这个问题,在这种情况下MeasureOverride
会按预期调用,因为滚动设置会强制项目与列表框的宽度匹配,因此自然会重新触发。但是,我仍在试图弄清楚为什么默认情况下不调用 Measure,因为Width
属性的元数据AffectsMeasure
设置了标志,并且宽度正在通过ArrangeOverride
步骤发生变化。
该标志是否只是对其容器的提示,并且对于放置在其中的控件,ScrollViewer
它会被忽略吗?我的猜测是,除非您禁用滚动,否则控件有无限的可用区域,因此一旦测量它们,就无需再次重新测量它们。但是禁用水平滚动并且您说宽度不是无限的,因此MeasureOverride
再次调用。但这只是一个猜测,尽管是合乎逻辑的。
这是可以使用的示例代码。创建一个新的 WPF 项目并将其粘贴到窗口的 CodeBehind 中并查看调试输出。接下来,设置 HorizontalScrollbarVisibility 标志,您会看到它确实被调用了。
public partial class MainWindow : Window
{
public MainWindow(){
InitializeComponent();
var items = new List<object>(){ "This is a really, really, really, really long sentence"};
var lbx = new ListBoxEx { ItemsSource = items };
this.Content = lbx;
}
}
public class ListBoxEx : ListBox
{
protected override bool IsItemItsOwnContainerOverride(object item){
return (item is ListBoxItemEx);
}
protected override DependencyObject GetContainerForItemOverride(){
return new ListBoxItemEx();
}
}
public class ListBoxItemEx : ListBoxItem
{
protected override Size MeasureOverride(Size availableSize){
Console.WriteLine("MeasureOverride called with " + availableSize);
return base.MeasureOverride(availableSize);
}
protected override Size ArrangeOverride(Size finalSize){
Console.WriteLine("ArrangeOverride called with " + finalSize);
return base.ArrangeOverride(finalSize);
}
}