I have a situation in a new WinRT app where I need to manage an ID property on a collection of objects. Essentially I’m holding the unique ID for each object which I need to increment for each new object added. This is because I’ll be serializing to XML to save the data so need to manage this ID myself. If I was using SQL it would be an auto incrementing field.
The best way I could come up with was to set this using a method called from the constructor and then have a collection changed handler help me to update the value each time.
Here is the view model class:
using MM.Models;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
namespace MM.ViewModels
{
public class VehiclesViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public VehiclesViewModel()
{
Vehicles = new ObservableCollection<Vehicle>();
NewVehicle = new Vehicle();
NextVehicleID = CalculateHighestID(Vehicles.AsQueryable()) + 1;
Vehicles.CollectionChanged += new NotifyCollectionChangedEventHandler(VehicleCollectionChanged);
}
private ObservableCollection<Vehicle> _vehicles;
public ObservableCollection<Vehicle> Vehicles
{
get
{
return _vehicles;
}
set
{
if (_vehicles != value)
{
_vehicles = value;
PropertyChanged(this, new PropertyChangedEventArgs("Vehicles"));
}
}
}
void VehicleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
NextVehicleID += 1;
}
}
public Vehicle NewVehicle { get; set; }
private int _nextVehicleID;
public int NextVehicleID
{
get
{
return _nextVehicleID;
}
private set
{
_nextVehicleID = value;
PropertyChanged(this, new PropertyChangedEventArgs("NextVehicleID"));
}
}
private int CalculateHighestID(IQueryable<Vehicle> vehicles)
{
var query = vehicles.OrderByDescending(v => v.VehicleID).FirstOrDefault();
if (query != null)
{
return query.VehicleID;
}
else
{
return 1;
}
}
}
}
and here is a text button click method I added on the xaml page to add an item.
private void Button_Click_1(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
vm.Vehicles.Add(new Vehicle { VehicleID = vm.NextVehicleID });
}
However, the VehicleCollectionChanged is never called. As a test I used the same code to add a vehicle from the constructor method and that did work.
Can anyone explain why the method would not be called with adding a vehicle from the xaml button click?
Also, is there a better overall approach to keep track of an ID value for the next record?
Does your ID have to be an
int(or incremental for that matter)? Could it be a GUID? At least then you could leave the creation up to theVehicleclass. As for why the event isn’t being called, are you ever re-assigning the “Vehicles” property on your viewmodel? Is there a reason you have a public “set” for that property? You could potentially set a new ObservableCollection to “Vehicles” and not 1) unhook from the old event and 2) hook-up the CollectionChanged event to the new collection.