如何在视图模型 (MVVM) 中设置模型



我有一个HelloWorldWPFApplication类,方法如下:

public override void Run()
{
    var app = new System.Windows.Application();
    app.Run(new ApplicationShellView());
}

ApplicationShellView具有以下 XAML:

<winbase:ApplicationShell x:Class="HelloWorldWPFApplication.View.ApplicationShellView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:winbase="clr-namespace:Framework.Presentation.Control.Window;assembly=Framework"
    xmlns:vm="clr-namespace:HelloWorldWPFApplication.ViewModel"
    Title="{Binding WindowTitle, Mode=OneWay}">
<Window.DataContext>
    <vm:ApplicationShellViewModel  />
</Window.DataContext>
</winbase:ApplicationShell>

如果我的视图模型 ( ApplicationShellViewModel ) 具有以下方法,则窗口的标题将设置为"测试":

    public string WindowTitle
    {
        get
        {
            return "Test";
        }
    }

我的问题是我想根据 HelloWorldWPFApplication 类中的属性设置标题。 我将以下内容添加到HelloWorldWPFApplication的基类(使用INotifyPropertyChanged接口):

private WpfApplicationBase<WpfApplicationDataBase> applicationModel;
public WpfApplicationBase<WpfApplicationDataBase> Application
{
    get { return this.applicationModel; }
    set { this.Set<WpfApplicationBase<WpfApplicationDataBase>>(ref this.applicationModel, value); }
}

因此,我计划重用现有的HelloWorldWPFApplication对象作为模型(在 MVVM 中)。

我更改了 WindowTitle 属性,如下所示:

public string WindowTitle
{
    get
    {
        return String.Format("{0} {1}",
              this.applicationModel.Data.FullName,
              this.applicationModel.Data.ReleaseVersion).Trim();
    }
}

当然,在此阶段,我的项目会创建一个没有标题的窗口,因为尚未设置应用程序字段。 我不想在视图模型中创建新的应用程序对象,因为已经存在一个。 我想使用这个现有对象。 实现这一目标的最佳方法是什么?

我对 MVVM/WPF 非常陌生 - 根据我对 MVVM 的基本了解,我不想在视图中放置任何代码隐藏。 我可以在静态类上为应用程序对象设置一个静态字段,然后在我的视图模型中分配此字段(这有效,但不确定使用"全局"变量是最好的方法)。

我也尝试在显示窗口之前创建视图模型,但遇到了一个我尚未解决的问题。 在此实现中,我的 run 方法如下所示:

public override void Run()
{
    var window = new ApplicationShell();  // inherits from System.Windows.Window
    var vm = new ApplicationShellViewModel();
    vm.Application = this;  // this line won't compile
    window.DataContext = vm;
    this.Data.WpfApplication.Run(window);
}

我收到编译错误:

错误 1 无法将类型"HelloWorldWPFApplication.Program.HelloWorldApplication"隐式转换为"Framework.Business.Logic.Program.Application.WpfApplicationBase"

我对错误感到困惑,因为我的HelloWorldWPFApplication类继承自WpfApplicationBase

    public class HelloWorldApplication<T> : WpfApplicationBase<T>
    where T : HelloWorldApplicationData

此外,HelloWorldApplicationData继承自WpfApplicationDataBase。

我在以下实现中遇到了几乎相同的问题:

public override void Run()
{
    var window = new ApplicationShell();
    var vm = new ApplicationShellViewModel();
    var app = new HelloWorldApplication<HelloWorldApplicationData>();
    vm.Application = app;  // Cannot implicitly convert type error again
    window.DataContext = vm;
    this.Data.WpfApplication.Run(window);
}

确切错误:

错误 1 无法将类型"HelloWorldWPFApplication.Program.HelloWorldApplication"隐式转换为"Framework.Business.Logic.Program.Application.WpfApplicationBase"

首先,WPF 中的"Application"类应该用于一件事,而且只用于一件事:启动程序。它是一个模型。

也就是说,我只会按顺序传递所有内容(这也适用于适当的模型):

MyViewModel viewmodel = new MyViewModel(this);
var app = new System.Windows.Application();
app.Run(new ApplicationShellView(viewmodel));

当然,请从 XAML 中删除数据上下文集。这确实需要修改代码隐藏以接受 VM 对象并将其设置为构造函数中的 DataContext,但这是将 VM 传递到视图的标准方法。

您还可以使用服务定位器来查找模型,或通过其他多种方式查找模型。不幸的是,很难说哪一个是正确的,因为你的模型太奇怪了。

顺便说一句,程序的标题在很大程度上是视图的一部分,可能根本不需要绑定(你的名字是静态的,所以让你的应用程序类成为模型不会给你带来任何东西)。

最新更新