В приложение за Windows Phone 8.1 (насочено към Runtime, а не към Silverlight), имам ObservableCollection, свързан към ListView, дефиниран по следния начин:
<ListView ItemsSource="{Binding ListItems, Mode=TwoWay}" CanReorderItems="True" ReorderMode="Enabled">
<ListView.ItemTemplate>
...etc...
В конструктора на ViewModel също имам
ListItems.CollectionChanged += ListItems_CollectionChanged;
което повдига събитието всеки път, когато се добавят и изтриват елементи - обаче, всичко това се обработва от VM, а не от View. За съжаление, събитието не се повдига, когато артикулите се пренареждат. Настроих това, преместих някои елементи, добавих точка на прекъсване в манипулатора на събития и добавих елемент и мога да видя, че основният ред на 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() трябва да повдига събитието, когато се извиква от Service Layer, но не и от самия ViewModel слой?