WPF MVVM下新建View并向ViewModel传递参数的技术问题
First, let's fix a critical bug in your BasePage class that would cause a stack overflow: the ViewModel property's getter is returning itself instead of the backing field mViewModel. Here's the corrected version:
public class BasePage<VM> : Page where VM : BaseViewModel, new() { private VM mViewModel; public VM ViewModel { get { return mViewModel; } // Fixed: return the backing field, not the property itself set { if (mViewModel == value) return; mViewModel = value; this.DataContext = mViewModel; } } public BasePage() { this.Resources = ((MainWindow)Application.Current.MainWindow).Resources; this.ViewModel = new VM(); } // Optional: Add a constructor to accept a pre-initialized ViewModel public BasePage(VM viewModel) { this.Resources = ((MainWindow)Application.Current.MainWindow).Resources; this.ViewModel = viewModel; } }
Now, let's tackle passing the position parameter to your DetailedViewViewModel's PossitionShown property. Here are two clean approaches:
Approach 1: Directly Assign the Property in the View's Constructor
This is the simplest solution for your current setup. Since the BasePage constructor already initializes the ViewModel, you can just set the property right after calling InitializeComponent:
namespace unnamed { public partial class DetailedViewPage : BasePage<DetailedViewViewModel> { public DetailedViewPage(string position) : base() { InitializeComponent(); // Assign the position directly to the ViewModel's property ViewModel.PossitionShown = position; } } // Your existing window creation code stays the same private void CreateNewWindow() { var MainWindow = (MainWindow) Application.Current.MainWindow; var MWViewModel = (WindowViewModel) MainWindow.DataContext; MWViewModel.CurrentPage = new DetailedViewPage("top"); } }
Approach 2: Initialize the ViewModel with a Parameter (More MVVM-Friendly)
If you prefer to keep ViewModel initialization logic within the ViewModel itself, add a parameterized constructor to DetailedViewViewModel and use the overloaded BasePage constructor we added earlier:
Step 1: Update the ViewModel with a Parameterized Constructor
namespace unnamed { public class DetailedViewViewModel : BaseViewModel { public string PossitionShown { get; set; } // Add a constructor that accepts the position parameter public DetailedViewViewModel(string position) { PossitionShown = position; } // Keep the default constructor if you still need it for other cases public DetailedViewViewModel() {} } }
Step 2: Modify the View to Use the Pre-Initialized ViewModel
namespace unnamed { public partial class DetailedViewPage : BasePage<DetailedViewViewModel> { public DetailedViewPage(string position) : base(new DetailedViewViewModel(position)) { // Pass the initialized VM to BasePage InitializeComponent(); } } }
Both approaches work well—choose the one that fits your project's structure. The second approach is more aligned with MVVM principles since it lets the ViewModel handle its own initialization, while the first is quicker for simple scenarios.
内容的提问来源于stack exchange,提问作者jurgis

