This is a migrated thread and some comments may be shown as answers.

Bind data to dictionary with columnMenu

6 Answers 275 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Sebastian
Top achievements
Rank 1
Sebastian asked on 16 Apr 2020, 03:01 PM
I have a grid in which I want to bind the generated columns inside the foreach-loop (currently set to "Number") to the dictionary entry of e.Key. The code below works, but I have the problem that I need the sorting functionality of the column menu to sort by the dictionary entry. In the current code I get the Bound "Number" as field to sort by, but I need the dictionary key.
 
@(Html.Kendo().Grid<Bauteil>()
                .Name("PartSearchGrid")
                .Resizable(resize => resize.Columns(true))
                .Sortable()
                .ClientDetailTemplateId("detailtemplate")
                .PersistSelection(true)
                .Selectable(selectable => selectable
                .Type(GridSelectionType.Row)
                .Mode(GridSelectionMode.Single)
                )
                .ToolBar(tools =>
                {
                    tools.Custom().Text("<input id='partsearchbox' onkeyup='onSearch()' placeholder='" + GuiLabel["Label_Search"].Value + "' />");
                    tools.Excel();
                    tools.Custom().Text("Reset").HtmlAttributes(new { onclick = "resetFilter()" });
                })
                .Pageable(pageable => pageable
                .PageSizes( new[] { 10, 20, 50, 100, 500, 1000 })
                .Enabled(true)
                .Numeric(true)
                )
                .Scrollable(s => s.Virtual(GridVirtualizationMode.Rows))
                .Columns(columns =>
                {
                    columns.Bound(p => p.Number).Width(100);
                    columns.Bound(p => p.Name).Width(100);
                    columns.Bound(p => p._calcNoOfProcesses).Width(100);
 
                    foreach (Meta_PlanningProfileEntry e in Model.Part_Profile_Entries)
                    {
                        columns.Bound("Number").ClientTemplate("# if (PlanningDataDict[\"" + e.Key + "\"] != null) { #" + "<p>#= PlanningDataDict[\"" + e.Key + "\"] #</p>" + "# } else { #" + "" + "# } #").Width(100);
                    }
                    columns.Bound(p => p.StateString).Width(100);
                })
                .Excel(excel => excel
                .FileName("TP_Parts_Export.xlsx")
                .AllPages(true)
                )
                .DataSource(dataSource => dataSource
                .Ajax()
                .PageSize(50)
                .ServerOperation(true)
                .Model(model =>
                {
                    model.Id(m => m.ID);
                })
 
                .Read(r => r.Action("Parts_Read", "Part").Data("getPartFilters"))
                )
                .ColumnMenu()
                )

6 Answers, 1 is accepted

Sort by
0
Tsvetomir
Telerik team
answered on 20 Apr 2020, 09:13 AM

Hi Sebastian,

Based on the provided information, I cannot be sure what is the exact implementation for the Meta_PlanningProfileEntry model. In general, you should be able to access the Key value from the model and cast it to a string. After that the column.Bound() option will make all the necessary bindings.

However, in order for the sorting of the column to work, it is mandatory to have such a field in the data source of the grid. The sorting is happening on the data source level. Can you ensure that for each of the keys of the dictionary, there is a corresponding field in the data source? 

It would be very helpful if you could share a sample response from the server-side along with the implementation for the Meta_PlanningProfileEntry model. 

Looking forward to your reply.

 

Regards,
Tsvetomir
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Sebastian
Top achievements
Rank 1
answered on 20 Apr 2020, 11:21 AM
public class Bauteil
{
    public string ID { get; set; }
    public Dictionary<string, string> PlanningDataDict { get; set; }
    public string Name { get; set; }
    public string Number { get; set; }
    public string _calcNoOfProcesses { get; set; }
    public string StateString { get; set; }
    ...
}
   
   
   
public class Meta_PlanningProfileEntry
{
    public string Key { get; set; }
    public string Title { get; set; }
    public string Unit { get; set; }
    ...
}

Hi Tsvetomir,

Thanks for your reply, I have a list of profile entries (Meta_PlanningProfileEntry) which describe columns that should be displayed in the grid. These can be changed by the user (saved in database).
The Grid should be bound to a List<Bauteil>, each Bauteil has a few properties and a dictionary with the additional properties. In the grid I would like to see some standard fields (Number, Name, _calcNoOfProcesses, StateString) and additionaly the properties described by the profile entries. If I just bind the dictionary entry like columns.Bound("PlanningDataDict[\"" + e.Key + "\"]") I get the following error:
InvalidOperationException: Bound columns require a field or property access expression.

0
Tsvetomir
Telerik team
answered on 22 Apr 2020, 09:31 AM

Hi Sebastian,

Thank you for the provided information. Indeed, binding the columns of the grid to a dictionary of key-value pairs is possible. I have attached a sample project that demonstrates the same. 

However, the functionality you are willing to achieve could not be implemented in such a way. What you would like to happen is that the columns will be populated with a value from the data source. However, at the moment of the initialization of the grid, the "PlanningDataDict" property is empty. This is due to the fact that the PlanningDataDict will be available after the data source sends a request to the server-side and retrieves the data. 

That is why the ClientTemplate is property rendered - the PlanningDataDict is available, and the "e.Key" has already been evaluated. 

What I can recommend is that you use the e.Value from the dictionary for the specific column.Bound() declaration:

                columns.Bound(e.Value).Width(100);

I hope you find those clarifications helpful.

 

Regards,
Tsvetomir
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Sebastian
Top achievements
Rank 1
answered on 07 May 2020, 01:06 PM

Hi Tsvetomir,

I've altered your code to match the exact problem I have. I need the Dictionary to get the proper values because the displayed data can vary from user to user. If I just bind it to some property like number, with the ClientTemplate displaying the PlanningDataDict entry, it works but the problem is that I need to bind it properly to get the right member for the sorting functionality. Is there maybe a workaround for this?

0
Sebastian
Top achievements
Rank 1
answered on 07 May 2020, 01:16 PM
I removed the bin folder to not exceed the upload limit. it should work with yours
0
Tsvetomir
Telerik team
answered on 08 May 2020, 01:28 PM

Hi Sebastian,

Thank you for the provided modification of the sample project. Indeed, the scenario you are facing has to be handled explicitly. I have made the needed changes in which the column could be sorted and dynamically bound to the "key" of the dictionary:

    .Columns(columns =>
    {
        foreach (var e in Model)
        {
            columns.Bound("[PlanningDataDict['" + e.Key + "']]").Width(100).Title(e.Label).ClientTemplate("# if (PlanningDataDict[\"" + e.Key + "\"] != null) { #" + "<p>#= PlanningDataDict[\"" + e.Key + "\"] #</p>" + "# } else { #" + "" + "# } #"); //displays right values but need binding for sorting
                  
        }

This approach, however, requires the grid to be bound to a dynamic instead of a strongly-typed C# class. This leads to the grid interpreting all of the columns to be of string type. You should ensure that you explicitly set the type of the field in the Model declaration of the grid.

Attached is a modified version of the sample.

 

Regards,
Tsvetomir
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Tags
Grid
Asked by
Sebastian
Top achievements
Rank 1
Answers by
Tsvetomir
Telerik team
Sebastian
Top achievements
Rank 1
Share this question
or