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
4/9/2025
7,501.57
3,187.65
6
US
Cars
4/15/2025
3,103.77
692.74
12
US
Stereos
4/21/2025
8,475.88
2,716.66
18
US
Watches
4/27/2025
4,205.98
3,094.03
24
US
Computers
5/3/2025
2,541.05
3,228.92
30
US
Phones
5/9/2025
4,162.29
2,213.21
36
US
Cars
5/15/2025
6,243.58
3,180.18
42
US
Stereos
5/21/2025
141.10
3,345.73
48
US
Watches
5/27/2025
8,830.42
2,644.27

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
4/9/2025
7,501.57
3,187.65
1
Germany
Cars
4/10/2025
5,926.31
2,002.98
2
UK
Stereos
4/11/2025
6,401.35
2,111.90
3
Japan
Watches
4/12/2025
1,309.07
486.69
4
Italy
Computers
4/13/2025
8,821.29
253.88
5
Greece
Phones
4/14/2025
4,488.25
4,127.60
6
US
Cars
4/15/2025
3,103.77
692.74
7
Germany
Stereos
4/16/2025
5,896.96
2,155.29
8
UK
Watches
4/17/2025
8,766.62
4,988.40
9
Japan
Computers
4/18/2025
8,431.34
479.97
10
Italy
Phones
4/19/2025
5,883.68
2,385.96
11
Greece
Cars
4/20/2025
6,688.09
4,045.91
12
US
Stereos
4/21/2025
8,475.88
2,716.66
13
Germany
Watches
4/22/2025
9,650.10
2,293.86
14
UK
Computers
4/23/2025
8,494.16
3,808.82
15
Japan
Phones
4/24/2025
1,513.49
1,620.91
16
Italy
Cars
4/25/2025
9,520.26
3,262.66
17
Greece
Stereos
4/26/2025
4,247.85
4,780.45
18
US
Watches
4/27/2025
4,205.98
3,094.03
19
Germany
Computers
4/28/2025
6,852.99
1,423.99
20
UK
Phones
4/29/2025
4,843.62
2,148.76
21
Japan
Cars
4/30/2025
829.52
2,892.55
22
Italy
Stereos
5/1/2025
1,853.87
2,249.89
23
Greece
Watches
5/2/2025
8,973.82
2,791.31
24
US
Computers
5/3/2025
2,541.05
3,228.92
25
Germany
Phones
5/4/2025
6,585.86
3,293.34
26
UK
Cars
5/5/2025
783.78
2,987.03
27
Japan
Stereos
5/6/2025
5,307.68
3,093.61
28
Italy
Watches
5/7/2025
8,587.05
4,173.90
29
Greece
Computers
5/8/2025
9,124.37
428.37
30
US
Phones
5/9/2025
4,162.29
2,213.21
31
Germany
Cars
5/10/2025
526.44
3,873.69
32
UK
Stereos
5/11/2025
8,981.93
4,757.75
33
Japan
Watches
5/12/2025
6,699.16
1,199.08
34
Italy
Computers
5/13/2025
8,512.92
2,278.40
35
Greece
Phones
5/14/2025
3,893.73
4,237.94
36
US
Cars
5/15/2025
6,243.58
3,180.18
37
Germany
Stereos
5/16/2025
6,706.33
2,546.67
38
UK
Watches
5/17/2025
2,302.43
4,640.50
39
Japan
Computers
5/18/2025
6,693.05
4,855.83
40
Italy
Phones
5/19/2025
1,492.70
2,149.70
41
Greece
Cars
5/20/2025
4,529.20
3,384.05
42
US
Stereos
5/21/2025
141.10
3,345.73
43
Germany
Watches
5/22/2025
1,632.58
3,661.80
44
UK
Computers
5/23/2025
4,767.27
1,723.66
45
Japan
Phones
5/24/2025
3,859.91
1,554.55
46
Italy
Cars
5/25/2025
3,772.14
1,479.77
47
Greece
Stereos
5/26/2025
6,966.60
1,312.70
48
US
Watches
5/27/2025
8,830.42
2,644.27
49
Germany
Computers
5/28/2025
4,065.13
2,039.69

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>