WPF ListBox сохраняет вид на SelectedItem при изменении стиля - PullRequest
0 голосов
/ 12 августа 2010

У меня есть 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), и я меняю вид, видимая область показанного списка будет сброшена до первого индекса (но выбранный элемент все еще выбран, просто не показано).

Я попытался решить эту проблему, используя решение здесь , чтобы прокрутить до выбранного элемента и установить его в центр. Но в настоящее время бывают ситуации, когда поведение кажется нестабильным, поскольку происходит то, что первый элемент в списке отображается первым, а затем переходит к выбранному элементу. Есть ли другие альтернативы для этого?

Спасибо!

Ответы [ 2 ]

1 голос
/ 13 августа 2010

То, что вы ищете, не слишком отличается от того, что я написал в моем предыдущем ответе.

Два отличия:

  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 и обновить HorizontalOffset и VerticalOffset, чтобы привести новый контейнер в ту же позицию, что и старый.

Причина, по которой это будет работать без мерцания, заключается в том, что все здесь происходит синхронно, поэтому никакие диспетчерские операции с приоритетом рендеринга не будут выполняться. Стоимость такова, что UpdateLayout () сравнительно дорогой.

Также обратите внимание, что если какой-либо из ваших отдельных элементов реализован таким образом, что он меняет свой размер после первоначальной меры / аранжировки (например, при обратном вызове диспетчера), то вам нужно будет дважды изменить положение: один раз в синхронном коде, затем снова в обратном вызове диспетчера. В этом случае единственный надежный общий метод, который я знаю, чтобы предотвратить мерцание, это исправить реализацию элементов, чтобы получить их размер прямо перед завершением первоначального макета.

0 голосов
/ 12 августа 2010

Это дело вкуса, но я бы запускал анимации постепенного исчезновения и постепенного появления, возможно, 0,15 или 0,2 секунды, и выполнял переключение шаблона, пока оно исчезло.Это сократит прокрутку и сгладит очень резкий переключатель в макете.

...