Windows Phone 8.1 ListView.ReorderMode не уведомляет ObservableCollection

В приложении 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?


person MrShoes    schedule 15.07.2014    source источник


Ответы (1)


Выходит, как обычно, вина была целиком на мне.

Это происходило из-за отключения метода обработки событий ListItems_CollectionChanged. Причина этого заключалась в том, что метод Sort заменял базовое соединение. Я обошел эту проблему, добавив при необходимости обработчик событий в установщик свойства (и, конечно же, удалив все неиспользуемые обработчики событий).

person MrShoes    schedule 16.07.2014