Custom caliburn.micro splashscreen with shell screen conductor

夙愿已清 提交于 2019-12-06 07:16:41

问题


I'm new to WPF and Caliburn.micro and I'd like to implement a custom splashscreen to a WPF App using Caliburn. I'm looking at the right way to do it with a screen conductor (as I understood it is the best solution).

My Bootstrapper looks like this :

public class AppBootstrapper : BootstrapperBase
    {
        private bool actuallyClosing;
        private CompositionContainer container;        

        public AppBootstrapper()
        {
            Start();
        }

        protected override void Configure()
        {
            container = new CompositionContainer(
                    new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>())
                );

            var batch = new CompositionBatch();

            batch.AddExportedValue<IWindowManager>(new WindowManager());
            batch.AddExportedValue<IEventAggregator>(new EventAggregator());
            batch.AddExportedValue(container);
            container.Compose(batch);
            Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
        }

        protected override object GetInstance(Type serviceType, string key)
        {
            string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
            var exports = container.GetExportedValues<object>(contract);

            if (exports.Any()) return exports.First();
            throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
        }

        protected override IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
        }

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

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor<ShellViewModel>();
        }
    }

ShellViewModel is like this : (but I don't actually wanna see a window of it)

[Export(typeof(ShellViewModel))]
public class ShellViewModel : Conductor<Screen>
{
    [ImportingConstructor]
    public ShellViewModel()
    {
         ActivateItem(new SplashScreenViewModel());
         int i = 10; // loading ... or do the loading inside the splashscreen ??
         ActivateItem(new MainWindowViewModel());
    }
}

SplashScreenViewModel is quite simple :

[Export(typeof(SplashScreenViewModel))]
    public class SplashScreenViewModel : Screen
    {
        private string appName;
        private string version;
        private string service;
        private string creator;
        private string copyright;
        private string message;

        [ImportingConstructor]
        public SplashScreenViewModel()
        {
            appName = Assembly.GetEntryAssembly().GetName().Name;
            version = Assembly.GetEntryAssembly().GetName().Version.ToString();
            copyright = "Copyright © corp 2014";
            service = "Department";
            creator = "user - " + Service;
            message = "Loading ...";
        }
    }

And finally, MainWindowViewModel :

[Export(typeof(MainWindowViewModel))]
public class MainWindowViewModel : Screen, IGuardClose
{
    [ImportingConstructor]
    public MainWindowViewModel()
    {
        NetworkUpdate(); // do stuff.
    }
    void IGuardClose.CanClose(Action<bool> callback)
    {
        throw new NotImplementedException();
    }

    void IClose.TryClose()
    {
        throw new NotImplementedException();
    }
}

Right now I'm trying a little bit every approach but it displays either nothing or the main window only or the splashscreen only or even an empty view for shellview ...

I really would appreciate some hints on this !

Thanks guys ...


回答1:


Dont use ActivateItem for splash screen.

It is better to use WindowManager, based on what I understand about splash ( pop up window displayed while the exe load all the necessary processes)

you can do it in Appbootstrapper in OnStartUp

protected override void OnStartup(object sender, StartupEventArgs e)
    {
        var splash = this.container.GetExportedValue<SplashScreenViewModel>();
        var windowManager = IoC.Get<IWindowManager>();
        windowManager.ShowDialog(splash);

       // do your background work here using
        var bw = new BackgroundWorker();
        bw.DoWork += (s, e) =>
            {
                // Do your background process here

            };

        bw.RunWorkerCompleted += (s, e) =>
            {
                // close the splash window
                splash.TryClose();
                this.DisplayRootViewFor<ShellViewModel>();
            }; 

        bw.RunWorkerAsync();           
    }


    // your ShellViewModel
    [ImportingConstructor]
    public ShellViewModel(MainViewModel mainViewModel)
    {
        this.DisplayName = "Window Title";
        // no need to new
        this.ActivateItem(mainViewModel);
    }


来源:https://stackoverflow.com/questions/25141186/custom-caliburn-micro-splashscreen-with-shell-screen-conductor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!