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

时间:2014-11-21 16:48:43

标签: c# wpf xaml 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>

如果我的ViewModel(ApplicationShellViewModel)具有以下方法,则该窗口的标题将设置为&#34;测试&#34;:

    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的基本了解,我不想在视图中添加任何代码隐藏。我可以在静态类上为应用程序对象设置一个静态字段,然后在我的视图模型中分配这个字段(这有效,但不确定是否有&#34;全局&#34;变量是最好的方法)。

我还尝试在显示窗口之前创建视图模型,但遇到了我尚未解决的问题。在此实现中,我的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无法隐式转换类型&#39; HelloWorldWPFApplication.Program.HelloWorldApplication&#39; to&#39; Framework.Business.Logic.Program.Application.WpfApplicationBase&#39;

由于我的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无法隐式转换类型&#39; HelloWorldWPFApplication.Program.HelloWorldApplication&#39; to&#39; Framework.Business.Logic.Program.Application.WpfApplicationBase&#39;

1 个答案:

答案 0 :(得分:2)

首先,&#34;应用&#34; WPF中的类应该用于一件事,只有一件事:启动程序。它是模型。

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

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

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

您还可以使用服务定位器查找您的模型或其他许多方式。不幸的是,很难说哪一个是正确的,因为你的模型是如此怪异

完全抛开;你的程序的标题是View的一部分,可能根本不需要绑定(你的名字是静态的,所以让你的应用程序类成为模型并不是为你买任何东西)。