在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的顺序已经从View控制中发生了变化。那么为什么不举办活动呢?如果它不胜,那么在数据库中持久保存ListView订单的最佳做法是什么?
更新
这个问题实际上比我想象的要大......似乎ListView.CollectionChanged事件在添加项目时也没有触发!它在应用程序启动时执行,并从数据库加载,但不是由用户从UI添加。这很奇怪,因为使用完全相同的方法执行项目的添加。来自数据库:
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;
}
您会看到此递归方法调用ViewModel的AddItem()方法来添加子项(具有相同类型)。我还有一个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层本身调用时会引发事件?
答案 0 :(得分:1)
事实证明,像往常一样,错误完全是我的。
发生这种情况是因为事件处理方法ListItems_CollectionChanged正在断开连接。造成这种情况的原因是由于Sort方法正在替换底层连接。我已经解决了这个问题,如果需要,可以在属性的setter中添加事件处理程序(当然还要删除任何未使用的事件处理程序)。