如何在caliburn.micro中对子VM进行逻辑删除

时间:2011-08-23 14:15:24

标签: windows-phone-7 caliburn.micro tombstoning

我在Caliburn.Micro中遇到了一些墓碑问题。我有一个枢轴控制,我们在每个枢轴控制项中都有一个列表框。我只是想使用caliburn.micro的内置支持来保存列表

我有一个MainViewModel,它将在飞行员控件中初始化一系列子VM

public class MainViewModel : Conductor<IScreen>.Collection.OneActive
{
    private readonly Func<QiushiListViewModel> _createQiushiListViewModel;
    private readonly INavigationService _navigationService;
    private readonly IEventAggregator _events;
    readonly IWindowManager _windowManager;
    readonly Func<AboutUsViewModel> _aboutUsViewModelFactory;
    readonly Func<SettingsViewModel> _settingsViewModelFactory;

    public MainViewModel(Func<QiushiListViewModel> createQiushiListViewModel, 
                        INavigationService navigationService,
                        IEventAggregator events,
                        IWindowManager windowManager, 
                        Func<AboutUsViewModel> aboutUsViewModelFactory,
                        Func<SettingsViewModel> settingsViewModelFactory
                        )
    {
        _createQiushiListViewModel = createQiushiListViewModel;
        _navigationService = navigationService;
        _events = events;
        _windowManager = windowManager;
        _aboutUsViewModelFactory = aboutUsViewModelFactory;
        _settingsViewModelFactory = settingsViewModelFactory;
    }

    protected override void OnInitialize()
    {
        if(Items.Count==0)
        {
            Enumerable.Range(1, 5).Apply(x =>
            {
                var pivot = _createQiushiListViewModel();
                switch (x)
                {
                    case 1:
                        pivot.DisplayName = AppResources.App_Pivot_First;
                        pivot.Section = "late";
                        break;
                    case 2:
                        pivot.DisplayName = AppResources.App_Pivot_Second;
                        pivot.Section = "pic";
                        break;
                    case 3:
                        pivot.DisplayName = AppResources.App_Pivot_Third;
                        pivot.Section = "8hr";
                        break;
                    case 4:
                        pivot.DisplayName = AppResources.App_Pivot_Fourth;
                        pivot.Section = "week";
                        break;
                    case 5:
                        pivot.DisplayName = AppResources.App_Pivot_Fifth;
                        pivot.Section = "month";
                        break;
                    default:
                        break;
                }
                Items.Add(pivot);
            });
            ActivateItem(Items[0]);    
        }
        ...
    }

}

子VM如下

public class QiushiListViewModel : 
        Screen, 
        IHandle<RefreshListMessage>, 
        IHandle<RetrieveNewItemsMessage>, 
        IHandle<TaskCompleted<EmailComposeTask>>, 
        IHandle<TaskCompleted<SmsComposeTask>>
    {
        private const int DefaultItemsPerPage = 20;
        readonly IEventAggregator _events;
        private readonly INavigationService _navigationService;

        public QiushiListViewModel(
            IEventAggregator events,
            INavigationService navigationService)
        {
            ItemsPerPage = DefaultItemsPerPage;
            _events = events;
            _navigationService = navigationService;
            _qiushiItems = new SortableObservableCollection<QiushiItem>();
        }

        protected override void OnActivate()
        {
            _events.Subscribe(this);
            base.OnActivate();

        }

        protected override void OnDeactivate(bool close)
        {
            SelectedItem = null;
            _events.Unsubscribe(this);
            base.OnDeactivate(close);
        }

        public string Section { get; set; }

        public int Page { get; set; }

        public int ItemsPerPage { get; set; }

        public int CountOfItemsUpdated { get; set; }

        public bool HasErrors { get; set; }

        private SortableObservableCollection<QiushiItem> _qiushiItems;

        public IEnumerable<QiushiItem> QiushiItems
        {
            get { return _qiushiItems; }
        }

        private bool _isBusy;
        public bool IsBusy
        {
            get { return _isBusy; }
            set
            {
                if (_isBusy == value)
                    return;
                _isBusy = value;
                NotifyOfPropertyChange(() => IsBusy);
            }
        }

        private bool _canLoadMore;
        public bool CanLoadMore
        {
            get { return _canLoadMore; }
            set
            {
                if (_canLoadMore == value)
                    return;
                _canLoadMore = value;
                NotifyOfPropertyChange(() => CanLoadMore);
            }
        }

        private QiushiItem _selectedItem;
        public QiushiItem SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                if(_selectedItem == value)
                    return;
                _selectedItem = value;
                NotifyOfPropertyChange(() => SelectedItem);
            }
        }

    ...
    }

我尝试实现QiushiListViewModelStorage

public override void Configure()
        {
            Id(x=>x.Section);

            Property(x => x.CanLoadMore).InAppSettings();
            Property(x => x.IsBusy).InAppSettings();
            Property(x => x.Page).InAppSettings();
            Property(x => x.QiushiItems).InAppSettings();
        }

它不起作用,没有任何反应,没有错误,没有例外。 QiushiItem类是可序列化的,请参阅以下代码段

[DataContract]
    public class QiushiItem : IComparable, IEqualityComparer<QiushiItem>
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Content { get; set; }
        [DataMember]
        public string ImageUrl { get; set; }
        [DataMember]
        public string MobileImageUrl { get; set; }
        [DataMember]
        public string Tags { get; set; }
        [DataMember]
        public int Tops { get; set; }
        [DataMember]
        public int Flops { get; set; }
        [DataMember]
        public int CommentsCount { get; set; }
        [DataMember]
        public DateTime PublishDateTime { get; set; }

        public string Age
        {
            get
            {
                if (DateTime.Now.Subtract(PublishDateTime).Minutes < 10)
                    return AppResources.App_TimeSpan_JustNow;
                if (DateTime.Now.Subtract(PublishDateTime).Minutes < 30)
                    return AppResources.App_TimeSpan_Recently;
                if (DateTime.Now.Subtract(PublishDateTime).Minutes < 60)
                    return AppResources.App_TimeSpan_Half_Hour_Ago;
                if (DateTime.Now.Subtract(PublishDateTime).Hours < 2)
                    return AppResources.App_TimeSpan_An_Hour_Ago;
                if (DateTime.Now.Subtract(PublishDateTime).Hours < 3)
                    return AppResources.App_TimeSpan_Two_Hours_Ago;
                if (DateTime.Now.Subtract(PublishDateTime).Hours < 24)
                    return AppResources.App_TimeSpan_In_One_Day;
                if (DateTime.Now.Subtract(PublishDateTime).Days < 2)
                    return AppResources.App_TimeSpan_One_Day_Ago;
                if (DateTime.Now.Subtract(PublishDateTime).Days < 3)
                    return AppResources.App_TimeSpan_Two_Days_Ago;
                if (DateTime.Now.Subtract(PublishDateTime).Days < 7)
                    return AppResources.App_TimeSpan_In_A_Week;
                return DateTime.Now.Subtract(PublishDateTime).Days < 30 ? AppResources.App_TimeSpan_In_A_Month : AppResources.App_TimeSpan_Long_Ago;
            }
        }

        int IComparable.CompareTo(object right)
        {
            if (!(right is QiushiItem)) throw new ArgumentException(AppResources.Ex_QiushiItem_Comparable_Argument_Exception, "right");
            QiushiItem righItem = (QiushiItem) right;
            return CompareTo(righItem);
        }

        public int CompareTo(QiushiItem right)
        {
            return Id.CompareTo(right.Id);
        }

        // Relational Operators.
        public static bool operator <(QiushiItem left, QiushiItem right)
        {
            return left.CompareTo(right) < 0;
        }
        public static bool operator <=(QiushiItem left, QiushiItem right)
        {
            return left.CompareTo(right) <= 0;
        }
        public static bool operator >(QiushiItem left, QiushiItem right)
        {
            return left.CompareTo(right) > 0;
        }
        public static bool operator >=(QiushiItem left, QiushiItem right)
        {
            return left.CompareTo(right) >= 0;
        }

        private static DateTimeComparer _datetimeComparer;
        public static IComparer DateTimeCompare
        {
            get
            {
                if (_datetimeComparer == null)
                    _datetimeComparer = new DateTimeComparer();
                return _datetimeComparer;
            }
        }

        private class DateTimeComparer : IComparer
        {
            #region IComparer Members
            int IComparer.Compare(object left, object right)
            {
                if (!(left is QiushiItem))
                    throw new ArgumentException(AppResources.Ex_QiushiItem_Comparable_Argument_Exception, "left");
                if (!(right is QiushiItem))
                    throw new ArgumentException(AppResources.Ex_QiushiItem_Comparable_Argument_Exception, "right");
                QiushiItem leftItem = (QiushiItem)left;
                QiushiItem rightItem = (QiushiItem)right;
                return leftItem.PublishDateTime.CompareTo(
                 rightItem.PublishDateTime);
            }
            #endregion

        }

        public bool Equals(QiushiItem x, QiushiItem y)
        {
            if (x.Id == y.Id)
                return true;
            return false;
        }

        public int GetHashCode(QiushiItem obj)
        {
            return obj.Id.GetHashCode();
        }
    }

除此之外,我还尝试使用自定义序列化

public override void Configure()
        {
            Id(x=>x.Section);
            Property(x => x.QiushiItems).InAppSettings();
            Property(x => x.QiushiItems).InAppSettings().Configure(x =>
                                                                       {
                                                                           x.Save = SaveStrokes;
                                                                           x.Restore = RestoreStrokes;
                                                                       });
        }

        void SaveStrokes(QiushiListViewModel vm, Func<string> serialize, StorageMode nMode)
        {
            IsolatedStorageHelper.SaveObject(vm.Section, vm.QiushiItems);
        }

        void RestoreStrokes(QiushiListViewModel vm, Func<string> serialize, StorageMode nMode)
        {
            // use IsolatedStorageSettings.ApplicationSettings[vm.DisplayName + "ThePropertyKey"] 
            // to check if the key exists, and if it is there get the serialized data and deserialize
            if (vm.Section == null)
                return;
            if(IsolatedStorageSettings.ApplicationSettings[vm.Section]!=null) 
                IsolatedStorageHelper.GetObject<IEnumerable<QiushiItem>>(vm.Section);
        }
但是,问题是有5个QiushiListViewModels,当墓碑化时,保存/恢复会被调用5次,我分不清哪个是哪个。

有什么建议吗?

提前致谢-Peng

1 个答案:

答案 0 :(得分:0)

我不是WP7专家,但您是否尝试使用[SurviveTombstone]属性修饰类和属性?

  

[SurviveTombstone]属性是一个简单的开箱即用   实现[ITombstone]界面,了解如何走路   对象图,检查它的属性并坚持它们。

Tombstoning ”标题下的更多详细信息: http://devlicio.us/blogs/rob_eisenberg/archive/2010/08/07/caliburn-micro-soup-to-nuts-pt-4-working-with-windows-phone-7.aspx