anakic/Jot

Persistent bug with Caliburn.Micro

Opened this issue · 2 comments

I'm using WPF, .Net Core 3.1 and Caliburn.Micro 4.0.117-alpha. I encountered a persistent bug while trying to implement Screen class to my Model. This is how my "stuff" looks like:
BindableCollection<TestModel> Test = new BindableCollection<TestModel>(); (The same happens with ObservableCollection<>)
In my constructor:

            Persistence.Tracker.Configure<MainViewModel>()
                .Id(p => p.WindowName, includeType: false)

                .Property(p => p.Test, "test")
                .PersistOn(nameof(PropertyChanged));

My TestModel:

    public class TestModel : Screen
    {
        public string Test { get; set; }
    }

When adding item to Test, this is what I get in .json file:

  {
    "Type": "Caliburn.Micro.BindableCollection`1[[yeye.Models.TestModel, yeye, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Caliburn.Micro.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null",
    "Name": "test",
    "Value": [
      {}
    ]
  }

So it's empty value, however, If I remove Screen class, it works perfectly. The reason why I want to implement the class is so I can use NotifyOfPropertyChange method. Obviously, I could implement my own NotifyOfPropertyChange method. Just pointing it out because it was a nightmare to debug it haha.

Cheers for reporting it. I'm not having any such issues though. The following setup seems to work fine:

public class MainViewModel : Screen
    {
        string abc;
        public string Abc { get => abc; set { abc = value; NotifyOfPropertyChange("ABC"); } }

        public bool CanStart(string abc)
        {
            return abc.Length > 3;
        }
        public void Start(string abc)
        {
            MessageBox.Show("Hura: " + abc);
        }
    }
public class HelloBootstrapper : BootstrapperBase
    {
        private readonly SimpleContainer _container = new SimpleContainer();
        public HelloBootstrapper()
        {
            Initialize();
        }

        protected override void OnExit(object sender, EventArgs e)
        {
            tracker.PersistAll();
            base.OnExit(sender, e);
        }

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            base.OnStartup(sender, e);
            DisplayRootViewFor<MainViewModel>();
        }
        Tracker tracker;
        protected override void Configure()
        {
            tracker = new Tracker();

            tracker.Configure<MainViewModel>().Properties(vm => new { vm.Abc });

            _container.Singleton<IWindowManager, WindowManager>();
            _container.Singleton<IEventAggregator, EventAggregator>();
            _container.RegisterInstance(typeof(Tracker), null, tracker);
            _container.RegisterPerRequest(typeof(MainViewModel), null, typeof(MainViewModel));
        }

        protected override object GetInstance(Type serviceType, string key)
        {
            var instance = _container.GetInstance(serviceType, key);
            tracker.Track(instance);
            return instance;
        }

        protected override IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return _container.GetAllInstances(serviceType);
        }

        protected override void BuildUp(object instance)
        {
            _container.BuildUp(instance);
        }
    }

Hmm, it still doesn't work.
Example Model:

    class ListViewModel : Screen
    {
        private string _mission;
        public string Mission
        {
            get => _mission;
            set
            {
                _mission = value;

                NotifyOfPropertyChange(() => Mission);
            }
        }
     }

My Collection:

        private BindableCollection<ListViewModel> _missionItems = new BindableCollection<ListViewModel>();
        public BindableCollection<ListViewModel> MissionItems
        {
            get => _missionItems;
            set
            {
                _missionItems = value; 

                NotifyOfPropertyChange(() => MissionItems);
            }
        }
.Property(p => p.MissionItems, "test")
.PersistOn(nameof(PropertyChanged));

Results:

    "Value": [
      {},
      {},
      {},
      {},
      {}
    ]

However, if I implement my own PropertyChanged it works just fine. Dunno what's wrong here.