0

I'm new to Caliburn micro and am trying to use it in an Excel add-in. I'm actually using ExcelDna to realize the add-in. I have my bootstrapper setup and am able to run a test application correctly in a dialog. Everything works like expected.

I then tried to run the Window/MainForm in a separate thread since I don't want it to run on Excel's main thread for various reasons. NotifyOfPropertyChanged throws then the following error only for the CanSayHello:

{"An error occurred while dispatching a call to the UI Thread"} {"The calling thread cannot access this object because a different thread owns it."}

NotifyOfPropertyChange(() => Name) works correctly w/o any issues.

I then tried to initialize the boostrapper in the new thread and this actually makes it work. However, if I close the wpf window and reopen from my excel menu i get an error that I cannot initialize the boostrapper since "An item with the same key has already been added".

Any suggestions?

Frank

Code:

    using Caliburn.Micro;
    using ExcelDna.Integration;
    using ExcelDNACMTest.ViewModels;
    using System.Threading;

    public class myBootstrapper:BootstrapperBase
        {                
            public myBootstrapper() :base(false)
            {        
            }

         }

        public class ProgramStart : IExcelAddIn //(this is ExcelDNA)
            {
                static Thread threadProgramWindow;
                static readonly MainViewModel ViewModel = new MainViewModel();
                static IWindowManager windowManager = new WindowManager();

                public void AutoOpen() //ExcelDNA - runs at start of xll
                {
                    var BS = new myBootstrapper();
                        BS.Initialize();

                    var myThread = new Thread(() =>
                        {
                            windowManager.ShowDialog(new MainViewModel());
                        }
                    );
                    myThread.SetApartmentState(ApartmentState.STA);
                    myThread.Start();

                }    
                public void AutoClose()
                {
                   }  




    //ViewModels

     class NameViewModel : PropertyChangedBase
        {

            string name;

            public string Name
            {
                get { return name; }
                set
                {
                    name = value;

                    NotifyOfPropertyChange(() => Name);
                    NotifyOfPropertyChange(() => CanSayHello);    //error here            
                }
            }

            public bool CanSayHello
            {
                get { return !string.IsNullOrWhiteSpace(Name); }
            }

            public void SayHello()
            {
                MessageBox.Show(string.Format("Hello {0}!", Name));
            }
        }

public class MainViewModel : Conductor<object>
{
    public void ShowPageOne()
    {
        ActivateItem(new NameViewModel());
    }        
}

1 Answers1

0

first you dont need that extra thread.

static IWindowManager windowManager = new WindowManager();

call

IOC.Get<IWindowManager>();

to get the windowmanager after your .Inizialize() call, so you get the correct window manager.

that should do the trick.

from Frank to Frank....

Usman Maqbool
  • 3,351
  • 10
  • 31
  • 48
Frank
  • 1
  • 1