DataGrid and business objects

G

Guest

I would like to display/edit an ArrayList of objects in a DataGrid. Each row
in the datagrid displays a Machine.
Problem 1: Each of the objects (Machine) in the list has an ArrayList of
child objects (Part). How must the following example be rewritten so that it
doesn't produce this exception:
System.ArgumentException: The data grid table styles collection already
contains a table style with the same mapping name.
Problem 2: Each of the Machine objects has a reference to a Manufacturer
object, which contains the property Name. I think this is a common situation
when using a database and an Object-Relational mapping. Is it possible to
display the manufacturer name in the grid, so that 4 columns are displayed
(Model, ID, Price, Manufacturer name)?
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;

public class Machine{
private string model;
private string id;
private decimal price;
private Manufacturer man;

// Use an ArrayList to create a related collection.
private ArrayList parts = new ArrayList();

public string Model{
get{return model;}
set{model=value;}
}
public string Id{
get{return id;}
set{id = value;}
}
public ArrayList Parts{
get{return parts;}
set{parts = value;}
}

public decimal Price{
get{return price;}
set{price = value;}
}

public Manufacturer Man{
get{return man;}
set{man=value;}
}
}

public class Manufacturer{
private string name;
public string Name{
get{return name;}
set{name=value;}
}
}

public class Part{
private string partId;
public string PartId{
get{return partId;}
set{partId = value;}
}
}

public class DataGridSample:Form{
DataGrid myGrid;

static void Main(){
Application.Run(new DataGridSample());
}

public DataGridSample(){
InitializeComponent();
}

void InitializeComponent(){
this.ClientSize = new System.Drawing.Size(550, 450);
myGrid = new DataGrid();
myGrid.Location = new Point (10,10);
myGrid.Size = new Size(500, 400);
myGrid.CaptionText = "Microsoft .NET DataGrid";
this.Text = "C# Grid Example";
this.Controls.Add(myGrid);
BindToArray();
}

private void BindToArray(){
Manufacturer man1=new Manufacturer();
man1.Name="Man.1";
// Create an ArrayList of Machine objects (defined below).
ArrayList Machines=new ArrayList();
Machine tempMachine;

tempMachine= new Machine();
tempMachine.Model = "AAA";
tempMachine.Id= "A100";
tempMachine.Price= Convert.ToDecimal(3.80);
tempMachine.Man=man1;
Machines.Add(tempMachine);

// The first Machine includes an array of Part objects.
Part p1 = new Part();
p1.PartId= "PartX";
Part p2 = new Part();
p2.PartId= "PartY";

// Note that the Machines.Parts property returns an ArrayList.
// Add the parts to the ArrayList using the AddRange method.
tempMachine.Parts.AddRange (new Part[]{p1, p2});;

tempMachine= new Machine();
tempMachine.Model = "BBB";
tempMachine.Id= "B100";
tempMachine.Price=Convert.ToDecimal(1.52);
Machines.Add(tempMachine);

tempMachine= new Machine();
tempMachine.Id= "CCC";
tempMachine.Model = "B100";
tempMachine.Price= Convert.ToDecimal(2.14);
Machines.Add(tempMachine);

myGrid.SetDataBinding(Machines, "");
CreateTableStyle();
}

private void CreateTableStyle(){
// Creates two DataGridTableStyle objects, one for the Machine
// array, and one for the Parts ArrayList.

DataGridTableStyle MachineTable = new DataGridTableStyle();
MachineTable.MappingName="ArrayList";

// Sets the AlternatingBackColor so you can see the difference.
MachineTable.AlternatingBackColor= System.Drawing.Color.LightBlue;

// Creates three column styles.
DataGridTextBoxColumn modelColumn = new DataGridTextBoxColumn();
modelColumn.MappingName= "Model";
modelColumn.HeaderText= "Model";

DataGridTextBoxColumn IdColumn = new DataGridTextBoxColumn();
IdColumn.MappingName= "Id";
IdColumn.HeaderText= "Id";

DataGridTextBoxColumn priceColumn = new DataGridTextBoxColumn();
priceColumn.MappingName= "Price";
priceColumn.HeaderText= "Price";
priceColumn.Format = "c";

DataGridTextBoxColumn manColumn = new DataGridTextBoxColumn();
manColumn.MappingName= "Man.Name";
manColumn.HeaderText= "Manuf.";

// Adds the column styles to the grid table style.
MachineTable.GridColumnStyles.Add(modelColumn);
MachineTable.GridColumnStyles.Add(IdColumn);
MachineTable.GridColumnStyles.Add(priceColumn);
MachineTable.GridColumnStyles.Add(manColumn);

// Add the table style to the collection, but clear the collection first.
myGrid.TableStyles.Clear();
myGrid.TableStyles.Add(MachineTable);

// Create another table style, one for the related data.
DataGridTableStyle partsTable = new DataGridTableStyle();
partsTable.MappingName="ArrayList"; //IF YOU UNCOMMENT THIS LINE, AT LEAST
THE MAIN ARRAYLIST IS DISPLAYED
DataGridTextBoxColumn partIdColumn = new DataGridTextBoxColumn();
partIdColumn.MappingName= "PartID";
partIdColumn.HeaderText = "Part ID";
partsTable.GridColumnStyles.Add(partIdColumn);

myGrid.TableStyles.Add(partsTable);
}

}
 
J

Jim Wooley

I would like to display/edit an ArrayList of objects in a DataGrid.
Each row
in the datagrid displays a Machine.
Problem 1: Each of the objects (Machine) in the list has an ArrayList
of
child objects (Part). How must the following example be rewritten so
that it
doesn't produce this exception:
System.ArgumentException: The data grid table styles collection
already
contains a table style with the same mapping name.

The mapping name tells the datagrid how to handle binding to a certain type.
You are trying to tell it to use two bindings to the ArrayList type which
confuses it. As a resolution, you can implement strongly typed collection
classes inheriting from CollectionBase for Machines and Parts. Then assign
the mapping name to the class name as appropriate. It appears 2003 and 2005
handle the MappingName designations differently.

Problem 2: Each of the Machine objects has a reference to a
Manufacturer
object, which contains the property Name. I think this is a common
situation
when using a database and an Object-Relational mapping. Is it possible
to
display the manufacturer name in the grid, so that 4 columns are
displayed
(Model, ID, Price, Manufacturer name)?

I don't think it is possible to bind to a child sub-property. In the past,
I have had to expose the ManufacturerName as a property in my Machine entity
for binding purposes. Alternatively, you can subclass the datagrid and include
a combobox column which will handle that mapping for you. This is significantly
more difficult in 2003 than 2005. The first option is easier.

Jim Wooley
http://devauthority.com/blogs/jwooley/default.aspx
 
G

Guest

Thanks for your answer.
I am not yet using .net for work, I just wanted to explore it, so your
answer is sufficient. Just let me explain the goal:
-the core of the system should be the business classes, which contain
references to other business classes.
-the user should be able to select the columns displayed in the grids. It
should be possible to choose from all the fields of the class in use, as well
as from the fields of the referenced objects and so on. For choosing the
columns, the solution would be a TreeView (which is built using reflection on
the business classes). The result of the selection could be a list of
strings, as the following:
OrderNumber
ShipmentDate
Customer.Name
Customer.Address.State.Description
Customer.Category.Description
this would eventually be saved in some form, along with other settings
(filters, records ordering...)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top