DotVVM Controls : GridView
Tags: dotvvm, webforms, csharp, dotnetcore
Published: 2020-07-22 22:06:46

GridView control in DotVVM is very similar to what we used to use in our legacy web forms applications. When you run your DotVVM application, it is getting rendered as a classic HTML table.

In DotVVM, you can bind your `GridView` control by setting `DataSource` property to `IEnumerable<T>` or `GridViewDataSet<T>` object. GridView Control in DotVVM supports inline editing, sorting and defining your column template.

#### Simple GridView
Suppose we want to display a list of students.
```
public class Student
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime EnrollmentDate { get; set; }
}    
```
in ViewModel class
```
public List<Student> Students { get; set; }
```
in dothtml file 
```
<dot:GridView DataSource="{value: Students}" class="page-grid">
	<Columns>
		 <dot:GridViewTextColumn ValueBinding="{value: FirstName}" HeaderText="First Name" />
         <dot:GridViewTextColumn ValueBinding="{value: LastName}" HeaderText="Last Name" />
         <dot:GridViewTextColumn ValueBinding="{value: EnrollmentDate}" HeaderText="Enrollment Date" />
	</Columns>
</dot:GridView>
```
we used `GridViewTextColumn` for all fields and used `ValueBinding` attribute to specify which property is going to be rendered in that column. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/flf7djiuf7f8uaew6bnh.png)

By Default DotVVM is getting the string representation of the specified value and render it.
#### FormatString
To specify a specific format for the rendered value, we can do that by setting `FormatString` of the target column. DotVVM is supporting most of .Net format strings
```
<dot:GridViewTextColumn ValueBinding="{value: EnrollmentDate}" 
 FormatString="yyyy-MM-dd" 
 HeaderText="Enrollment Date" />
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d60ug9pauawij4gkecbt.png)

#### Inline Editing
In the past when we tried to implement inline editing for a GridView in web forms application we had had to write many lines of code and implement Edit event but in DotVVM it pretty easy to implement it with only one limitation, your data source should be of type `GridViewDataSet<T>`. `IEnumerable<T>` is not supported for inline editing.

In ViewModel class change the Students property type and Set `RowEditOptions.PrimaryKeyPropertyName` to your list unique key(in our case is `Id`).

```
public GridViewDataSet<Student> Students { get; set; } = new GridViewDataSet<StudentListModel>()
   {
      RowEditOptions = { PrimaryKeyPropertyName = "Id" }
   };
```  
In `PreRender` method populate your `GridViewDataSet<Student>`
```
public override async Task PreRender()
{
     if (Students.IsRefreshRequired)
     {
         var queryable = await _studentService.GetAllStudentsAsync();
         Students.LoadFromQueryable(queryable.AsQueryable());
     }
     await base.PreRender();
}
```
in dothtml file, set `InlineEditing` attribute of your GridView to `true`. By default DotVVM is allowing all columns to be editable. If you want to prevent a specific column to be edited you need to set its `IsEditable` attribute to `false`
```
<dot:GridView DataSource="{value: Students}" class="page-grid" InlineEditing="true">
  <Columns>
    <dot:GridViewTextColumn ValueBinding="{value: FirstName}" HeaderText="First Name" />
    <dot:GridViewTextColumn ValueBinding="{value: LastName}" HeaderText="Last Name" />
    <dot:GridViewTextColumn ValueBinding="{value: EnrollmentDate}"
       IsEditable="false"
       HeaderText="Enrollment Date" FormatString="yyyy-MM-dd" />
    <dot:GridViewTemplateColumn>
        <ContentTemplate>
           <dot:Button class Text="Edit" Click="{command: _parent.Edit(_this)}" />
        </ContentTemplate>
        <EditTemplate>
           <dot:Button Text="Save" Click="{command: _parent.Update(_this)}" />
           <dot:Button Text="Cancel" Click="{command: _parent.Cancel()}" />
        </EditTemplate>
    </dot:GridViewTemplateColumn>
  </Columns>  
</dot:GridView>
```
We added a` GridViewTemplateColumn` and specified its `ContentTemplate` which will be rendered in normal display 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fjko72wdov3c5l97eacy.png)
and `EditTemplate` which will be rendered when we click Edit button 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5drqna12eyz2a351y7me.png)

`_parent` is instance of your model object and `_this` which is passed to `Edit` and `Update` Methods is the corresponding item in GridView data source.

in ModelView class we need to add the commands (normal c# method) that will be executed when the user click on Edit, Save, and cancel buttons.

```
public void Edit(Student student)
{
     Students.RowEditOptions.EditRowId = student.Id;
}
public void Cancel()
{
     Students.RowEditOptions.EditRowId = null;
     Students.RequestRefresh();
}
public void Update(StudentListModel model)
{
     // code for updating your datastore
     .....
     Students.RowEditOptions.EditRowId = null;
}
```

> When you do inline editing, DotVVM does't refresh the whole page, but it do it via ajax calls.

#### Nested GridViews
Suppose we want to display student grades in the same row besides his Name. to achieve this, the Student Object should contains a property if type `GridViewDataSet` for grades List. Then in `Prerender()` method populate that property for each Student object.

```
public override async Task PreRender()
{
     if (Students.IsRefreshRequired)
     {
         var queryable = await _studentService.GetAllStudentsAsync();
         queryable.ForEach(x =>
         {
             x.Grades = new GridViewDataSet<Grade>()
             {
                RowEditOptions = { PrimaryKeyPropertyName = "GradeId" }
             };                 
             x.Grades.LoadFromQueryable(x.StudentGrades.AsQueryable());
         });
         Students.LoadFromQueryable(queryable.AsQueryable());
     }
     await base.PreRender();
}
```
in dothtml file will add a new GridViewTemplateColumn for the inner GridView
```
<dot:GridViewTemplateColumn HeaderText="Grades" IsEditable="false">
     <dot:GridView DataSource="{value: Grades}" class="page-grid">
          <Columns>
              <dot:GridViewTextColumn ValueBinding="{value: Subject}" HeaderText="Subject" />
              <dot:GridViewTextColumn ValueBinding="{value: Month}" HeaderText="Month" />
              <dot:GridViewTextColumn ValueBinding="{value: Score}" HeaderText="Score" />                            
          </Columns>
     </dot:GridView>
</dot:GridViewTemplateColumn>
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5vz98dkv4nj4y5zwcdn6.png)
#### Summary
In this article we demonstrated how to use DotVVM GridView control and how it is pretty easy to bind your collection to it, enable inline editing without re-loading the whole page and how to render nested GridViews with few line of code.