I can easily pass in an IConfiguration appsettings.json to a Window in WPF, which is what I have done in the past. Now I am trying to do this the proper way and pass it into a ViewModel that is assigned as the DataContext of a Page that is being displayed on a Window. I'm loading the Page into a Frame on the Window. I would like to pass the config to the ViewModel of the Page so I dont have to reread it in manually.
Here is what I currently have and some stuff I tried:
public partial class HomeWindow : Window
{
readonly IConfiguration _config;
public HomeWindow(IConfiguration config)
{
_config = config;
// Instantiate the Object with JSON settings.
InitializeComponent();
DataContext = new HomeWindowVM(config)
}
}
public class HomeWindowVM
{
readonly IConfiguration _config;
//public INotify btnCheckoutPage { get; set; }
public object MyFrameContent { get; set; }
public HomeWindowVM(IConfiguration config)
{
_config = config;
CheckoutClickCommand = new MyCommand(CheckoutClick);
ShipmentClickCommand = new MyCommand(ShipmentClick);
frameURI = new INotify();
frameVis = new INotify();
frameVis.MyProperty = "Hidden";
}
private void CheckoutClick()
{
frameURI.MyProperty = "CheckoutPage.xaml";
frameVis.MyProperty = "Visible";
// I tried this
//CheckoutPage checkoutPage = new CheckoutPage(_config);
//MyFrameContent = new CheckoutPage(_config);
}
}
public partial class CheckoutPage : Page
{
readonly IConfiguration _config;
public CheckoutPage()
{
InitializeComponent();
DataContext = new CheckoutPageVM();
}
public CheckoutPage(IConfiguration config)
{
_config = config;
InitializeComponent();
//Frame frame = new Frame();
//MainView
DataContext = new CheckoutPageVM(config);
}
}
public class CheckoutPageVM
{
readonly IConfiguration _config;
public CheckoutPageVM(IConfiguration config)
{
_config = config;
LblErrorProjectNum = new INotify();
LblErrorProjectNum.MyProperty = "Hidden";
LblErrorTransfer = new INotify();
LblErrorTransfer.MyProperty = "Hidden";
CheckoutSubmitCommand = new MyCommand(CheckoutSubmit);
}
There's no one proper way to do this, but I'm guessing you've got a background in ASP.NET and are familiar with dependency injection. Of course WPF doesn't use that pattern and it's probably overkill in this case. A statically accessible singleton works perfectly fine and avoids the morass of passing the config instance around through constructors or other over-engineered solutions:
// In your Model layer
public static class MyConfiguration
{
public static IConfiguration Instance { get; private set; }
public static void Load(IConfiguration config)
{
// call this when the app initializes
Instance = config;
}
}
Then if individual classes need instance properties for binding, etc., it's as simple as:
public partial class HomeWindow : Window
{
public IConfiguration Config => MyConfiguration.Instance;
// ...
}
public class CheckoutPageVM
{
public IConfiguration Config => MyConfiguration.Instance;
// ...
}
public partial class CheckoutPage : Page
{
public IConfiguration Config => MyConfiguration.Instance;
// ...
}
etc.