Introduction
This tip will help the audience who might have/had some difficulty in creating a multi-header column in XamDataPresenter
or XamDataGrid
( Infragistics Controls).
Background
I had some difficulty in creating a multi-header column, so I thought it's worth sharing the idea which I used to overcome the problem. In my case, I was getting the data & header in the form of two XML string
s, which I had to parse and generate a data table which is then binded to the datagrid
in this case it's XamDataPresenter
.
But as we all know that a DataTable
can have only a single Column row, so I have made use of FieldLayoutInitializing
event of XamDataPresenter
in initializing the fields and generating the multi-header column.
The multi-header is achieved in Infragistics using the concept of Unbound Fields & Bounded Fields.
- Unbound Fields are not bound to a data source. The value shown in the unbound column is calculated in the code-behind.
- Bound Fields are those which are binded with the Data Table.
Using the Code
In this section, we will see step by step how I overcome the problem of multi-header column.
In my case, I was getting the data & header in the form of two XML string
s.
The header XML will have the data of the number of header rows that would be present in the DataGrid
(XamDataPresenter
).
Header XML string
will be parsed and stored in the list as shown below:
private IList<XmlRow> _headerRows = new List<XmlRow>();
public IList<XmlRow> headerRows
{
get
{
return _headerRows;
}
set
{
_headerRows = value;
}
}
XmlRow
class will have the details of all the header rows that will be present in the header rows,
public class XmlRow
{
private IList<XmlColumn> _columnList = new List<XmlColumn>();
public IList<XmlColumn> columnList
{
get
{
return _columnList;
}
set
{
_columnList = value;
}
}
public void addColumn(XmlColumn xmlColumn)
{
columnList.Add(xmlColumn);
}
}
XmlColumn
will have the values of the Attributes
present in the XML string
:
public class XmlColumn
{
private string _id = "";
public string id
{
get
{
return _id;
}
set
{
_id = value;
}
}
private string _value = "";
public string value
{
get
{
return _value;
}
set
{
_value = value;
}
}
private int _span = 1;
public int span
{
get
{
return _span;
}
set
{
_span = value;
}
}
private string _type = "";
public string type
{
get
{
return _type;
}
set
{
_type = value;
}
}
private string _format = "";
public string format
{
get
{
return _format;
}
set
{
_format = value;
}
}
private string _cellColor = "";
public string cellColor
{
get
{
return _cellColor;
}
set
{
_cellColor = value;
}
}
private string _fieldColor = "";
public string fieldColor
{
get
{
return _fieldColor;
}
set
{
_fieldColor = value;
}
}
}
Now the data table is generate from the last XML row in the header XML which will be used to create the columns of the Data Table which in turn will be binded to the XamDataPresenter
directly.
The below code shows how the columns of the data table is generated.
DataTable dataTable = new DataTable();
foreach (XmlColumn column in dataHeader.Last<XmlRow>().columnList)
{
string columnType= column.type;
switch (columnType.ToUpper())
{
case "STRING":
dataTable.Columns.Add(column.id, typeof(string));
break;
case "DATE":
dataTable.Columns.Add(column.id, typeof(DateTime));
break;
case "BOOL":
dataTable.Columns.Add(column.id, typeof(bool));
break;
case "DOUBLE":
dataTable.Columns.Add(column.id, typeof(double));
break;
case "PERCENTAGE":
dataTable.Columns.Add(column.id, typeof(double));
break;
case "DECIMAL":
dataTable.Columns.Add(column.id, typeof(decimal));
break;
case "NUMBER":
DataColumn columnValue = new DataColumn();
columnValue.DataType = typeof(double);
columnValue.AllowDBNull = true;
columnValue.ColumnName = column.id;
dataTable.Columns.Add(columnValue);
break;
case "INT":
dataTable.Columns.Add(column.id, typeof(Int32));
break;
}
}
After this, the data is added to the data table using the data XML.
Once the Data Table is ready, it is binded to the XamDataPresenter
, in the FieldLayoutInitializing
event of the XamDataPresenter
the unbounded Fields are generated in the code-behind as shown in the below code:
private void XamDataPresenter_FieldLayoutInitializing
(object sender, Infragistics.Windows.DataPresenter.Events.FieldLayoutInitializingEventArgs e)
{
try
{
e.FieldLayout.Settings.AutoGenerateFields = false;
e.FieldLayout.Settings.AutoArrangeCells = AutoArrangeCells.Never;
int rowCount = rpgvm.getHeaderRows().Count;
dummyPositions = new int[rowCount];
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
XmlRow row = rpgvm.getHeaderRows()[rowIndex];
int columnIndex = 0;
if (rowIndex != (rowCount - 1))
{
foreach (XmlColumn column in row.columnList)
{
UnboundField ubf = new UnboundField
{
Name = column.id,
Label = column.value,
Row = rowIndex,
Column = columnIndex,
ColumnSpan = column.span,
Width= FieldLength.Auto,
};
ubf.Settings.CellMaxHeight = 0.00;
e.FieldLayout.FieldSettings.LabelTextAlignment = TextAlignment.Center;
e.FieldLayout.FieldSettings.AllowGroupBy = true;
e.FieldLayout.Settings.RecordSelectorLocation = RecordSelectorLocation.None;
e.FieldLayout.Fields.Add(ubf);
if (column.span > 1)
{
columnIndex = columnIndex + column.span;
}
else
{
columnIndex++;
}
}
}
else
{
foreach (XmlColumn column in rpgvm.getHeaderRows().Last<XmlRow>().columnList)
{
Field fld = new Field
{
Name = column.id,
Label = column.value,
Row = rowIndex,
Column = columnIndex,
};
fld.Settings.AllowRecordFiltering = true;
fld.Settings.FilterLabelIconDropDownType =
FilterLabelIconDropDownType.MultiSelectExcelStyle;
e.FieldLayout.Settings.AllowFieldMoving = AllowFieldMoving.No;
e.FieldLayout.Settings.RecordSelectorLocation = RecordSelectorLocation.None;
e.FieldLayout.FieldSettings.AllowEdit = false;
e.FieldLayout.Settings.FilterUIType = FilterUIType.LabelIcons;
columnIndex++;
}
}
}
}
catch (Exception ex)
{
Logger.Error(ex, "XamDataPresenter_FieldLayoutInitializing");
}
}
Though this is a very small work, I sure hope this will help somebody. :)
Points of Interest
With the help of Unbound Field, we can play with the XamDataPresenter
in a much more flexible manner. Formatting of the fields can we done easily in the FieldLayoutInitializing
event as shown in the above example.