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

NextId = 1を設定する代わりに、保存したXMLファイルの内容に基づいて設定することをお勧めします。そうすれば、常に1から始まるとは限りません。

于 2012-12-05T19:01:49.607 に答える
1

あなたのIDはint(またはそれに関しては増分)である必要がありますか?GUIDでしょうか?少なくとも、作成はVehicleクラスに任せることができます。イベントが呼び出されない理由については、ビューモデルの「Vehicles」プロパティを再割り当てしたことがありますか?あなたがそのプロパティのパブリック「セット」を持っている理由はありますか?新しいObservableCollectionを「Vehicles」に設定する可能性があります。1)古いイベントからフックを解除したり、2)CollectionChangedイベントを新しいコレクションにフックアップしたりすることはできません。

于 2012-12-05T20:52:33.320 に答える