В приложении Windows Phone 8.1 (нацеленном на среду выполнения, а не на Silverlight) у меня есть ObservableCollection, привязанный к ListView, определенный следующим образом:
<ListView ItemsSource="{Binding ListItems, Mode=TwoWay}" CanReorderItems="True" ReorderMode="Enabled">
<ListView.ItemTemplate>
...etc...
В конструкторе ViewModel у меня также есть
ListItems.CollectionChanged += ListItems_CollectionChanged;
который вызывает событие всякий раз, когда добавляются и удаляются какие-либо элементы, однако все это обрабатывается с виртуальной машины, а не с представления. К сожалению, событие не возникает при изменении порядка элементов. Я настроил это, переместил некоторые элементы, добавил точку останова в обработчике событий и добавил элемент, и я вижу, что базовый порядок ObservableCollection изменился в соответствии с управлением из представления. Так почему же событие не поднимается? И если это не так, как лучше всего сохранить порядок ListView в базе данных?
ОБНОВЛЕНИЕ:
Проблема на самом деле больше, чем я думал... кажется, что событие ListView.CollectionChanged также не срабатывает при добавлении элемента! Это происходит, когда приложение запускается и загружает их из базы данных, но не при добавлении пользователем из пользовательского интерфейса. Это очень странно, потому что добавление элементов выполняется точно таким же методом. Из базы данных:
private ViewModel MapFromModel(Item model, SQLiteAsyncConnection connection)
{
var viewModel = new ViewModel
{
Id = model.Id,
Text = model.Text,
Description = model.Description,
Added = model.Added,
Completed = model.Completed,
DueOn = model.DueOn,
ParentId = model.ParentId,
DisplayOrderNumber = model.DisplayOrderNumber,
IsNew = false
};
foreach (
var childViewModel in
connection.Table<Item>()
.Where(ci => ci.ParentId == viewModel.Id)
.ToListAsync()
.Result.Select(childItem => MapFromModel(childItem, connection)))
{
if (!_cache.Contains(childViewModel))
_cache.Add(childViewModel);
viewModel.AddItem(childViewModel);
}
return viewModel;
}
Вы видите, что этот рекурсивный метод вызывает метод AddItem() ViewModel для добавления дочерних элементов (которые имеют один и тот же тип). У меня также есть ICommand, привязанный к кнопке для добавления других элементов:
public void Execute(object parameter)
{
var viewModel = parameter as ViewModel;
if (viewModel == null) return;
AddItem(viewModel);
}
public static void AddItem(ViewModel viewModel)
{
// The DisplayOrderNumber of the new item needs to be the max of the current collection + 1.
var displayOrderNumber = viewModel.ListItems.Any()
? viewModel.ListItems.Max(ci => ci.DisplayOrderNumber) + 1
: 0;
var newText = string.Format("{0} {1}",
viewModel.Id == Guid.Empty ? "List" : "Item", displayOrderNumber + 1);
var newItem = new ViewModel
{
Text = newText,
NewText = newText,
ParentId = viewModel.Id,
InEditMode = true,
Added = DateTime.Now,
DisplayOrderNumber = displayOrderNumber,
IsNew = true
};
viewModel.AddItem(newItem);
viewModel.Save();
}
Так почему же метод AddItem() должен генерировать событие при вызове из сервисного уровня, а не из самого уровня ViewModel?