(1/7). NET Core 3 WPF MVVM Framework Prism Series Data Binding

(1/7). NET Core 3 WPF MVVM Framework Prism Series Data Binding

data binding

最后更新 6/10/2023 11:30 PM
RyzenAdorer
预计阅读 6 分钟
分类
WPF
专题
WPF MVVM Framework Prism Series
标签
.NET C# WPF Prism MVVM

This article comes from reprint

Original author: RyzenAdorer

Original title: Data Binding of. NET Core 3 WPF MVVM Framework Prism Series

Original link: www.cnblogs.com/ryzen/p/11905866.html

I. Install Prism

  1. Using the Package Management Console
Install-Package Prism.Unity -Version 7.2.0.1367

You can also remove '-Version 7.2.0.1367' to get the latest version

  1. Use NuGet package for management solutions

Maybe we have a question above? Why does installing prism have something to do with Prism.Unity? We know that Unity is an IOC container, and Prism itself supports IOC, and currently officially supports several IOC containers:

    1. Since unity is official Microsoft and supports componentization of prism, I recommend using prism.unity. In the official document, prism7 does not support prism.Mef, and Prism 7.1 will not support prism.Autofac
    1. After installing pris.unity, it already contains all the core libraries of pris. The architecture is as follows:

II. Implement data binding

We first create the Views folder and the ViewModels folder, place MainWindow under the Views folder, and then create the MainWindowViewModel class under the ViewModels folder, as follows:

The xaml code is as follows:

<Window
  x:Class="PrismSample.Views.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:prism="http://prismlibrary.com/"
  xmlns:local="clr-namespace:PrismSample"
  mc:Ignorable="d"
  Title="MainWindow"
  Height="450"
  Width="800"
  prism:ViewModelLocator.AutoWireViewModel="True"
>
  <StackPanel>
    <TextBox
      Text="{Binding Text}"
      Margin="10"
      Height="100"
      FontSize="50"
      Foreground="Black"
      BorderBrush="Black"
    />
    <button
      Height="100"
      Width="300"
      Content="Click Me"
      FontSize="50"
      Command="{Binding ClickCommnd}"
    />
  </StackPanel>
</Window>

The ViewModel code is as follows:

using Prism.Commands;
using Prism.Mvvm;

namespace PrismSample.ViewModels
{
   public class MainWindowViewModel:BindableBase
    {
        private string _text;
        public string Text
        {
            get { return _text; }
            set { SetProperty(ref _text, value); }
        }

        private DelegateCommand _clickCommnd;
        public DelegateCommand ClickCommnd =>
            _clickCommnd ?? (_clickCommnd = new DelegateCommand(ExecuteClickCommnd));

        void ExecuteClickCommnd()
        {
            this.Text = "Click Me!";
        }

        public MainWindowViewModel()
        {
            this.Text = "Hello Prism!";
        }
    }
}

Start procedure:

Click the click Me button:

As you can see, we have successfully used prism to achieve data binding, and View and ViewModel have perfect separation of front and back ends.

But now we have another question. What should we do when we don't want to put View and ViewModels in Views and ViewModels in accordance with the rules of prism, or maybe our own project naming rules are different? At this time, we need to use several other methods:

  1. Change naming rules

If the company's naming rules are abnormal, resulting in the project structure becoming like this (this company should resign):

First of all, we need to introduce prism in the App, modify 'Application' to 'prism:PrismApplication' and delete StartupUri

The xaml code is as follows:

<prism:PrismApplication
  x:Class="PrismSample.App"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:prism="http://prismlibrary.com/"
  xmlns:local="clr-namespace:PrismSample"
>
  <Application.Resources> </Application.Resources>
</prism:PrismApplication>

The cs background code is as follows:

using Prism.Unity;
using Prism.Ioc;
using Prism.Mvvm;
using System.Windows;
using PrismSample.Viewsb;
using System;
using System.Reflection;

namespace PrismSample
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        //设置启动起始页
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {

        }

        //配置规则
        protected override void ConfigureViewModelLocator()
        {
            base.ConfigureViewModelLocator();
            ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
            {
                var viewName = viewType.FullName.Replace(".Viewsb.", ".ViewModelsa.OhMyGod.");
                var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
                var viewModelName = $"{viewName}Test, {viewAssemblyName}";
                return Type.GetType(viewModelName);
            });
        }
    }
}

The above two sentences are the key:

".Viewsb. "Represents the namespace in the folder where the View is located,".ViewModelsa.OhMyGod. "Represents the namespace where the ViewModel is located

var viewName = viewType.FullName.Replace(".Viewsb.", ".ViewModelsa.OhMyGod.");

Test represents ViewModel suffix

var viewModelName = $"{viewName}Test, {viewAssemblyName}";
  1. Custom ViewModel registration

We create a new Foo class as a custom class, with the following code:

using Prism.Commands;
using Prism.Mvvm;

namespace PrismSample
{
   public class Foo:BindableBase
    {

        private string _text;
        public string Text
        {
            get { return _text; }
            set { SetProperty(ref _text, value); }
        }

        public Foo()
        {
            this.Text = "Foo";
        }

        private DelegateCommand _clickCommnd;
        public DelegateCommand ClickCommnd =>
            _clickCommnd ?? (_clickCommnd = new DelegateCommand(ExecuteClickCommnd));

        void ExecuteClickCommnd()
        {
            this.Text = "Oh My God!";
        }
    }
}

Modify App.cs code:

protected override void ConfigureViewModelLocator()
{
    base.ConfigureViewModelLocator();
    ViewModelLocationProvider.Register<MainWindow, Foo>();
    //ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
    //{
    //    var viewName = viewType.FullName.Replace(".Viewsb.", ".ViewModelsa.OhMyGod.");
    //    var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
    //    var viewModelName = $"{viewName}Test, {viewAssemblyName}";
    //    return Type.GetType(viewModelName);
    //});
}

Run:

Click the button:

Even without commenting the code that modifies the naming rules, we found that the results were still the same, so we could conclude that

This direct and customized registration method without reflection registration will have higher priority, and the official document also states that this method will be more efficient.

The official provides 4 methods, and the remaining three registration methods are as follows:

ViewModelLocationProvider.Register(typeof(MainWindow).ToString(), typeof(MainWindowTest));
ViewModelLocationProvider.Register(typeof(MainWindow).ToString(), () => Container.Resolve<Foo>());
ViewModelLocationProvider.Register<MainWindow>(() => Container.Resolve<Foo>());
Keep Exploring

延伸阅读

更多文章