How to plan the Base ViewModel of JHRS WPF framework

How to plan the Base ViewModel of JHRS WPF framework? The previous article introduced the topic of How to load modules in the JHRS WPF framework. If you read this article, it means that we have entered some discussions on the business phase code.

The JHRS framework is based on WPF technology and uses MVVM to build a framework. Of course, it is open source. The functions that come out are not perfect. If you use them, there will definitely be many adjustments. The main purpose is to share how to solve the problems encountered in the actual project.

Reasonably design the ViewModel base class

wpf-mvvm
How to plan the Base ViewModel of JHRS WPF framework

Using MVVM in WPF to do projects, I don’t know how many teams strictly follow it. If you don’t understand MVVM, you can search for many blogs introducing these contents on Google.

If you don’t use MVVM for WPF projects, the simplest and rude way is to write various processing events in the post code, such as button click events, DataGrid binding data, and so on. Once you follow the MVVM, you can’t do whatever you want directly in the ViewModel. For example, you can’t control the hidden display of a button, the background color, and some behaviors of the interface in the ViewModel; therefore, design the ViewModel reasonably. The base class is particularly important.

The Base ViewModel of JHRS framework

Any project can be roughly classified into the management list page, the detail page, the new edit page, the floating prompt page (effect), the pop-up page, the message prompt, etc. according to the function points; and the base class of ViewModel that handles these function points has the same The sexual method can be refined into the base class, which can reduce a lot of repetitive code; how to refine this depends on the small partners in the team who are familiar with the business and the technology. Usually this may be the work of the architect in the team or Responsibilities of senior developers.

How to design a reasonable ViewModel base class in JHRS development framework
How to plan the Base ViewModel of JHRS WPF framework

For example, in the above figure, there is a common base class (BaseViewModel) and two business-related base classes defined in the JHRS framework according to the function. They are the base class used to manage the list page (BaseManagePageViewModel) and the new edit page. The base class (BaseDialogPageViewModel) is named BaseDialogPageViewModel because it uses modal windows for adding and editing operations.

BaseViewModel

First of all, this BaseViewModel class inherits from the BindableBase class provided by Prism , as the base class of all ViewModels, and other base classes with different functions inherit BaseViewModel to extend the common functions of the same business; as you can see from the above figure, the framework is defined The base class of the management list page and the base class of the new edit page are inherited from the BaseViewModel class.

This base class mainly defines common methods and attributes in the entire system. The current code mainly includes opening and closing modal windows, and realizes the dynamic splicing of context parameter transfer, event aggregator, log attributes, and query rules.

For example, the GetQueryRules method provided in the base class is used for splicing query rules. Its function is to automatically obtain the input data on the page when the user enters the query data when there are multiple query bars on any management list page. According to certain rules, the json data is passed into the background web api to execute the query to obtain the data; of course, the corresponding web api will be automatically parsed into a Linq expression (Expression), similar to the parameters passed in by calling this code on the server side [expression] 】same.

IQueryable<T> Where(Expression<Func<T, bool>> expression);

How to plan the Base ViewModel of JHRS WPF framework

Simply put, it can be understood as the same where conditions in spelling SQL.

jhrs-query
How to plan the Base ViewModel of JHRS WPF framework

Because the query function is indispensable to all systems, these methods are directly placed in the base class. Of course, it is a virtual method that can be overridden by subclasses; but in most cases, this is generally not done.

This class can also be inherited by the ViewModel of some simple functional pages (Page), for example, it can be inherited only by a page with details.

BaseManagePageViewModel

It can be seen from the naming that this class is provided in the framework for pages that can be paging query with management functions. It mainly provides three public properties (PagingData, PageData, SelectedList) and page loading event methods (subclasses need to be implemented) ), new methods, binding data methods, and methods and callback methods before changing the business state.

Still use the demo interface in the framework to illustrate the problem. A typical management list page is as shown in the figure below (regardless of how the interface is displayed and placed, only the core issues are described), there is a query button, and there are various types on the right Buttons, such as adding, exporting, batch printing, etc. buttons are common. There is a paging control at the bottom of the table (not shown in the figure, it may be a bug in the program and not repaired). Clicking the page will jump to the corresponding page to load the data.

There is an event, so these can be encapsulated into the base class of the management function , and the subclass viewmodel can implement the related business.

jhrs-baseviewmodel
How to plan the Base ViewModel of JHRS WPF framework

This is only designed like this in the demo framework. In actual projects, you can abstract and extend the interface designed according to your own needs and the product.

PagingData: Package related to paging, including page number (PageIndex), number of data items displayed per page (PageSize), total number (Total), total number of pages (MaxPageCount), and assign values ​​after calling the paging interface (web api).

PageData: The data source of the DataGrid. This object is of type IEnumerable<object>. Generally, it is assigned a value after calling the web api to get the data.

SelectedList: When the DataGrid has a check box function, the selected data collection.

When the subclass inherits this class, if the function is not complicated, that is, there is no extra button event to handle, generally only 4 methods need to be implemented, as shown in the following AccountListViewModel.cs

/// <summary>
     /// Account management business
     /// </summary>
     public class AccountListViewModel: BaseManagePageViewModel
     {
         /// <summary>
         /// Account management business constructor
         /// </summary>
         /// <param name="container"></param>
         public AccountListViewModel(IContainerExtension container): base(container)
         {
             PagingData.PageSize = 20;
         }


         public override DelegateCommand AddCommand => new DelegateCommand(()=> {});

         public override void PageLoaded(Page page)
         {
           
         }

         protected override Task<object> BindPagingData()
         {
             throw new NotImplementedException();
         }

         protected override Task<object> UpdateDataStatus<TEntity>(TEntity entity)
         {
             throw new NotImplementedException();
         }
     }
}

How to plan the Base ViewModel of JHRS WPF framework

BaseDialogPageViewModel

This base class is specifically used to add and edit pages. Subclasses can inherit it and implement the save method. Generally speaking, if a page is added and modified, it is convenient for adding new pages. But for the editing function, when entering the editing mode, you need to initialize and assign the relevant form controls on the page. For example, the drop-down box (Comobox) needs to bind the data source and select the original value, and the text box needs to be assigned. The original input value, fortunately, WPF is two-way binding, so you can save a lot of things.

A typical new editor subclass is implemented like this.

    /// <summary>
    /// Add appointment registration and edit the viewmodel of the appointment registration function page, which is used to process business logic
    /// Call web api to save data
    /// </summary>
    public class AddOrEditReservationViewModel: BaseDialogPageViewModel
    {
        /// <summary>
        /// Add a new construction function for appointment registration business processing
        /// </summary>
        /// <param name="container"></param>
        public AddOrEditReservationViewModel(IContainerExtension container): base(container)
        {
            InintData();
        }

        /// <summary>
        /// Initialize interface data in edit mode
        /// </summary>
        private void InintData()
        {
            ReservationOutputDto current = this.GetContext<ReservationOutputDto>();
            //Not null means in edit mode
            if (current != null)
            {
                Dto = new ReservationInputDto
                {
                    DepartmentID = current.DepartmentID,
                    DepartmentName = current.DepartmentName,
                    DoctorName = current.DoctorName,
                    Gender = current.Gender,
                    Index = current.Index,
                    BusinessNumber = current.BusinessNumber,
                    Name = current.Name,
                    ReservationTime = current.ReservationTime
                };
            }
        }

        private ReservationInputDto _dto = new ReservationInputDto();

        /// <summary>
        /// Information entered on the interface
        /// </summary>
        public ReservationInputDto Dto
        {
            get {return _dto;}
            set {SetProperty(ref _dto, value);}
        }

        /// <summary>
        /// New, edit the save method, get the data from the viewmodel and save it.
        /// </summary>
        /// <returns></returns>
        [WaitComplete]
        protected async override Task SaveCommand()
        {
            var current = this.GetContext<ReservationOutputDto>();
            if (current == null)
            {
                if (!IsDevelopment)
                {
                    var response = await RestService.For<IReservationApi>(AuthClient).Add(Dto);
                    AlertPopup(response.Message, response.Succeeded? MessageType.Success: MessageType.Error, (d) =>
                    {
                        if (response.Succeeded)
                            this.CloseDialog(returnValue: "It has been added successfully. This can be any parameter and object. The parent form can receive this return parameter.");
                    });
                }
            }
            else
            {
                if (!IsDevelopment)
                {
                    var response = await RestService.For<IReservationApi>(AuthClient).Update(Dto);
                    AlertPopup(response.Message, response.Succeeded? MessageType.Success: MessageType.Error, (d) =>
                    {
                        if (response.Succeeded)
                            this.CloseDialog(returnValue: "It has been modified successfully. This can be any parameter and object. The parent form can receive this return parameter.");
                    });
                }
            }
        }
    }

How to plan the Base ViewModel of JHRS WPF framework

The xaml code on the WPF interface is just some form controls, you can see the source code here .

in conclusion

In a real project, the ViewModel base class should be designed reasonably according to the actual project. This article only provides a way of thinking, which can be flexibly controlled in practical applications. This is also a necessary skill for the program to kill people in the rivers and lakes. As the so-called people are in the arena, they can’t help themselves. When you do this, you still have to think about recruiting when you encounter problems.

The next article will share the topic of using WPF development projects, some common components are encapsulated into user controls , and those who are interested can pay attention to it.

Related reading in this series

  1. WPF Enterprise Development Framework Building Guide (Revelation)
  2. Basic class library of JHRS development framework
  3. Selection of third-party frameworks for JHRS development framework
  4. WPF call Web API package of JHRS development framework
  5. Client portal project of JHRS development framework
  6. How to load modules in the JHRS WPF framework
  7. How to plan the Base ViewModel of JHRS WPF framework
  8. Encapsulation of public component user control of JHRS development framework
  9. Some principles of cataloging documents followed by the recommendations of the JHRS development framework
  10. WPF data verification of JHRS development framework
  11. The solution of JHRS development framework’s ViewModel mutual parameter transfer and pop-up frame return parameter
  12. JHRS development framework of stepping on the pit (final chapter)

Leave a Comment