Master Detail

The simplest way to deal with hierarchical data is the master-detail model. Use a control to select the main item and one or more additional controls to show the main item's details.

For example, the ComboBox below is used as a master control. Select a country from the combo and the grid below will show the items in that country:

Id
Country
Product
Date
Sales
Expenses
0
US
Phones
5/19/2025
1,929.71
1,345.54
6
US
Cars
5/25/2025
9,575.84
2,316.73
12
US
Stereos
5/31/2025
7,812.13
1,492.09
18
US
Watches
6/6/2025
8,369.35
714.09
24
US
Computers
6/12/2025
1,192.46
4,525.86
30
US
Phones
6/18/2025
4,604.02
1,452.35
36
US
Cars
6/24/2025
5,698.02
861.66
42
US
Stereos
6/30/2025
9,244.90
4,696.78
48
US
Watches
7/6/2025
9,010.82
2,288.38

In the next example, FlexGrid is used as the master control. Select an item on the grid and see the details in the controls below:

Master

Id
Country
Product
Date
Sales
Expenses
0
US
Phones
5/19/2025
1,929.71
1,345.54
1
Germany
Cars
5/20/2025
4,544.39
2,248.78
2
UK
Stereos
5/21/2025
8,964.70
4,088.58
3
Japan
Watches
5/22/2025
8,170.57
1,770.48
4
Italy
Computers
5/23/2025
8,420.01
569.62
5
Greece
Phones
5/24/2025
6,577.75
2,005.51
6
US
Cars
5/25/2025
9,575.84
2,316.73
7
Germany
Stereos
5/26/2025
8,434.58
3,094.28
8
UK
Watches
5/27/2025
5,624.61
2,939.69
9
Japan
Computers
5/28/2025
9,787.05
1,709.11
10
Italy
Phones
5/29/2025
6,720.17
302.26
11
Greece
Cars
5/30/2025
4,676.74
1,925.68
12
US
Stereos
5/31/2025
7,812.13
1,492.09
13
Germany
Watches
6/1/2025
114.55
1,620.47
14
UK
Computers
6/2/2025
344.87
1,089.86
15
Japan
Phones
6/3/2025
7,532.26
3,769.57
16
Italy
Cars
6/4/2025
6,924.56
4,495.59
17
Greece
Stereos
6/5/2025
557.79
259.32
18
US
Watches
6/6/2025
8,369.35
714.09
19
Germany
Computers
6/7/2025
3,200.95
727.09
20
UK
Phones
6/8/2025
837.78
1,639.84
21
Japan
Cars
6/9/2025
3,962.61
2,532.72
22
Italy
Stereos
6/10/2025
2,050.58
1,890.15
23
Greece
Watches
6/11/2025
6,307.37
4,253.01
24
US
Computers
6/12/2025
1,192.46
4,525.86
25
Germany
Phones
6/13/2025
5,335.48
3,418.66
26
UK
Cars
6/14/2025
5,625.37
1,419.91
27
Japan
Stereos
6/15/2025
438.55
4,985.92
28
Italy
Watches
6/16/2025
8,525.85
4,896.83
29
Greece
Computers
6/17/2025
6,347.98
1,647.53
30
US
Phones
6/18/2025
4,604.02
1,452.35
31
Germany
Cars
6/19/2025
283.39
1,262.15
32
UK
Stereos
6/20/2025
7,480.71
3,944.38
33
Japan
Watches
6/21/2025
4,162.84
2,769.34
34
Italy
Computers
6/22/2025
9,681.38
3,864.47
35
Greece
Phones
6/23/2025
6,632.08
3,311.05
36
US
Cars
6/24/2025
5,698.02
861.66
37
Germany
Stereos
6/25/2025
5,179.17
1,356.54
38
UK
Watches
6/26/2025
6,324.32
3,192.94
39
Japan
Computers
6/27/2025
7,174.70
751.44
40
Italy
Phones
6/28/2025
5,206.30
4,104.93
41
Greece
Cars
6/29/2025
3,450.85
2,391.44
42
US
Stereos
6/30/2025
9,244.90
4,696.78
43
Germany
Watches
7/1/2025
668.37
680.52
44
UK
Computers
7/2/2025
9,983.65
4,155.87
45
Japan
Phones
7/3/2025
4,915.80
1,691.84
46
Italy
Cars
7/4/2025
9,512.08
482.27
47
Greece
Stereos
7/5/2025
712.41
775.93
48
US
Watches
7/6/2025
9,010.82
2,288.38
49
Germany
Computers
7/7/2025
173.71
4,580.18

Detail

Country:
Product:
Date:
Sales:
Expenses:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// This file locates: "Scripts/Lesson/C1FlexGrid/MasterDetail.js".
c1.documentReady(function () {
    // create some random data
    var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(',');
    var products = 'Phones,Cars,Stereos,Watches,Computers'.split(',');
    var data = [];
    for (var i = 0; i < 50; i++) {
        data.push({
            id: i,
            country: countries[i % countries.length],
            product: products[i % products.length],
            date: wijmo.DateTime.addDays(new Date(), i),
            sales: Math.random() * 10000,
            expenses: Math.random() * 5000,
        });
    }
 
    // show countries in combo
    var theCombo = wijmo.Control.getControl('#theCombo');
    theCombo.selectedIndexChanged.addHandler(function (s, e) {
        view.refresh();
    });
 
    // show items for the selected country in the detail grid
    var theGridDetail = wijmo.Control.getControl('#theGridDetail');
    theGridDetail.itemsSource = data;
 
    //show items for the selected country
    var view = theGridDetail.collectionView;
    view.filter = function (item) {
        return item.country == theCombo.text;
    }
 
    // using a grid as the master
    var theGridMaster = wijmo.Control.getControl('#theGridMaster');
    theGridMaster.itemsSource = data;
    theGridMaster.selectionChanged.addHandler(function (s, e) {
        updateDetailControls();
    });
 
    // update detail controls when selection changes
    function updateDetailControls() {
        var item = theGridMaster.collectionView.currentItem;
        var bndCtls = document.querySelectorAll('.bnd-ctl');
        for (var i = 0; i < bndCtls.length; i++) {
            var host = bndCtls[i];
            var prop = host.id.substr(3).toLowerCase();
            var ctl = wijmo.Control.getControl(host);
            if (wijmo.isString(item[prop])) {
                ctl.text = item[prop];
            } else {
                ctl.value = item[prop];
            }
        }
    }
 
    // set a property on the current item
    function setProperty(prop, val) {
        var v = theGridMaster.collectionView;
        v.editItem(v.currentItem);
        v.currentItem[prop] = val;
        v.commitEdit();
    }
 
    // define detail controls
    var theCountry = wijmo.Control.getControl('#theCountry');
    theCountry.textChanged.addHandler(function (s, e) {
        setProperty('country', s.text);
    });
    var theProduct = wijmo.Control.getControl('#theProduct');
    theProduct.textChanged.addHandler(function (s, e) {
        setProperty('product', s.text);
    });
    var theDate = wijmo.Control.getControl('#theDate');
    theDate.valueChanged.addHandler(function (s, e) {
        setProperty('date', s.value);
    });
    var theSales = wijmo.Control.getControl('#theSales');
    theSales.valueChanged.addHandler(function (s, e) {
        setProperty('sales', s.value);
    });
    var theExpenses = wijmo.Control.getControl('#theExpenses');
    theExpenses.valueChanged.addHandler(function (s, e) {
        setProperty('expenses', s.value);
    });
});
1
2
3
4
5
6
7
8
// This file locates: "Content/css/Lesson/C1FlexGrid/MasterDetail.css".
.wj-flexgrid {
  max-height: 220px;
}
.tbl-spaced td {
  vertical-align: middle;
  margin: 3px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
using System.Web.Mvc;
 
namespace LearnMvcClient.Controllers
{
    public partial class C1FlexGridController : Controller
    {
        // GET: MasterDetail
        public ActionResult MasterDetail()
        {
            return View();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@{
    var countries = new[] { "US", "Germany", "UK", "Japan", "Italy", "Greece" };
    var products = new[] { "Phones", "Cars", "Stereos", "Watches", "Computers" };
}
 
<h1>
    @Html.Raw(Resources.C1FlexGrid.MasterDetail_Title)
</h1>
<p>
    @Html.Raw(Resources.C1FlexGrid.MasterDetail_Text1)
</p>
 
<p>
    @Html.Raw(Resources.C1FlexGrid.MasterDetail_Text2)
</p>
 
<label>
    @Html.Raw(Resources.C1FlexGrid.MasterDetail_Text3)
    @Html.C1().ComboBox().Id("theCombo").Bind(countries)
</label>
@Html.C1().FlexGrid().Id("theGridDetail")
 
<p>
    @Html.Raw(Resources.C1FlexGrid.MasterDetail_Text4)
</p>
 
<h3>
    @Html.Raw(Resources.C1FlexGrid.MasterDetail_Title1)
</h3>
@Html.C1().FlexGrid().Id("theGridMaster").SelectionMode(C1.Web.Mvc.Grid.SelectionMode.Row).IsReadOnly(true)
 
<h3>
    @Html.Raw(Resources.C1FlexGrid.MasterDetail_Title2)
</h3>
<table class="tbl-spaced">
    <tr>
        <td>@Html.Raw(Resources.C1FlexGrid.MasterDetail_Text5)</td>
        <td id="theCountry" class="bnd-ctl"></td>
        @Html.C1().ComboBox("#theCountry").Bind(countries)
    </tr>
    <tr>
        <td>@Html.Raw(Resources.C1FlexGrid.MasterDetail_Text6)</td>
        <td id="theProduct" class="bnd-ctl"></td>
        @Html.C1().ComboBox("#theProduct").Bind(products)
    </tr>
    <tr>
        <td>@Html.Raw(Resources.C1FlexGrid.MasterDetail_Text7)</td>
        <td id="theDate" class="bnd-ctl"></td>
        @Html.C1().InputDate("#theDate")
    </tr>
    <tr>
        <td>@Html.Raw(Resources.C1FlexGrid.MasterDetail_Text8)</td>
        <td id="theSales" class="bnd-ctl"></td>
        @Html.C1().InputNumber("#theSales").Format("n2").Step(10)
    </tr>
    <tr>
        <td>@Html.Raw(Resources.C1FlexGrid.MasterDetail_Text9)</td>
        <td id="theExpenses" class="bnd-ctl"></td>
        @Html.C1().InputNumber("#theExpenses").Format("n2").Step(10)
    </tr>
</table>