Замораживание listboxitem при добавлении элементов

У нас есть ListBox, который имеет несколько элементов. Элементы вставляются в ListBox через ObservableCollection. Некоторые из этих элементов можно редактировать прямо в ListBox. Однако, если элемент добавлен в индекс < отредактированный индекс объекта, весь контент ListBox перемещается вниз.

Нам нужно сделать следующее: если элемент находится в режиме редактирования, мы хотели бы заморозить его позицию на экране. Это нормально, если элементы добавляются в коллекцию, а пользовательский интерфейс вокруг элемента изменяется. Но позиция элемента должна оставаться постоянной на экране.

Единственное, что мне удалось сделать до сих пор, - это присоединить к событию ScrollChanged и, самое большее, использовать методы BringIntoView или ScrollIntoView, чтобы гарантировать, что элемент всегда отображается где-то в пользовательском интерфейсе, но я не могу заблокируйте его положение.

Кто-нибудь сделал что-то подобное и помог?

Ответ 1

Я думаю, что следующее решение вашей проблемы:

  • При входе в режим редактирования держите ссылку на объект, который вы редактируете, его индекс в списке и ScrollViewer HorizontalOffset.

  • В обработчике события ObservableCollection.CollectionChanged найдите новый индекс объекта, который вы редактируете, если индекс изменился, замените отредактированный элемент на тот, который теперь занимает его место (или какая-то другая логика, если вы хотите соблюдайте определенный порядок). Затем, если ScrollViewer.HorizontalOffset изменился, переместите его обратно на указанное смещение.

Это позволит убедиться, что элемент, который вы редактируете, всегда будет находиться в том же месте в списке и в пользовательском интерфейсе.

Надеюсь, это поможет вам.

Ответ 2

Вы всегда можете принудительно добавлять элементы к концу своей коллекции. В противном случае, я думаю, что вы на правильном пути, прокручивая ScrollViewer. При входе в режим редактирования отслеживайте текущее горизонтальное смещение.


 ScrollViewer sv = listBox.GetScrollViewer();
 double indexPos =  sv.HorizontalOffset;

Однако, я думаю, вам было бы лучше подключиться к событию ObservableCollection.CollectionChanged. Когда событие срабатывает, проверьте, было ли новое значение вставлено над вашим "режимом редактирования". Если это так, выполните следующий код.


 ScrollViewer sv = listBox.GetScrollViewer();
 sv.ScrollToHorizontalOffset(indexPos+1); // This will obviously require an offset 

Ответ 3

Проблема в том, что вы просто не хотите, чтобы она двигалась? Или проблема в том, что вы ссылались на указанный элемент по его номеру индекса, а изменение индекса вызывает другие проблемы при применении изменений (например, применяя их к элементу, который теперь находится в предыдущем индексе)?

Если проблема в том, что изменение индекса вызывает проблемы в коде, я бы прекратил использовать индекс и вместо этого получал ссылку на объект. Позже вы всегда можете получить индекс элемента, если найдете, что вам это нужно.

Ответ 4

Можно ли переключиться на ListView и использовать EnsureVisible?

Ответ 5

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