2010-03-22 24 views
0

我有一个自定义面板,一个列表框如何从定制儿童失效列表框的布局

<ItemsPanelTemplate x:Key="FloatPanelTemplate"> 
    <Controls:FloatPanel x:Name="CardPanel" /> 
</ItemsPanelTemplate> 

面板使用其X和Y依赖属性勾画出它的孩子。 当FloatPanel被自己使用时,这一切都很好用 - 我正在使用FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.Affects测量子项的依赖项属性以告诉FloatPanel重绘其布局。当我在列表框中使用它(上面的代码)时,它在第一次绘制时很好,但是当我拖动子项(修改项目的X和Y)时,它不会通知Listbox它需要重画FloatPanel的孩子。我认为这个问题与这样一个事实有关,即绑定集合中的每个项目都被一个ListBoxItem包装。

希望我已经描述了我做得很好,有人可以告诉我如何让面板(或其子)告诉它需要再次执行布局例程。正如我所说的一次工作(初始绘制),但拖动项目不起作用(Listbox不知道它的子项已经改变,需要重新布局)。如果我拖动一个项目,然后调整窗口大小,列表框将做一个布局和这些物品被吸引到他们的新地点。

如何通知ListBox(或更重要的是ItemsPanelTemplate中的FloatPanel)它需要执行布局传递?

回答

1

请改用FrameworkPropertyMetadataOptions.AffectsParentMeasure和FrameworkPropertyMetadataOptions.AffectsParentArrange。

那些名字......感谢上帝的智慧,是吧?

正如您所指出的那样,由于ListBoxItem是您的元素的直接布局父级,所以影响父级布局的依赖性属性的更改将不会由进一步位于可视化树上的面板“看到”。

因此,您可能需要做的不幸的是遍历视觉树,直到找到派生于Panel的元素并调用它的InvalidateArrange方法。

DependencyObject obj=this; 
while ((obj=VisualTreeHelper.GetParent(obj)) != null) { 
    Panel p = obj as Panel; 
    if (p != null) { 
     p.InvalidateArrange(); 
     break; 
    } 
} 

这很丑陋,但也许WPF大师会有更好的建议。

+0

忘了提及我已经尝试过这些,但没有奏效。 FloatPanel似乎不是ListBoxItems中FloatElements的父级。 – 2010-03-22 06:34:05

+0

这是真的,但我不知道为什么它甚至可以在第一个布局传递中工作,因为ListBoxItem容器将始终位于面板和项目本身之间。 – Josh 2010-03-22 06:39:33

+0

好点。作为一个测试,我已经把cardPanel.InvalidateVisual();在ItemPanelTemplate中卡面板的mousemove事件上,并在拖动项目时正确重绘面板。 因此,它不是一个小组没有正确绘图的问题,它的问题是孩子们不通知列表框改变了它。 – 2010-03-22 07:16:32

0

你确定你的ListBoxListView面板不似乎呈现一个不正确的尺寸,因为它有...

ScrollViewer.CanContentScroll="True" 

...这是默认值?

当列表控件是在这种模式下,当它被滚动到最下方,有可能是在其面板的底部多余的空格,以确保一个整体项目在顶部一字排开其内部ScrollViewer,这可能看起来像ScrollViewer - 因此列表控制 - 不是自己调整大小。

为了防止空白在面板的底部,您必须启用列表框或ListView控件的逐像素滚动:

ScrollViewer.CanContentScroll="False" 

或代码:

ScrollViewer.SetCanContentScroll(list_ctrl, false); 

参见:WPF ListView non integral scrolling