好的,为了便于说明,下面我创建了一个ListBoxItem
的子类和一个ListBox
的子类,它通过覆盖IsItemItsOwnContainerOverride
和GetContainerForItemOverride
将其用作容器。
现在,当窗口首次出现时,正如预期的那样,MeasureOverride
会在每个ListBoxItem
(使用Infinity,Infinity)上调用ArrangeOverride
,然后在每个项目上调用ListBox
。
但是,在调整ArrangeOverride
的大小时,ListBoxItem
上只调用MeasureOverride
,而AffectsMeasure
调用ScrollViewer.HorizontalScrollbarVisibility
,即使width属性的元数据设置为{{1} }}
NotE:我知道我可以通过将
MeasureOverride
设置为“已禁用”来解决此问题,在这种情况下,Width
会按预期调用,因为滚动设置会强制项目与列表框的宽度相匹配因此自然会重新开火。但是,我仍然试图弄清楚为什么默认情况下不会调用Measure,因为AffectsMeasure
属性的元数据设置了ArrangeOverride
标志,宽度通过{{1}更改}步骤。
该标志只是其容器的提示吗?如果控件放在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);
}
}
答案 0 :(得分:0)
好吧,我认为答案是它没有解雇因为测量通过影响了面板,而不是项目,并且面板本身没有调整大小,所以没有理由重新开始 - 测量它的孩子。
然而,当将ScrollViewer.HorizontalScrollbarVisibility
设置为Disabled
时,面板的宽度会跟踪ListBox的宽度,而不是其内容,因此需要重新测量子项,因此&#39 ;为什么他们在那种情况下。