Blazor Grid Column Order

Hello,

I have a component which some standard columns I want in most of my tables. It takes a @ChildContent which defines specific columns to display in the grid. It looks like this:

<RadzenGrid TItem="TRecord"
            RowSelect="RowSelected">
    <Columns>
        @if (ShowEditButtons)
        {
            @*A column that goes at the beginning and defines some buttons*@
        }

        @ChildContent

        @*Some columns that go at the end*@
    </Columns>
</RadzenGrid>

This allows some flexibility to show/hide columns as needed. I have found that when the user toggles ShowEditButtons to True or if they add columns to @ChildContent, both of which add a new column to the grid, that the new column will end up at the end of the grid instead of the intended position.

I assume this is because the new RadzenGridColumn which is being rendered is just added a list of columns, and is at the end. I think it would be great if there was an optional parameter for ColumnOrder which I could specify.

I did try toggling Visible from false to true, or changing Width from 0rem to something longer as options to show or hide columns. That worked OK on the cells of the column, but the header wouldn't show up.

Hi @mconrad,

Try to execute StateHasChanged() on ShowEditButtons change.

No luck. Here is a complete example.The edit buttons always end up on the right.

<div class="main">
    <button class="btn"
            @onclick="ToggleButtons">
        Show/Hide buttons
    </button>

    <RadzenGrid AllowFiltering="true" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" AllowPaging="true" PageSize="4"
                AllowSorting="true" Data="@people" TItem="Person" ColumnWidth="200px">
        <Columns>
            @if (showButtons)
            {
                <RadzenGridColumn TItem="Person" Sortable="false" Width="12rem">
                    <Template Context="record">
                        <button class="btn"
                                @onclick="@(async () => { })">
                            Edit @record.Name
                        </button>
                    </Template>
                </RadzenGridColumn>
            }
            <RadzenGridColumn TItem="Person" Property="Name" Title="Name" />
        </Columns>
    </RadzenGrid>
</div>

@code{

    IEnumerable<Person> people;
    bool showButtons;

    protected override void OnInitialized()
    {
        people = new List<Person>
        {
            new Person{Name = "Bob"},
            new Person{Name = "Sue"},
        };
        base.OnInitialized();
    }

    void ToggleButtons()
    {
        showButtons = !showButtons;
        StateHasChanged();
    }

    class Person
    {
        public string Name { get; set; }
    }
}

@enchev Anything else I should try for now? If not, does this look like something that can be addressed in a future release?

The only option I can suggest is to declare all columns with desired order with if/else. I’ll check if there is a way to fix this.

In the smaller example I gave, I thought that's what I am doing. Is there something I should change?

In your example you only show/hide the button column while my idea is to show/hide whole set of columns - one with button and one without

Hi @enchev, @mconrad.
Problem with column order is due blazor optimization in BuildRenderTree.

To avoid rewrite BlazorGrid twice, One solution could be create a new component with only Datagrid with all columns using @if (showColumns) and showColumns as parameter.
And in Parent do:

@if(showColumns)
{
<ChildDataGrid showColumns="@showColumns" .../>
}
else
{
<ChildDataGrid showColumns="@showColumns" .../>
}

This sound repeated but force Blazor to recreate component and component is create with showColumns dependence.

Thanks, @enchev @ctnet

Both of these make sense as work around for the simple example I showed. I don't think they can solve the issue where I am changing the ChildContent columns. @ctnet I'm not sure if I tried this option exactly, but I was thinking the option of last resort might be to force blazor to make a new component no matter what when this changed.

I think if Visible worked as expected (so that the column header showed/hid with the columns) or if there was a new parameter for column order, then I think I could handle the ChildContent columns as well.

Finally have a solution: As @ctnet pointed out this issue was happening because of how blender optimizes render tree building.

I realized we can use the @key directive by binding it to the record ID that was populating my grid. Then when the record changed, blazor will see the @key change and dump and rebuild the grid from scratch.