我可以很容易地传入一个IConfiguration应用程序设置。json到WPF中的一个窗口,这是我过去所做的。现在,我尝试以正确的方式完成此操作,并将其传递到ViewModel中,该ViewModel被分配为正在Window上显示的Page的DataContext。我正在把页面加载到窗口的框架中。我想把配置传递给页面的ViewModel,这样我就不用手动重读了。
以下是我目前所做的和我尝试过的一些事情:
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);
}
2条答案
按热度按时间relj7zay1#
没有一个正确的方法来做到这一点,但我猜你有ASP的背景。NET,熟悉依赖注入。当然,WPF不使用这种模式,在这种情况下,它可能是矫枉过正。静态可访问的单例工作得很好,避免了通过构造函数或其他过度设计的解决方案传递配置示例的困境:
然后,如果单个类需要示例属性进行绑定,等等。,就像这样简单:
等等
0tdrvxhp2#
首先,您的视图不应该依赖于任何应用程序设置模型。因此,
Window
和Page
示例对MVVM应用程序中IConfiguration
对象的依赖性是错误的。配置是应用程序 * 型号 * 的一部分。为了避免这种依赖性,最好的方法是使用所谓的 View-Model-First 模式。该模式要求您的 View Model 类决定要加载哪个 View 类。这与当前的 * View-First * 模式相反,在该模式中,View 决定加载哪个 View Model。
ContentPresenter
或ContentControl
或派生类)来实现。然后定义一个DataTemplate
,它将由框架基于当前数据类型(视图模型类型)加载和呈现。此DataTemplate
包含您要显示的实际视图。这消除了 View 对 Model 类的依赖性(在本例中,这是通过允许视图显式地构造其 View Model 类而引入的)。
您可以查看以下示例以了解 View-Model-First:C# WPF Navigation Between Pages (Views)。
出于这个原因,我建议改变您的方法,实现MVVM友好的 View-Model-First 模式。
即使您没有实现MVVM模式,您也将获得一个更易于维护和扩展的应用程序。
无论使用 View-First 还是 View-Model-First,
IConfiguration
示例都必须来自应用程序 Model。当前代码的第一个修正或改进是将
IConfiguration
示例化移动到 Model。View Model 必须从 Model 而不是 View 获取此类应用程序数据。为此,示例创建了一个ConfigurationRepositoty
类,该类封装了IConfiguration
示例的创建。由于数据持久性也是 Model 的一部分,因此ConfigurationRepositoty
可以轻松访问文件或数据库等资源。理想情况下,它将使用其他 Model 类,这些类详细了解如何获取数据(从文件或数据库读取)。ConfigurationRepositoty
要么直接在 View Model 类中创建,要么通过构造函数注入(在实现任何IoC的情况下,如 Dependency Injection 模式)。关于视图模型构造函数依赖项,您应该引入一个工厂,其中视图模型具有构造函数依赖项。考虑实现 Abstract Factory 模式。View-First 实现的结果是 View 显式地示例化视图,因此必须知道所有的依赖关系才能满足构造函数。
由于 View Model 类的依赖项通常是 Model 类,因此在 View 中声明的依赖项是非法的或在设计方面有缺陷。当使用工厂(或抽象工厂)时,这些依赖性被消除。
第二个强制修复是将页面导航从 View Model 移动到 View。
因为您实现了 View-First 导航,所以您可以通过创建视图的示例或通过URI显式地知道它们来导航。
但是您的 View Model 不能知道/依赖于 View 类型或它们的URI。这使它们不具备充当导航控制器的资格。
如果您想从 View Model 导航,那么就实现 View-Model-First 模式。
最后,
MyFrameContent
属性看起来也非常可疑。根据名称,似乎所有者视图模型类对视图有太多的了解,甚至可能是具体的依赖关系。配置存储库。cs
一个 Model 类,知道如何获取或创建
IConfiguration
示例。主窗口。xaml.cs
首页.cs
CheckoutPage.cs
INavigationSource。cs
由需要导航离开的所有页面实现。
NavigationRequestedEventArgs。cs
HomePageVM。cs
CheckoutPageVM。cs