0

我在一个新的 WinRT 应用程序中遇到了一种情况,我需要管理对象集合上的 ID 属性。本质上,我持有每个对象的唯一 ID,我需要为每个添加的新对象递增。这是因为我将序列化为 XML 以保存数据,因此需要自己管理此 ID。如果我使用 SQL,它将是一个自动递增字段。

我能想出的最好方法是使用从构造函数调用的方法来设置它,然后让集合更改处理程序帮助我每次更新值。

这是视图模型类:

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;
            }
        }

    }
}

这是我在xaml页面上添加的文本按钮单击方法以添加项目。

private void Button_Click_1(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    vm.Vehicles.Add(new Vehicle { VehicleID = vm.NextVehicleID });
}

但是,永远不会调用 VehicleCollectionChanged。作为测试,我使用相同的代码从构造函数方法添加车辆,并且确实有效。

谁能解释为什么通过单击 xaml 按钮添加车辆时不会调用该方法?

此外,是否有更好的整体方法来跟踪下一条记录的 ID 值?

4

2 回答 2

1

在您的车辆类中保留一个计数器怎么样?

public class Vehicle
{
    static int NextId = 1;
    static object IdLock = new Object();

    public int VehicleId { get; set; }
    ...

    public Vehicle(int nextId = 0)
    {
         // can probably use interlocked increment instead
         // of keeping a separate lock object
         lock (IdLock)
         {
             if (nextId == 0)
             {
                 VehicleId = NextId++;
             }
             else
             {
                 NextId = nextId;
                 VehicleId = nextId;
             }
         }
    }
    ...
}

您可能希望根据保存的 XML 文件中的内容来设置它,而不是设置 NextId = 1。这样,它并不总是从 1 开始。

于 2012-12-05T19:01:49.607 回答
1

您的 ID 是否必须是一个int(或增量)?它可能是一个 GUID 吗?至少那时你可以把创作留给Vehicle班级。至于为什么没有调用事件,您是否曾经在视图模型上重新分配“车辆”属性?您是否有理由为该属性设置公共“设置”?您可能会将新的 ObservableCollection 设置为“Vehicles”,而不是 1)从旧事件中取消挂钩,以及 2)将 CollectionChanged 事件连接到新集合。

于 2012-12-05T20:52:33.320 回答