Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MudBlazor with Dynamic Columns

I'd like to create a way to create dynamic columns using PropertyColumn in MudBlazor Datagrid.

<MudDataGrid @ref=_grid Items="GetItems(Model.ModelClass.Object, Items)">
    <Columns>
   @foreach(ListViewColumn col in Listview.Columns.OrderBy(x => x.Index))
    {
        <PropertyColumn Property="@MakeExpression(col, Model.ModelClass.Object, PropertyMatch(col).PropertyType)" Title="@col.Caption" />
    }
    </Columns>
</MudDataGrid>
@code{

    Expression<Func<T, P>> MakeExpression<T, P>(ListViewColumn col, T obj, P item) where T : Type
    {  
        var text = $"x => x.{col.PropertyName}";
        return System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda<T, P>(new System.Linq.Dynamic.Core.ParsingConfig(), true, text);
    }
}

However, it is still giving me an exception: No property or field 'String1' exists in type 'Type''

String1 is the propertyName.. Model.ModelClass.Object is the type to reflect the T of the MudDataGrid

How do I fix my Expression<Func<T,P>> method?

like image 331
Michael de Vlieger Avatar asked Jul 28 '26 08:07

Michael de Vlieger


1 Answers

Here is how i made it work.

Firstly, create a GenericComponent call DataGrid, which contains the DataGrid:

@typeparam T
    
<MudDataGrid T="T" Items="@Items">
   <Columns>
    <SelectColumn T="T" />
    
 @foreach (var PInfo in typeof(T).GetProperties())
  {
   if (PInfo.PropertyType == typeof(string))
   {
    <PropertyColumn Property="@(GetStringPropertyLambdaExpression(PInfo))" />
   }
  }
 </Columns>
</MudDataGrid>

code{

 [Parameter]
 public string Title { get; set; }

 [Parameter]
 public IEnumerable<T> Items { get; set; }

  private Expression<Func<T, string>> GetStringPropertyLambdaExpression(System.Reflection.PropertyInfo propertyInfo)
  {
      // Define a parameter for the lambda expression
      ParameterExpression param = Expression.Parameter(typeof(T), "x");

      // Create an expression to access the property
      Expression propertyAccess = Expression.Property(param, propertyInfo);


      // Create a lambda expression that takes an AType parameter and returns its Name property
      Expression<Func<T, string>> lambdaExpression = Expression.Lambda<Func<T, string>>(propertyAccess, param);

      return lambdaExpression;
  }

}

Then i just use it in my page like that: dataname is the name of my datasource. On parameter set. I build the datasource depend on its name. It can be list of person, contact list, product list...

@page "/infolist/{*dataname}"

<MudText Typo="Typo.caption"  >@dataname</MudText>

@InfoGrid

Code block of the page, where my datagrid is added after parameters are set


      protected override async Task OnParametersSetAsync()
      {
          try
          {
              await base.OnParametersSetAsync();

              if (DataNameChanged)
              {                                    
                 await vm.LoadAsync();
                 InfoGrid = AddGridView();
                 StateHasChanged();

              }

          }
          catch (Exception ex)
          {
              await alert.ShowErrorAsync(ex);
          }
      }

      private RenderFragment InfoGrid { get; set; }
          
      private RenderFragment AddGridView() => __builder =>
      {
          var ItemType = ViewModel.RowDataType;

          var sample = Activator.CreateInstance(ItemType);

          var genericType = typeof(GridView<>);

          var theGridType = genericType.MakeGenericType(ItemType);

          __builder.OpenComponent(11, theGridType);
         
          __builder.AddAttribute(23, "Items", ViewModel.Items);

          __builder.CloseComponent();

      };

The Property Attribute of Mud PropertyColumn is Expression<Func<T,TProperty>>.

I don't know how or where to define TProperty, so I've fixed it as string, decimal, datetime... It's ugly, but it is the best solution I can come up with for now. I hope someone can enlighten me with a better solution.

like image 195
Eric Ngo Avatar answered Jul 30 '26 22:07

Eric Ngo