2

So from this post I got the following code for passing command line arguments into my WPF Application

public partial class App : Application
{
    private string _customerCode;
    public string CustomerCode
    {
        get { return _customerCode; }
        set { _customerCode = value; }
    }


    protected override void OnStartup(StartupEventArgs e)
    {
        if (e.Args.Count() != 0)
        {
            CustomerCode = e.Args[0].Replace("/", string.Empty); 
        }
    }
}

The application then starts my MainWindow.xaml and the application runs but in the viewModel for MainWindow.xaml (MainViewModel.cs) I would like to access the value of App.CustomerCode.

Is this the right way to deal with command line arguments and is it possible to access the value of CustomerCode?

Community
  • 1
  • 1
JKennedy
  • 18,150
  • 17
  • 114
  • 198

2 Answers2

4

One of the easy ways to access the customer code is to overwrite the Application.Current property with the new keyword (as more or less Davut has pointed out in his answer):

public class App : Application
{
    public static new App Current
    {
        get { return (App) Application.Current; }
    }

    public string CustomerCode { get; set; }
    protected override void OnStartup(StartupEventArgs e)
    {
        this.CustomerCode = e.Args[0].Replace("/", string.Empty);
        base.OnStartup(e);
    }
}

In your view model you can then access the customer code by writing App.Current.CustomerCode.

However, if you want a more object-oriented way regarding the SOLID principles, I would advise to do the following: in your OnStartup method, create the view model and the main window in code and show it. Using this approach, you can inject the customer code to the view model, e.g. via constructor injection. The OnStartup method would look like this:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    // Composition root
    var customerCode = e.Args[0].Replace("/", string.Empty);

    // Here I inject the customer code to the view model so that 
    // it can save it in a field and use it later.
    // This is called dependency injection (here it's constructor injection)
    var mainWindowViewModel = new MainWindowViewModel(customerCode);
    MainWindow = new MainWindow { DataContext = mainWindowViewModel };
    MainWindow.Show();
}

For this to work, you have to remove the StartupUri entry in App.xaml - otherwise your manually created main window will not show up.

Your view model would look like this:

public class MainWindowViewModel
{
    private readonly string _customerCode;

    public MainWindowViewModel(string customerCode)
    {
        if (customerCode == null)
            throw new ArgumentNullException("customerCode");

        _customerCode = customerCode;
    }

    // Other code in this class can access the _customerCode field
    // to retrieve the value from the command line
}

This approach is a more flexible than to access the static App.Current property as your view model is independent of the App class (i.e. it has no references to it).

If you want to learn more about dependency injection, just google it, you'll find plenty of example. I can also recommend the excellent book Dependency Injection in .NET by Mark Seemann, if you want to dive in more.

feO2x
  • 5,358
  • 2
  • 37
  • 46
  • Thanks for addition feO2x , I thought showing an easier way of accessing the param but just wanted to focus on the current problem then. BTW AFAIK you passed a param to a ViewModel. Dependency Injection is getting rid of from dependencies. If you were passing an interface of a ViewModel class which provided from a factory it would be. But I do not see exact IOC or DI here. – Davut Gürbüz Sep 04 '14 at 09:45
  • Hmm, I think we have a different understanding about the term dependency injection. From my knowledge, I would define it as the following: if an object needs a certain other object, it will not actively obtain it (e.g. by call static methods), but the object will be passed to it via constructor, method or property injection. That's what I did with the view model. In this case I don't care if it is an abstraction (i.e. an interface or abstract base class) or not. – feO2x Sep 04 '14 at 09:53
  • If you talk about "programming against abstractions instead of concrete implementations" then I would relate this to the Dependency Inversion Principle by Uncle Bob. But in this case, I don't want to call `customerCode` polymorphically - I just want the data that's inside of it. Thus I do not access it via an abstraction - not every dependency must be an abstraction (although most of them are in daily life). – feO2x Sep 04 '14 at 09:57
3

I do not know your real intent, but the code below should help you.

You can try this by adding some arguments on project debug settings.

If your parameters contains blank spaces you should use "" signs to distinguish them. But instead of doing this you can use Application Config file for some cases. You can add some Settings from Project Settings or directly editing by settings.settings file.

If you need/fancy startup args, here is it.

//App
public partial class App : Application
{
    public string CustomerCode { get; set; }
    protected override void OnStartup(StartupEventArgs e)
    {

        this.CustomerCode=e.Args[0].ToString();
        base.OnStartup(e);
    }
}


//MainWindow
 public partial class MainWindow : Window
{
    public MainWindow()
    {
        var hereIsMyCode=(Application.Current as App).CustomerCode;
        InitializeComponent();
    }
}
Davut Gürbüz
  • 5,526
  • 4
  • 47
  • 83