Reputation: 3083
I have an HelloWorldWPFApplication
class with the following method:
public override void Run()
{
var app = new System.Windows.Application();
app.Run(new ApplicationShellView());
}
The ApplicationShellView
has the following 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":
public string WindowTitle
{
get
{
return "Test";
}
}
My problem is that I want to set the title based on properties within the HelloWorldWPFApplication
class. I added the following to the HelloWorldWPFApplication's base class (which uses the INotifyPropertyChanged
interface):
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).
I changed the WindowTitle property as follows:
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. 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:
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'
I'm confused with the error as my HelloWorldWPFApplication
class inherits from WpfApplicationBase
:
public class HelloWorldApplication<T> : WpfApplicationBase<T>
where T : HelloWorldApplicationData
Additionally, HelloWorldApplicationData inherits from 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'
Upvotes: 0
Views: 1288
Reputation: 61379
First off, the "Application" class in WPF should be used for one thing, and one thing only: starting the program. 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. 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.
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).
Upvotes: 2