MVVM mode of WPF (2) and wpfmvvm Mode
We all want to pursue perfection.
Every view in the app has an empty codebehind file, except for the standard boilerplate code that calls InitializeComponent in the class's constructor. In fact, you could remove the views' codebehind files from the project and the application would still compile and run correctly
Josh Smith said that the views 'codebehind file can be deleted and the program can run normally.
The authors of the stylet framework say that "Stylet lets you delete the codebehind entirely (it will callInitializeComponent
For you), and you are strongly encouraged to do so. Delete the codebehind !"
Ah... is there such a perfect thing? Isn't there a line of code in the views 'codebehind file that is not written, and all the code can be written in ViewModel, so that the display layer and business logic layer can be perfectly separated?
The ideal is full, but the reality is backbone! In order to pursue the ultimate MVVM, in actual project development, I will be very entangled in myself and do not know where to start...
For example, if a third-party control does not support the dependency attribute, we can only write the code in the view 'codebehind file. The problem is that this control uses the logic in ViewModel.How does View access ViewModel?? To obtain the data of this control in ViewModelHow does ViewModel call the methods in View?? I searched and found that this problem was hard to solve...
This "Mouse" control ruined our plan to achieve the perfect MVVM. Oh, at this time, I began to regret using MVVM and regret using WPF. I simply used WinForm for development, or find a third-party MVVM framework to see if it can solve the problem... I had this mentality at the beginning.
The following uses a simple demo to demonstrate how to solve the above two problems:
Use ViewModel in View
When the program is started, the corresponding ViewModel has been used to initialize the DataContext of the View.
/// <Summary> /// App. interaction logic of xaml // </summary> public partial class App: Application {protected override void OnStartup (StartupEventArgs e) {base. onStartup (e); var vw = new MainWindow (); var vm = new MainWindowViewModel (); vw. dataContext = vm; vw. show ();}}
Therefore, in View, we can obtain the ViewModel through DataContext.
private MainWindowViewModel _vm;private void OnLoaded(object sender, RoutedEventArgs e){ if (_vm == null) { _vm = this.DataContext as MainWindowViewModel; ... }}
Use attributes or methods in ViewModel in View
Private void LvPersons_OnSelectionChanged (object sender, SelectionChangedEventArgs e) {var item = this. LvPersons. SelectedItem as PersonModel; if (item! = Null) {_ vm. personProfile = string. format ("Name: {0}, Gender: {1}, age: {2};", item. name, item. sex, item. age );}}
Note: You can use the System. Window. interactivity plug-in provided by blend to convert the View event to the command in ViewModel.
Use View in ViewModel
First define an Interface
namespace MVVMSample.Comm{ public interface IView { void SetAddress(Uri uri); }}
Initialize and implement this interface in View
public partial class MainWindow : IView{ private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) { if (_vm == null) { _vm = this.DataContext as MainWindowViewModel; if (_vm != null) { _vm.View = this; } } } ... public void SetAddress(Uri uri) { this.Wb.Navigate(uri); }}
Define and use the interface in View in ViewModel
Public IView View {private get; set ;}... public ICommand NavigationCmd {get {if (_ navigationCmd = null) {_ navigationCmd = new DelegateCommand () => {if (View! = Null) {// Interface Method in IView View. SetAddress (new Uri ("http://www.bing.com") ;}}return _ navigationCmd ;}}
The problem is finally solved. The key is that the above method can also be used for unit testing.
Summary
Operations related to business logic must be placed in ViewModel. operations unrelated to business logic can be placed in the view'codebehind file. The MVVM mode is a guiding principle in development and needs to be used flexibly.