Generating Table in Telerik Report Viewer Programmatically - c#

I am trying to generate a telerik report table dynamically. Actually, after lots of efforts besides surfing the web I have come to the following code which works fine but not presenting the desired output. Here is the code:
private void table1_ItemDataBinding(object sender, EventArgs e)
{
// Get data and bind it to the table
var processingTable = (sender as Telerik.Reporting.Processing.Table);
var data = GenerateTable(DomainClass.GetCurrentAsset());
if (processingTable != null) processingTable.DataSource = data;
// Better clear table before binding
table1.ColumnGroups.Clear();
table1.Body.Columns.Clear();
table1.Body.Rows.Clear();
HtmlTextBox txtGroup;
HtmlTextBox txtTable;
//int rowIndex = 0;
for (int i = 0; i <= data.Columns.Count - 1; i++)
{
var tableGroupColumn = new TableGroup();
table1.ColumnGroups.Add(item: tableGroupColumn);
txtGroup = new HtmlTextBox
{
Size = new SizeU(Unit.Inch(2.1), Unit.Inch(0.3)),
Value = data.Columns[i].ColumnName,
Style =
{
BorderStyle = { Default = BorderType.Solid },
BorderColor = { Default = Color.Black }
},
};
tableGroupColumn.ReportItem = txtGroup;
txtTable = new HtmlTextBox()
{
Size = new SizeU(Unit.Inch(2.2), Unit.Inch(0.3)),
Value = "=Fields." + data.Columns[i].ColumnName,
//Value = data.Rows[rowIndex][i].ToString(),
Style =
{
BorderStyle = { Default = BorderType.Solid },
BorderColor = { Default = Color.Black }
}
};
table1.Body.SetCellContent(0, columnIndex: i, item: txtTable);
//rowIndex++;
table1.Items.AddRange(items: new ReportItemBase[] { txtTable, txtGroup });
}
}
Here is a picture of DataTable which contains the table data:
Finally, the current out put which is of course not what needed:
So the problem is; The Account_Price column does not display the Prices, though retrieved from the data store and can be seen in the data table picture above.
I have traced line by line of the code and could find out the prices as tracing the code. But I have no idea why they are not shown in the browser.
Hope any one could help me,
Thank you very much

Apparently, this is a newer issue with the later Telerik reporting.
I found the answer in the Telerik forums here:
http://www.telerik.com/community/forums/reporting/telerik-reporting/incorrect-dynamic-table-columns.aspx
Basically, you need to assign a unique name the TableGroup column:
TableGroup tableGroupColumn = new TableGroup();
//add this :
tableGroupColumn.Name = i.ToString();

Related

How to get all cells data in a selected row using DataGridView in WindowsForms?

I have a DataGridView showing some data from my database and when I double click any row in the datagridview I get its contents in a new window.
I have this:
private void ListaProductos_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
var content = ListaProductos.Rows[e.RowIndex].Cells["Name"].Value.ToString();
var abrirNuevoProducto = new modificar_producto(content ); // I want to pass data to another form
abrirNuevoProducto.Show(); // loads the new form with data for modification
}
This worked for me but... it would be tired and tedious to make this one by one like this:
var content = ListaProductos.Rows[e.RowIndex].Cells["Name"].Value.ToString();
var content2 = ListaProductos.Rows[e.RowIndex].Cells["Age"].Value.ToString();
var conten3 = ListaProductos.Rows[e.RowIndex].Cells["Surname"].Value.ToString();
var content4 = ListaProductos.Rows[e.RowIndex].Cells["Address"].Value.ToString();
... and 150 more columns
var abrirNuevoProducto = new modificar_producto(content, content2, content3, content4 ... and so on); // I want to pass data to another form
abrirNuevoProducto.Show(); // loads the new form with data for modification
I would do this using a List but..., I am wondering if there is an easy way to do this because the way I am trying is very tired and poor. Or Should I use a list instead?
I need to pass data to another form for modification operations.
If you already have a class defined for this table you can use code as below
var products = new List<Products>(grid.SelectedRows.Count);
for(int index = 0; index < grid.SelectedRows.Count; index++)
{
var selectedRow = grid.SelectedRows[index];
var product = (Products)selectedRow.DataBoundItem;
products.Add(prduct);
}
or if you don't have a class definition you can use dynamic keyword
var products = new List<dynamic>(grid.SelectedRows.Count);
for(int index = 0; index < grid.SelectedRows.Count; index++)
{
var selectedRow = grid.SelectedRows[index];
var product = (dynamic)selectedRow.DataBoundItem;
products.Add(prduct);
}

Issue with moving items between listboxes

I have 2 listboxes in my Windows C# WinForms application. I have written the code to move items between my 2 listboxes. I can select any/multiple items and move them between the boxes. However if I select the bottom item in the listbox and move it to the other listbox, then the content in the table it was moved from shows up incorrectly. Instead of showing the actual contents, it's showing:- ProgramName__.objectname for each entry that was above the entry i moved! This only happens with the last item in the listbox. If i select the entry that shows up wrong and move it to the other listbox, the correct information shows up.
This appears to me to be a bug, but I'm not sure. I can move any other item in the listbox and both listboxes show up properly.
public class customers
{
public int id { get; set; }
public string name {get; set; }
}
this.table1Box.DataSource = this.customersBindingSource;
this.table1Box.DisplayMember = "name";
this.table1Box.Name = "Table1Name";
this.table1Box.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
this.table1Box.Sorted = true;
this.table1Box.TabIndex = 13;
this.table1Box.ValueMember = "id";
this.table2Box.DataSource = this.customersBindingSource;
this.table2Box.DisplayMember = "name";
this.table2Box.Name = "Table2Name";
this.table2Box.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
this.table2Box.Sorted = true;
this.table2Box.TabIndex = 14;
this.table2Box.ValueMember = "id";
// Click method for moving table 1 -> table 2
private void table1ToTable2Button_Click(object sender, EventArgs e)
{
foreach (int i in this.table1Box.SelectedIndices)
{
selectedCustomer = (customers)this.table1Box.Items[i];
table2List.Add(selectedCustomer);
table1List.Remove(selectedCustomer);
}
this.table1Box.DataSource = this.emptyList;
this.table1Box.DataSource = this.table1List;
this.table1Box.Update();
this.table2Box.DataSource = this.emptyList;
this.table2Box.DataSource = this.table2List;
this.table2Box.Update();
}
![Picture at Start of program] http://www.mclenaghan.com/Pic1.jpg
![Picture after moving last item] http://www.mclenaghan.com/Pic2.jpg
![Picture moving item 2] http://www.mclenaghan.com/Pic3.jpg
Make sure you are binding to BindingList<customers>.
You don't need to set the DataSource to an empty list and then set to the actual list again and then call ListBox.Update(). This seems to be working but it also means you are doing wrong in your binding.
One more thing- Do not edit the designer-generated code by hand, use the Properties Pane. I find even if I change the code sequence in the InitializeComponent method, the listbox can display incorrectly.
BindingList<customers> table1List;
BindingList<customers> table2List;
public FormWith2Listboxes()
{
InitializeComponent();
table1List = new BindingList<customers>();
table1List.Add(new customers() { id = 1, name = "name1" });
table1List.Add(new customers() { id = 2, name = "name2" });
table1List.Add(new customers() { id = 3, name = "name3" });
table2List = new BindingList<customers>();
table2List.Add(new customers() { id = 4, name = "name4" });
this.table1Box.DataSource = this.table1List;
this.table2Box.DataSource = this.table2List;
}
private void table1ToTable2Button_Click(object sender, EventArgs e)
{
foreach (int i in this.table1Box.SelectedIndices)
{
var selectedCustomer = (customers)this.table1Box.Items[i];
table2List.Add(selectedCustomer);
table1List.Remove(selectedCustomer);
}
}

How to Add Value to a DataGrid that has a ComboBox Column

What i'm trying to do is collect the data base on the referrence of DocNumber and put it in a DataGrid the record can sometimes be single to many. dependes on how it takes by retrieving. here is my function code below:
internal void SelectDetailsRecord(string p)
{
SFCDataContext SFC = new SFCDataContext();
try
{
var DetailsRec = SFC.Sales_OrderFormDetails.Where(w => w.OrderDocNum == p)
.Select(t => new {
Ord = t.OrderDocNum,
Line = t.LineNumber,
Vcode = t.VariantCode,
Vdesc = t.VariantDesc,
Icode = t.Itemnmbr,
Idesc = t.ItemDesc,
Qty = t.Quantity,
UofM = t.UofM,
Kgs = t.KgsPerBag,
Post = t.Posted
});
int count = 0;
foreach (var r in DetailsRec)
{
decimal TotalKgs = Convert.ToDecimal(r.Qty) * Convert.ToDecimal(r.Kgs);
string[] row =
{
r.Qty.ToString(),
r.Icode,
r.Idesc,
r.UofM,
r.Vcode,
r.Vdesc,
r.Kgs.ToString(),
TotalKgs.ToString(),
r.Line.ToString()
};
//DataGridView1.Rows.Add(row); <-- Tried this one but returns me an error statement.
DataGridView1.Rows[count].Cells[0].Value = row[0];
DataGridView1.Rows[count].Cells[1].Value = row[1]; <-- this Part here is the combo box column
DataGridView1.Rows[count].Cells[2].Value = row[2];
DataGridView1.Rows[count].Cells[3].Value = row[3];
DataGridView1.Rows[count].Cells[4].Value = row[4];
DataGridView1.Rows[count].Cells[5].Value = row[5];
DataGridView1.Rows[count].Cells[6].Value = row[6];
DataGridView1.Rows[count].Cells[7].Value = row[7];
DataGridView1.Rows[count].Cells[8].Value = row[8];
count++;
}
}
catch (Exception) { }
SFC.Connection.Close();
}
Is there a way I could put the value of the record into the datagrid combobox like putting a value in a combobox like this: " ComboBox.Text = Value; " please help if anytone has an idea.
In order to populate a ComboBox with a List of items, you need to set its DataSource.
myComboBox.DataSource = myList;
See the relevant MSDN page: http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox%28v=vs.110%29.aspx
This code must work in this problem:
DataGridView1.Rows[count].Cells[1].Value = Convert.ToString(row[1]);
You have to convert object value into string value to set value in GridComboBox. Also make sure that value of row[1] present in collection GridComboBox

how to add items to TreeViewAdv in multi-column mode with winforms

I was playing around with this control called TreeViewAdv. I've already added the control and added couple of columns trying to see how it works. but till now when I add items to the control all I get is empty nodes. the example provided with the control is not clear at all and it just gave me headaches when I try to figure out how the data is being added to it. anyway here is what I've done so far and I hope that someone can guide me to the right direction.
TreeModel _model = new TreeModel();
treeViewAdv1.Model = _model;
treeViewAdv1.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new Node("root" + i);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new MyNode("child" + n);
parentNode.Nodes.Add(childNode);
}
}
treeViewAdv1.EndUpdate();
anyway, all I'm getting is empty nodes and I really can't figure out how to add data to the other columns... any help would be appreciated...
Obviously this questions is old, but I was unable to find any answers to this question, so I figured I would try to save someone some future frustration.
To get multiple columns to display, first change the UseColumns property to true.
Then add desired columms to the Columns collection property.
Next using the NodeControls collection property to create a list of the types of data that will be shown, and how they should be formatted (Checkbox, TextBox, etc). Make sure to set 1) the DataPropertyName (will be used later), 2) the ParentColumn (to show which column in the treeView is supposed to show the data.
Finally, create a new class inheriting from the Node class, and add a public property with the same name as each NodeControl. Then when adding Nodes, use your new class with the correct value.
private class ColumnNode: Node
{
public string NodeControl1=""; // This sould make the DataPropertyName specified in the Node Collection.
public string NodeControl2 = "";
public string NodeControl3 = "";
public ColumnNode(string nodeControl1, string nodeControl2, int nodeControl3)
{
NodeControl1 = nodeControl1;
NodeControl2 = nodeControl2;
NodeControl3 = nodeControl3.ToString();
}
}
Then when adding the
TreeModel _model = new TreeModel();
_treeViewAdv.Model = _model;
_treeViewAdv.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new ColumnNode("root" + i, "",0);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new ColumnNode("child" + n,"Further Information",1);
parentNode.Nodes.Add(childNode);
}
}
_treeViewAdv.EndUpdate();
For reference, the designer code for the treeViewAdv in this case would look like this:
private Aga.Controls.Tree.TreeViewAdv _treeViewAdv;
private Aga.Controls.Tree.TreeColumn Column1;
private Aga.Controls.Tree.TreeColumn Column2;
private Aga.Controls.Tree.TreeColumn Column3;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl1;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl2;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl3;
private InitializeComponent()
{
// Left out all other initialization, since this was long enough already.
this.treeViewAdvPrint = new Aga.Controls.Tree.TreeViewAdv();
this.Column1 = new Aga.Controls.Tree.TreeColumn();
this.Column2 = new Aga.Controls.Tree.TreeColumn();
this.Column3 = new Aga.Controls.Tree.TreeColumn();
this.NodeControl1 = new Aga.Controls.Tree.NodeControls.NodeTextBox();
this.NodeControl2 = new Aga.Controls.Tree.NodeControls.NodeTextBox();
this.NodeControl3= new Aga.Controls.Tree.NodeControls.NodeTextBox();
//
// _treeViewAdv
//
this._treeViewAdv.BackColor = System.Drawing.SystemColors.Window;
this._treeViewAdv.Columns.Add(this.Column1);
this._treeViewAdv.Columns.Add(this.Column2);
this._treeViewAdv.Columns.Add(this.Column3);
this._treeViewAdv.DefaultToolTipProvider = null;
this._treeViewAdv.DragDropMarkColor = System.Drawing.Color.Black;
this._treeViewAdv.GridLineStyle = ((Aga.Controls.Tree.GridLineStyle)((Aga.Controls.Tree.GridLineStyle.Horizontal | Aga.Controls.Tree.GridLineStyle.Vertical)));
this._treeViewAdv.LineColor = System.Drawing.SystemColors.ControlDark;
this._treeViewAdv.Location = new System.Drawing.Point(12, 12);
this._treeViewAdv.Model = null;
this._treeViewAdv.Name = "_treeViewAdv";
this._treeViewAdv.NodeControls.Add(NodeControl1);
this._treeViewAdv.NodeControls.Add(NodeControl2);
this._treeViewAdv.NodeControls.Add(NodeControl3);
this._treeViewAdv.SelectedNode = null;
this._treeViewAdv.Size = new System.Drawing.Size(443, 356);
this._treeViewAdv.TabIndex = 6;
this._treeViewAdv.Text = "_treeViewAdv";
this._treeViewAdv.UseColumns = true;
//
// Column1
//
this.Column1.Header = "Column 1";
this.Column1.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column1.TooltipText = null;
this.Column1.Width = 290;
//
// Column3
//
this.Column3.Header = "Column 3";
this.Column3.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.Column3.TooltipText = null;
//
// Column2
//
this.Column2.Header = "Column 2";
this.Column2.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.Column2.TooltipText = null;
this.Column2.Width = 91;
//
// NodeControl1
//
this.NodeControl1.DataPropertyName = "NodeControl1";
this.NodeControl1.IncrementalSearchEnabled = true;
this.NodeControl1.LeftMargin = 3;
this.NodeControl1.ParentColumn = this.Column1;
//
// NodeControl2
//
this.NodeControl2.DataPropertyName = "NodeControl2";
this.NodeControl2.IncrementalSearchEnabled = true;
this.NodeControl2.LeftMargin = 3;
this.NodeControl2.ParentColumn = this.Column2;
//
// NodeControl3
//
this.NodeControl3.DataPropertyName = "NodeControl3";
this.NodeControl3.IncrementalSearchEnabled = true;
this.NodeControl3.LeftMargin = 3;
this.NodeControl3.ParentColumn = this.Column3;
}
It seems as though the price of entry for using this fantastic control is hours, and hours, of head scratching frustration.
This is what you need to do:
private void Form1_Load(object sender, EventArgs e)
{
TreeModel _model = new TreeModel();
treeViewAdv1.Model = _model;
treeViewAdv1.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new Node("root" + i);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new Node("child" + n);
parentNode.Nodes.Add(childNode);
}
}
NodeTextBox ntb = new NodeTextBox();
ntb.DataPropertyName = "Text";
this.treeViewAdv1.NodeControls.Add(ntb);
treeViewAdv1.EndUpdate();
}
Just in case you're still struggling with the issue, or anyone else is having the same trouble: the solution to empty nodes is to assign a view component to tree.
TreeViewAdv uses MVC, and it requires that you assign a view, though this is not obvious from the example project. NodeTextBox class under NodeControls folder in the source of the TreeViewAdv is one of the viewers you can use. You need to add it to your form and connect it to tree control through its DataPropertyName attribute like this:
this._tBox.DataPropertyName = "Text";
where _tBox is the NodeTextBox instance. Needless to say, I've just lost hours figuring this out. Hope it helps someone else.
You need to instantiate your columns first, then attach them to the TreeView. After all add new cells in all columns at same cell index.
Hope to help

Set columns width in a datagrid using Compact Framework

I'm trying to set the width of the columns in my datagrid. I use Compact Framework 2.0 and C#
I tried this but it gives me an "out of bonds" error message:
foreach (DataGridColumnStyle vColumnStyle in dataGrid1.TableStyles[0].GridColumnStyles)
{
vColumnStyle.Width = 100;
}
Here is the code for filling my datagrid with the datatable (only fails when I try to set the columns width):
void FillData()
{
// 1
// Open connection
string conString = "Data Source=\\Program Files\\smartdeviceproject2\\repartocrack.sdf";
using (SqlCeConnection c = new SqlCeConnection(conString))
{
c.Open();
// 2
// Create new DataAdapter
using (SqlCeDataAdapter a = new SqlCeDataAdapter(
"SELECT codbultocomp, nombre, estado FROM envios INNER JOIN tiendas ON envios.codigodestino = tiendas.codigodestino", c))
{
// 3
// Use DataAdapter to fill DataTable
DataTable t = new DataTable();
a.Fill(t);
// 4
// Render data onto the screen
foreach (DataGridColumnStyle vColumnStyle in dataGrid1.TableStyles[0].GridColumnStyles)
{
vColumnStyle.Width = 100;
}
dataGrid1.DataSource = t;
}
}
}
Try this code:
dataGrid1.TableStyles.Clear();
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = t.TableName;
foreach (DataColumn item in t.Columns)
{
DataGridTextBoxColumn tbcName = new DataGridTextBoxColumn();
tbcName.Width = 100;
tbcName.MappingName = item.ColumnName;
tbcName.HeaderText = item.ColumnName;
tableStyle.GridColumnStyles.Add(tbcName);
}
dataGrid1.TableStyles.Add(tableStyle);
DataGrid is now obsolete but I encountered the same problem when changing some legacy code so I'll post my solution.
The problem is that DataGrid has a private field called myGridTable that is holding the current DataGridTableStyle. A current DataGridTableStyle exists even if the TableStyles collection is empty, in which case it points to a default DataGridTableStyle which is also private/internal.
Since DataGrid is obsolete anyway and won't be changed, I decided to just use Reflection to access those private fields. They should have been public anyway and making them private was a bad design decision IMO.
The advantage of working with the current styles directly is you don't need to destroy and recreate the table styles just to change the widths, and it works without unexpected behavior every time.
I created a few extension methods to do it:
static class DataGridColumnWidthExtensions
{
public static DataGridTableStyle GetCurrentTableStyle(this DataGrid grid)
{
FieldInfo[] fields = grid.GetType().GetFields(
BindingFlags.NonPublic |
BindingFlags.Instance);
return (DataGridTableStyle)fields.First(item => item.Name == "myGridTable").GetValue(grid);
}
public static IList<int> GetColumnWidths(this DataGrid grid)
{
var styles = grid.GetCurrentTableStyle().GridColumnStyles;
var widths = new int[styles.Count];
for (int ii = 0; ii < widths.Length; ii++)
{
widths[ii] = styles[ii].Width;
}
return widths;
}
public static void SetColumnWidths(this DataGrid grid, IList<int> widths)
{
var styles = grid.GetCurrentTableStyle().GridColumnStyles;
for (int ii = 0; ii < widths.Count; ii++)
{
styles[ii].Width = widths[ii];
}
}
}
I spent a better part of 2 days looking for the answer above. Thanks for the great solutions provided. Here is some vb code, with a customization of column widths by column:
' trgAppt is defined as system.windows.forms.datagrid
trgAppt.TableStyles.Clear()
Dim tableStyle As DataGridTableStyle
tableStyle = New DataGridTableStyle
tableStyle.MappingName = dtAppt.TableName
For Each myItem As DataColumn In dtAppt.Columns
Dim tbcName As DataGridTextBoxColumn = New DataGridTextBoxColumn
Select Case myItem.ColumnName.ToString.ToUpper
Case "STOP"
tbcName.Width = 35
Case "ORDER"
tbcName.Width = 45
Case "CUSTOMER"
tbcName.Width = 70
Case "QTY"
tbcName.Width = 35
End Select
tbcName.MappingName = myItem.ColumnName
tbcName.HeaderText = myItem.ColumnName
tableStyle.GridColumnStyles.Add(tbcName)
tbcName = Nothing
Next
trgAppt.TableStyles.Add(tableStyle)
trgAppt.DataSource = dtAppt

Categories