2010-03-22 25 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