1

I have a tricky question regarding the SingleInstance class on CodeProject.

I want to be able to handle commandline args after my window has loaded and before I started using SingleInstance, I handled all that in my MainWindow's Loaded event. Now, I think I'm forced to put all this in my App class, but I don't know how to access any properties or methods from my ViewModel there.

Code for the app:

public partial class App : System.Windows.Application, ISingleInstanceApp
{
    public static new App Current
    {
        get {
            return System.Windows.Application.Current as App;
        }
    }
    internal ApplicationInitializeDelegate ApplicationInitialize;
    internal delegate void ApplicationInitializeDelegate(SplashScreen splashWindow);

    private const string Unique = "Unique App Id";

    public bool SignalExternalCommandLineArgs(IList<string> args)
    {
        //This executes for each instance after the first. 
        //We can activate the window and access properties/methods of type Window, 
        //but not of type MainWindow, and, therefore, have no 
        //access to ViewModel.
        this.MainWindow.Activate();
        return true;
    }

    [STAThread]
    public static void Main(params string[] Arguments)
    {
        //Stops new windows from being created.
        if (SingleInstance<App>.InitializeAsFirstInstance(Unique))
        {
            App app = new App();

            app.InitializeComponent();
            app.Run();

            SingleInstance<App>.Cleanup();
        } else {
            //Runs each time after first instance.
        }
    }

    public App()
    {
        ApplicationInitialize = _applicationInitialize;
    }


    //I added this here while experimenting, though, obviously it doesn't do anything yet. Can we do something here, possibly?
    protected override void OnStartup(StartupEventArgs e)
    {
        if (e.Args.Length > 0)
        {
        }
    }

    private void _applicationInitialize(SplashScreen splashWindow)
    {
        //Do work and update splashWindow

        //Create the main window on the UI thread.
        Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate ()
        {
            MainWindow = new MainWindow();
            MainWindow.Show();
        }));
    }
}

Edit 1

I have came up with an extremely dirty (and not so ideal) hack that gives me exactly what I want, but not in the way I think I should be doing it.

public bool SignalExternalCommandLineArgs(IList<string> args)
{
    this.MainWindow.Activate();
    this.MainWindow.Tag = args.Count > 0 ? args[1] : "";
    return true;
}

This allows me to pass the path of the file I am trying to do stuff with on to my MainWindow directly so that after everything is loaded, I can go ahead and open it. I hate the fact that I have use the Tag attribute for this as it just doesn't feel right. Any alternatives?

  • 1
    If you don't want to use the .Tag property, you can add your own properties to your MainWindow for this purpose. Or you could add your own init method (or constructor through inheritance) to specifically pass context parameters into it *before* the Activate/Show (I did this for many years in COM WinForms). – RBarryYoung Mar 12 '16 at 21:02
  • Just realized I can add additional DependencyProperties as you suggested, which is perfect for this sort of thing. Thank you! –  Mar 30 '16 at 20:38

0 Answers0