简体   繁体   English

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

[英]How to set the model in a viewmodel (MVVM)

I have an HelloWorldWPFApplication class with the following method: 我有一个具有以下方法的HelloWorldWPFApplication类:

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

The ApplicationShellView has the following XAML: 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>

If my ViewModel ( ApplicationShellViewModel ) has the following method, the window will have the title set to "Test": 如果我的ViewModel( ApplicationShellViewModel )具有以下方法,则窗口的标题将设置为“ Test”:

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

My problem is that I want to set the title based on properties within the HelloWorldWPFApplication class. 我的问题是我想根据HelloWorldWPFApplication类中的属性设置标题。 I added the following to the HelloWorldWPFApplication's base class (which uses the INotifyPropertyChanged interface): 我将以下内容添加到HelloWorldWPFApplication的基类(使用INotifyPropertyChanged接口):

private WpfApplicationBase<WpfApplicationDataBase> applicationModel;

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

So effectively, I plan on reusing the existing HelloWorldWPFApplication object as the model (in MVVM). 如此有效,我计划将现有的HelloWorldWPFApplication对象作为模型重用(在MVVM中)。

I changed the WindowTitle property as follows: 我将WindowTitle属性更改如下:

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

Of course, at this stage my project creates a window without a title, as the application field has not been set. 当然,由于尚未设置应用程序字段,因此在此阶段我的项目将创建一个没有标题的窗口。 I don't want to create a new application object within the view model as one already exists. 我不想在视图模型中创建一个新的应用程序对象,因为它已经存在。 I want to use this existing object. 我想使用这个现有对象。 What is the best way to achieve this? 实现此目标的最佳方法是什么?

I am very new to MVVM/WPF - and from my basic understanding of MVVM I don't want to put any code-behind in the view. 我对MVVM / WPF非常陌生-从对MVVM的基本了解,我不想在视图中放任何代码。 I could have a static field set on a static class to the application object, and then assign this field in my view model (this works, but not sure having "global" variables is the best approach). 我可以在静态类上为应用程序对象设置一个静态字段,然后在我的视图模型中分配此字段(此方法有效,但不确定具有“全局”变量是最佳方法)。

I have also tried creating the view model before showing the window, but have encountered a problem I have yet to solve. 我还尝试过在显示窗口之前创建视图模型,但是遇到了尚未解决的问题。 In this implementation my run method appears as follows: 在此实现中,我的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);
}

I get a compile error: 我收到一个编译错误:

Error 1 Cannot implicitly convert type 'HelloWorldWPFApplication.Program.HelloWorldApplication' to 'Framework.Business.Logic.Program.Application.WpfApplicationBase' 错误1无法将类型'HelloWorldWPFApplication.Program.HelloWorldApplication'隐式转换为'Framework.Business.Logic.Program.Application.WpfApplicationBase'

I'm confused with the error as my HelloWorldWPFApplication class inherits from WpfApplicationBase : 我对错误感到困惑,因为我的HelloWorldWPFApplication类继承自WpfApplicationBase

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

Additionally, HelloWorldApplicationData inherits from WpfApplicationDataBase. 此外,HelloWorldApplicationData继承自WpfApplicationDataBase。

I get the pretty much the same problem with the following implementation: 我通过以下实现得到了几乎相同的问题:

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);
}

Exact error: 确切错误:

Error 1 Cannot implicitly convert type 'HelloWorldWPFApplication.Program.HelloWorldApplication' to 'Framework.Business.Logic.Program.Application.WpfApplicationBase' 错误1无法将类型'HelloWorldWPFApplication.Program.HelloWorldApplication'隐式转换为'Framework.Business.Logic.Program.Application.WpfApplicationBase'

First off, the "Application" class in WPF should be used for one thing, and one thing only: starting the program . 首先,应该将WPF中的“ Application”类用于一件事,并且只能用于一件事: 启动程序 It is not a model. 不是模型。

That said, I would just pass everything in sequence (this can apply to a proper model as well): 就是说,我将按顺序传递所有内容(这也适用于适当的模型):

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

Of course, remove the data context set from XAML. 当然,请从XAML中删除数据上下文集。 This does require modifying your code behind to accept the VM object and set it to the DataContext in your constructor, but thats a standard way of passing the VM to the View. 这确实需要修改后面的代码以接受VM对象并将其设置为构造函数中的DataContext,但这就是将VM传递给View的一种标准方法。

You could also use a Service Locator to find your model, or a number of other ways. 您还可以使用“服务定位器”来找到您的模型,或者使用其他多种方式。 Unfortunately, its hard to say which one is right, since your model is so weird . 不幸的是,由于您的模型太奇怪了 ,很难说哪个是对的。

As a complete aside; 作为补充; the title of your program is very much a part of the View, and probably doesn't need to be bound at all (your name is static, so making your application class the model isn't buying you anything). 程序的标题几乎是View的一部分,可能根本不需要绑定(您的名称是静态的,因此使您的应用程序类成为模型并不会为您带来任何收益)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM