#windows-phone-7 #silverlight-toolkit #tombstoning
#windows-phone-7 #silverlight-инструментарий #надгробие
Вопрос:
Я пытаюсь работать с элементом управления LongListSelector из инструментария WP7 Silverlight Toolkit. Потребовалось немного поработать, но я наконец-то заставил это работать с моим приложением. К сожалению, у меня возникли некоторые проблемы с правильной обработкой процесса надгробия.
Когда приложение запускает tombstones (или пользователь переходит на другую страницу, выбирая элемент в списке), я сохраняю копию самого верхнего видимого элемента в списке. Я сохраняю его как в переменной класса, так и в коллекции состояний приложения.
ICollection<object> visibleItems = myLongList.GetItemsInView();
_lastItem = null;
if (visibleItems.Count > 0)
_lastItem = visibleItems.First();
IDictionary<string, object> state =
Microsoft.Phone.Shell.PhoneApplicationService.Current.State;
state["IndexByName_LastTopItem"] = _lastItem;
Затем, когда пользователь возвращается на страницу, я проверяю одно из двух значений (состояние или переменная) и использую его для восстановления последнего положения прокрутки.
if (_lastItem == null)
{
if (state.ContainsKey("IndexByName_LastTopItem"))
{
_lastItem = state["IndexByName_LastTopItem"] as Chemical;
}
}
if (_lastItem != null)
Dispatcher.BeginInvoke(() => { myLongList.ScrollTo(_lastItem); });
Это отлично работает, если только приложение tombstones. В этом случае я не получаю никаких ошибок, но список полностью пуст, пока я не коснусь его и не перетащу. Как только я это сделаю, он повторно отобразится вверху списка. Я взглянул на источник элемента управления и обнаружил, что при вызове .scrollTo (объект) не находит соответствия. Дальнейшее расследование показало, что при поиске элемента для прокрутки сравнивается использование == вместо Equals. Я только переопределил Equals, и, по-видимому, default == сравнивает (по дизайну) ссылки. При восстановлении элемента состояния после надгробия ссылки не совпадают.
Я могу переопределить ==, но это кажется неправильным. Я могу изменить и перестроить источник управления, чтобы вместо этого вызывать equals (я пытался, и это сработало), но это было написано людьми намного умнее меня, и мне интересно, может быть, я просто не понимаю.
Есть ли способ лучше?
Ответ №1:
Это исправление, к которому я в конечном итоге пришел…
Поскольку исходный код находится в свободном доступе для инструментария, я закончил редактированием исходного кода LongListSelector для вызова .Равно вместо ==. Кажется, это работает правильно для моего варианта использования, и я подумал, что поделюсь на случай, если кто-нибудь еще сочтет это полезным…
в LongListSelector.cs найдите функцию GetFlattenedIndex (элемент объекта) и замените
if (item == _flattenedItems[index].Item)
с
if (item.Equals(_flattenedItems[index].Item))
а затем в том же файле найдите функцию GetResolvedIndex(object item, out ContentPresenter ContentPresenter) и замените
if (node.Value.Content == item) // Nov 2010 Release
// OR
if (_flattenedItems[index].Item == item) // Feb 2011 Release
с
if (item.Equals(node.Value.Content)) // Nov 2010 Release
// OR
if (item.Equals(_flattenedItems[index].Item)) // Feb 2011 Release
ОБРАТИТЕ внимание, что замена зависит от того, какой набор инструментов вы используете!
Как только вы внесете эти изменения в элемент управления, он будет правильно сопоставлять объекты, указанные в scrollTo (object), даже если ссылки не равны, если вы правильно переопределите Equals для всех типов объектов, отображаемых в вашем LongListSelector. Не забывайте, что это относится к вашему классу группировки, а также к вашему классу элементов, если у вас есть сгруппированный список!
Ответ №2:
Можете ли вы попытаться получить элемент в новом списке?
var _goodReference = myList.FirstOrDefault(x => x.id == _lastItem.Id);
if (_goodReference != null)
Dispatcher.BeginInvoke(() => { myLongList.ScrollTo(_goodReference); });
Комментарии:
1. На первый взгляд это выглядело неплохо. К сожалению, элементы в LongListSelector немного сложнее. Источником списка, по сути, является список <Список<элемент>>, где внешний список — это группировки (отображаются в виде заголовков групп), а внутренний список — элементы для каждой группировки. Таким образом, переменная _lastItem может содержать элемент или список<элемент> в зависимости от текущего положения прокрутки.
2. Можете ли вы обернуть список<Список<Элемент>> в класс с каким-либо пользовательским идентификатором?
3. ДА. Вероятно, вы на пути к решению, которое могло бы сработать. Я просто надеялся получить отзыв о том, что я просто пропустил что-то простое. Восстановление с tombstone кажется излишне сложным. Теперь мне нужно будет обрабатывать восстановление отдельно в зависимости от того, является ли самый верхний видимый элемент заголовком группы или элементом. Это не ракетостроение, но, похоже, его можно улучшить с помощью чего-то такого простого, как scrollTo (intPositionOffsetForTopmostVisibleItem).