簡體   English   中英

WPF ListBox在樣式更改時保留對SelectedItem的視圖

[英]WPF ListBox retain view on SelectedItem on change of Style

我有一個ListBox,其樣式和ItemTemplate在單擊特定按鈕后會在代碼后更改。

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的項目)並更改視圖時,顯示的列表框的可見區域將重置為第一個索引(但選定的項目仍處於選中狀態,只是未顯示) 。

我嘗試使用此處的解決方案來解決此問題,方法是滾動到所選項目並將其設置為居中。 但是當前,該行為有時看起來很不穩定,因為發生的情況是首先顯示了列表框中的第一個項目,然后才跳轉到所選項目。 還有其他選擇嗎?

謝謝!

您正在尋找的內容與我在先前的答案中寫的內容沒有太大不同。

兩個區別是:

  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以將新容器移到與舊容器相同的位置。

之所以可以正常運行,是因為這里的所有內容都是同步發生的,因此不會運行“渲染”優先級的調度程序操作。 代價是UpdateLayout()比較昂貴。

還要注意,如果實現了您的任何單個項目,使其在初始度量/安排后(例如,在分派器回調中)更改了大小,則您將需要重新放置兩次:一次在同步代碼中,然后一次在調度程序回調。 在這種情況下,我知道唯一可以防止閃爍的確定方法是在初始布局完成之前修復項目的實現以使其大小正確。

這是一個品味問題,但是我可能會觸發.15或.2秒的淡出和淡入動畫,並在淡出時進行模板切換。 這樣既可以隱藏滾動,又可以平滑布局中原本非常突然的切換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM