2010-08-12 56 views
0

我有一個ListBox,其Style和ItemTemplate在代碼隱藏後在點擊特定按鈕時發生變化。WPF列表框保留對SelectedItem的風格變化

listbox.ItemTemplate = FindResource("dataTemplateView1") as DataTemplate; 
listbox.Style = FindResource("listBoxStyle1") as Style; 

有三種可能的意見,所以有三組數據模板和樣式。 DataTemplate包含一些文本和縮略圖(每組不同的大小)。樣式只是將ItemsPanelTemplate更改爲WrapPanel,StackPanel(水平)和StackPanel(垂直)。例如:

<Style x:Key="listBoxStyle1" TargetType={x:Type ListBox}"> 
    <Setter Property="ItemsPanel"> 
     <Setter.Value> 
      <ItemsPanelTemplate> 
       <WrapPanel /> 
      </ItemsPanelTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

的問題是,當我有一個選擇的項目(表示具有索引20項目)和I改變視圖,示出將重置回到第一索引列表框的可見區域(但所選項目仍然被選中,只是沒有顯示)。

我試圖解決這個問題,使用解決方案here滾動到選定的項目並將其設置爲居中。但是目前,有些時候行爲似乎不穩定,因爲發生的情況是listbox中的第一個項目首先顯示,然後跳轉到選定的項目。任何其他的替代品呢?

謝謝!

回答

1

你在找什麼和我在我以前的回答中寫的沒什麼不同。

兩個差異:

  1. 你的目標似乎是從移動保持目前的項目,而不是把它移動到中心。這實際上是可能的,並且與居中一樣簡單。
  2. 您的代碼的時間允許暫時顯示未滾動的版本,導致跳動。

這些問題都可以解決一起如下(參考我前面的相關代碼細節的答案):

  1. 使用box.ItemContainerGenerator.ContainerFromItem(box.SelectedItem)來獲得該項目的容器
  2. 呼叫container.TransformToAncestor(box).Transform(new Point())得到容器的相對於列表框的左上角。 (如果你喜歡保持項目靜止的中心,使用new Point(container.DesiredSize.Width/2, container.DesiredSize.Height/2)代替。)
  3. 更改ItemTemplate中或樣式,根據需要
  4. 強制立即重新測量(最簡單的方式做,這是通過調用UpdateLayout請)再次
  5. 使用box.ItemContainerGenerator.ContainerFromItem(box.SelectedItem)來獲得該項目的容器
  6. 呼叫container.TransformToAncestor(box).Transform(new Point())再次向新容器的左上角相對角球到列表框中
  7. 使用從我的其他答案找到IScrollInfo和更新Horizo​​ntalOffset和代碼VerticalOffset將新容器置於與舊容器相同的位置。

這個工作沒有閃爍的原因是這裏的一切都是同步發生的,所以Render優先級的任何調度器操作都不會運行。成本是UpdateLayout()比較昂貴。還需要注意的是,如果你的任何單個項目被實現,使得它在初始度量/排列之後(例如在調度器回調中)改變其大小,那麼你將需要重新定位兩次:一旦進入同步代碼,然後再次在調度員回調中。在這種情況下,我所知道的防止閃爍的唯一可靠的通用方法是在初始佈局完成之前修正項目的實現以獲取其大小。

+0

謝謝你的上述! – 2010-08-13 09:21:52

0

這是一個有趣的問題,但我會觸發淡出和淡入淡出的動畫,可能是0.15秒或0.2秒,然後在淡出模板時進行模板切換。這將隱藏滾動並平滑佈局中的其他非常突然的切換。

+0

好的,謝謝。將檢查這個建議。 – 2010-08-12 09:24:13