| | | Display data & modify layout | |
Hi, I havea requirement where in I can display the data in a tabular fashion: There should be capability to drag and drop the rows as well as link the cells with kind of arrows. I am attaching a screen shot of the layout that's expected. We have the EXE for this tool developed but don't have the code. It would be nice if someone could tell me the way forward: The coloring is not required but check the linking between the cells . I have the source data to be read from excel file. One should have the capability to drag the rows up or down as needed. The row currently shown in gray highlight & blue row 1st column has been selected for dragging. Any help would be appreciated. Hope this helps !! Please close the thread once answered Sudeep
My Blog | | Sudeep Raj Tuesday, September 29, 2009 11:00 PM | Anyone with any ideas? Hope this helps !! Please close the thread once answered Sudeep
My Blog | | Sudeep Raj Wednesday, September 30, 2009 11:20 AM | Hi Sudeep,
We need to create a new custom control to show the grid. The headers can be some labels in one column. The cells need to be drawn by ourselves: draw a rectangle with some color, draw borders and then draw a text.
The lines can also be drawn. The lines stand for two kind of cell relations: 1. Row relation: one cell is related to another cell in the same row. 2. Column relation: one cell is related to another cell in the same column. We can figure out what lines need to be drawn in one relation between two cells.
The code snippet below shows the detail implementation: The control:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MyForm.CustomCtrl
{
//Grid control.
public partial class GraphGrid : Control
{
public GraphGrid()
{
this.BackColor = Color.White;
_rowHeaders = new RowHeaders(this);
_columns = new List<GraphGridColumn>();
_rows = new List<GraphGridRow>();
//No row is selected in the beginning.
this.CurrentRowIndex = -1;
InitializeComponent();
}
//row height
public int RowHeight
{
get { return _rowHeight; }
set { _rowHeight = value; }
}
//width of the square column which includes some colored square with a number.
public int SquareColumnWidth
{
get { return _squareColumnWidth; }
set { _squareColumnWidth = value; }
}
//width of the head column which inlcudes the head label.
public int HeadColumnWidth
{
get { return _headColumnWidth; }
set { _headColumnWidth = value; }
}
//width of colored square cell
public int GraphCellWidth
{
get { return _graphCellWidth; }
set { _graphCellWidth = value; }
}
//height of colored square cell
public int GraphCellHeight
{
get { return _graphCellHeight; }
set { _graphCellHeight = value; }
}
//width of the head label
public int HeadLabelWidth
{
get { return _headLabelWidth; }
set { _headLabelWidth = value; }
}
//height of the head label
public int HeadLabelHeight
{
get { return _headLabelHeight; }
set { _headLabelHeight = value; }
}
//row headers
public RowHeaders RowHeaders
{
get { return _rowHeaders; }
}
//rows include empty row
public List<GraphGridRow> Rows
{
get { return _rows; }
}
//columns
public List<GraphGridColumn> Columns
{
get { return _columns; }
}
//index of the selected row
public int CurrentRowIndex { set; get; }
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
if (this.CurrentRowIndex != -1)
{
//Paint the selected row background.
Rectangle rect = new Rectangle();
rect.X = 0;
rect.Y = CurrentRowIndex * _rowHeight;
rect.Width = this.ClientRectangle.Width;
rect.Height = _rowHeight;
pe.Graphics.FillRectangle(Brushes.LightCyan, rect);
}
//paint the colored square cells
for (int rowIndex = 0; rowIndex < _rows.Count; rowIndex++)
{
GraphGridRow row = _rows[rowIndex];
if (row.IsEmpty == false)
{
for (int colIndex = 0; colIndex < _columns.Count; colIndex++)
{
if (this.Rows[rowIndex].Cells.ContainsKey(colIndex))
this.DrawCell(rowIndex, colIndex, pe);
}
}
}
//Draw horizontal lines those connect two cells in the same row.
foreach(GraphGridRow row in _rows)
{
if (row.IsEmpty == false)
{
foreach (int key in row.Relations.Keys)
{
this.DrawHorizontalLine(key, row.Relations[key], row.Index, pe);
}
}
}
//Draw vertical lines those connect two cells in the same column.
foreach (GraphGridColumn col in _columns)
{
foreach (int key in col.Relations.Keys)
{
this.DrawVerticalLine(key, col.Relations[key], col.Index, pe);
}
}
}
//The method to draw square number cells.
private void DrawCell(int rowIndex, int colIndex, PaintEventArgs pe)
{
GraphGridCell cell = this.Rows[rowIndex].Cells[colIndex];
Point loc = new Point();
loc.X = _headColumnWidth + colIndex * _squareColumnWidth + (_squareColumnWidth - _graphCellWidth) / 2;
loc.Y = rowIndex * _rowHeight + (_rowHeight - _graphCellHeight) / 2;
Size size = new Size(_graphCellWidth, _graphCellHeight);
Rectangle rect = new Rectangle(loc, size);
using (Brush b = new SolidBrush(cell.Color))
{
pe.Graphics.FillRectangle(b, rect);
}
pe.Graphics.DrawRectangle(Pens.Black, rect);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
pe.Graphics.DrawString(cell.Value, this.Font, Brushes.Black, rect, format);
}
//The method to draw lines those connect two cells in the same row.
private void DrawHorizontalLine(int leftColIndex, int rightColIndex, int rowIndex, PaintEventArgs pe)
{
if (leftColIndex > rightColIndex)
{
int tem = leftColIndex;
leftColIndex = rightColIndex;
rightColIndex = tem;
}
int xLeft = _headColumnWidth + leftColIndex * _squareColumnWidth + (_squareColumnWidth) / 2;
int xRight = _headColumnWidth + rightColIndex * _squareColumnWidth + (_squareColumnWidth) / 2;
int yBottom = rowIndex * _rowHeight + (_rowHeight - _graphCellHeight) / 2;
int yTop = yBottom - HORIZONTAL_LINE_HEIGHT;
Point p1 = new Point(xLeft, yBottom);
Point p2 = new Point(xLeft, yTop);
Point p3 = new Point(xRight, yTop);
Point p4 = new Point(xRight, yBottom);
pe.Graphics.DrawLine(Pens.Black,p1, p2);
pe.Graphics.DrawLine(Pens.Black, p2, p3);
pe.Graphics.DrawLine(Pens.Black, p3, p4);
}
//The method to draw lines those connect two cells in the same column.
private void DrawVerticalLine(int topRowIndex, int bottomRowIndex, int colIndex, PaintEventArgs pe)
{
if (topRowIndex > bottomRowIndex)
{
int tem = topRowIndex;
topRowIndex = bottomRowIndex;
bottomRowIndex = tem;
}
int x = _headColumnWidth + colIndex * _squareColumnWidth + (_squareColumnWidth) / 2;
int yBottom = bottomRowIndex * _rowHeight + (_rowHeight - _graphCellHeight) / 2;
int yTop = topRowIndex * _rowHeight + (_rowHeight - _graphCellHeight) / 2 + _graphCellHeight;
Point p1 = new Point(x, yTop);
Point p2 = new Point(x, yBottom);
pe.Graphics.DrawLine(Pens.Black, p1, p2);
}
private int _rowHeight = 40;
private int _squareColumnWidth = 40;
private int _headColumnWidth = 110;
private int _graphCellWidth = 30;
private int _graphCellHeight = 30;
private int _headLabelWidth = 100;
private int _headLabelHeight = 30;
private const int HORIZONTAL_LINE_HEIGHT = 5;
private List<GraphGridRow> _rows = null;
private List<GraphGridColumn> _columns = null;
private RowHeaders _rowHeaders = null;
}
public class RowHeaders
{
public RowHeaders(GraphGrid grid)
{
_grid = grid;
}
public Label this[int rowIndex]
{
get { return _rowheadLabels[rowIndex];}
}
//Insert one header label.
public void SetLabel(int rowIndex, string text)
{
Label label = new Label();
label.BackColor = SystemColors.Control;
label.Location = new Point((_grid.HeadColumnWidth - _grid.HeadLabelWidth) / 2,
rowIndex * _grid.RowHeight + (_grid.RowHeight - _grid.HeadLabelHeight) / 2);
label.Size = new Size(_grid.HeadLabelWidth,_grid.HeadLabelHeight);
label.Text = text;
label.TextAlign = ContentAlignment.MiddleCenter;
_rowheadLabels[rowIndex] = label;
//Store row index in Tag which would be used in click event handler later
label.Tag = rowIndex;
//Handle click event to select one row.
label.Click += new EventHandler(label_Click);
_grid.Controls.Add(label);
}
void label_Click(object sender, EventArgs e)
{
int rowIndex = Convert.ToInt32((sender as Label).Tag);
if (_grid.CurrentRowIndex != rowIndex)
{
//Recover the old selected label.
if(_grid.CurrentRowIndex != -1)
_rowheadLabels[_grid.CurrentRowIndex].BackColor = SystemColors.Control;
//Modify the selected row.
_grid.CurrentRowIndex = Convert.ToInt32((sender as Label).Tag);
//Set the new selected label.
_rowheadLabels[_grid.CurrentRowIndex].BackColor = Color.LightBlue;
//Refresh the row background.
_grid.Invalidate();
}
}
//A simple method to add a label.
public void AddLabel(string text)
{
this.SetLabel(_rowheadLabels.Keys.Count, text);
}
private Dictionary<int,Label> _rowheadLabels = new Dictionary<int,Label>();
private GraphGrid _grid = null;
}
//Grid column include the square cells. The head column is not of this type.
public class GraphGridColumn
{
public GraphGridColumn(int index)
{
_index = index;
}
//Index of the column.
public int Index { get { return _index; } }
//Relations of the cells. One relation includes two cells.
public Dictionary<int, int> Relations
{
get { return _relations; }
}
private Dictionary<int, int> _relations = new Dictionary<int, int>();
private int _index;
}
//Grid row includes the cells and cell relations in this row.
public class GraphGridRow
{
public GraphGridRow(int index)
{
_index = index;
}
public GraphGridRow(int index,GraphGrid grid)
{
_index = index;
_grid = grid;
}
//Inser a cell to certain column.
public void SetCell(int colIndex, string value, Color color)
{
this.Cells[colIndex] = new GraphGridCell(_grid, _index, colIndex, value, color);
}
//Add a cell to the next column.
public void AddCell(string value, Color color)
{
this.SetCell(this.Cells.Keys.Count, value, color);
}
//The index of the row.
public int Index { get { return _index; } }
//If this row is blank.
public bool IsEmpty { set; get; }
//Cells
public Dictionary<int,GraphGridCell> Cells { get { return _cells; } }
//Relations between cells.
//key: row index, value: column index.
public Dictionary<int, int> Relations
{
get { return _relations; }
}
private Dictionary<int, int> _relations = new Dictionary<int,int>();
private int _index;
private Dictionary<int, GraphGridCell> _cells = new Dictionary<int, GraphGridCell>();
private GraphGrid _grid;
}
//Grid cell, includes the color, value(a number).
public class GraphGridCell
{
public GraphGridCell(GraphGrid grid, int rowIndex, int colIndex)
{
_grid = grid;
_rowIndex = rowIndex;
_colIndex = colIndex;
}
public GraphGridCell(GraphGrid grid, int rowIndex, int colIndex,string value,Color color)
{
_grid = grid;
_rowIndex = rowIndex;
_colIndex = colIndex;
this.Value = value;
this.Color = color;
}
public GraphGrid Grid { get { return _grid; } }
public int RowIndex { get { return _rowIndex; } }
public int ColumnIndex { get { return _colIndex; } }
public Color Color { set; get; }
//The number shows in the cell.
public string Value { set; get; }
private GraphGrid _grid;
private int _rowIndex;
private int _colIndex;
}
}
The sample code in one form shows how to use the control:
private void GraphGridForm_Load(object sender, EventArgs e)
{
//Add the columns.
for(int i = 0; i < 3; i++)
this.graphGrid1.Columns.Add(new GraphGridColumn(i));
//Add the head label in the first row.
this.graphGrid1.RowHeaders.AddLabel("row head 1");
//Add the first row.
GraphGridRow row = new GraphGridRow(0);
row.IsEmpty = false;
row.AddCell("100", Color.Red);
this.graphGrid1.Rows.Add(row);
//Add the head label in the second row.
this.graphGrid1.RowHeaders.AddLabel("row head 2");
//Add the second row.
row = new GraphGridRow(1);
row.IsEmpty = false;
row.AddCell("110", Color.Red);
row.AddCell("210", Color.LightBlue);
//Add a relation between cell in column 0 and cell in column 1
row.Relations[0] = 1;
this.graphGrid1.Rows.Add(row);
//Add an empty row.
row = new GraphGridRow(2);
row.IsEmpty = true;
this.graphGrid1.Rows.Add(row);
//Add the head label in the third row.
this.graphGrid1.RowHeaders.SetLabel(3,"row head 3");
row = new GraphGridRow(3);
row.IsEmpty = false;
row.AddCell("120", Color.Red);
row.AddCell("220", Color.LightBlue);
row.AddCell("320", Color.Green);
//Add relations between cells in column 0,1,2
row.Relations[0] = 1;
row.Relations[1] = 2;
this.graphGrid1.Rows.Add(row);
//Add relation between cell(row 1) and cell(row 3) in column 1
this.graphGrid1.Columns[1].Relations[1] = 3;
//Add relation between cell(row 0) and cell(row 1) in column 0
this.graphGrid1.Columns[0].Relations[0] = 1;
}
Regards, Aland Li
Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread. - Marked As Answer bySudeep Raj Monday, October 05, 2009 11:05 AM
- Marked As Answer byAland LiMSFT, ModeratorWednesday, October 07, 2009 2:24 AM
- Unmarked As Answer bySudeep Raj 16 hours 45 minutes ago
- Unmarked As Answer bySudeep Raj Monday, October 05, 2009 12:18 PM
-
| | Aland Li Friday, October 02, 2009 8:26 AM | Thanks Aland, I will try this out and let you know. Hope this helps !!
Sudeep
My Blog | | Sudeep Raj Saturday, October 03, 2009 5:42 AM | Thanks Aland once again. That was of great help & i got exactly what I was looking for. Hope this helps !!
Sudeep
My Blog | | Sudeep Raj Monday, October 05, 2009 11:05 AM | How do I manage the drag and drop fetaure in the custom control? What I need is the ability to drag any row to any position and drop there, the rows should be shifted one place down. Hope this helps !!
Sudeep
My Blog | | Sudeep Raj Monday, October 05, 2009 12:19 PM | Hi Sudeep,
You can handle the MouseDown, MouseMove and MouseUp events to implement the row dragging and dropping. These are the detail steps: 1. In the MouseDown event handler, use the mouse position to calculate the row under the mouse and save the row index to a member variable. 2. In the MouseMove event handler, modify the cursor to indicate the dragging process. 3. In the MouseUp event handler, use the mouse positon to calculate the row under the mouse and exchange this row to the row saved in the member variable.
Please feel free to let me know if you need more information or a code snippet. Aland Li Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.- Marked As Answer byAland LiMSFT, ModeratorWednesday, October 07, 2009 2:24 AM
- Unmarked As Answer bySudeep Raj 16 hours 45 minutes ago
-
| | Aland Li Wednesday, October 07, 2009 2:24 AM | Hi, Even I need a similar control. It would be nice if you could provide the code snippet for the drag & drop feture. | | mads_123 Wednesday, October 07, 2009 9:31 AM | Aland Thanks once again. You gave me just whats needed ;)
label.MouseDown += new MouseEventHandler(lable_MouseDown);
label.MouseUp += new MouseEventHandler(lable_MouseUp);
void lable_MouseDown(object sender, MouseEventArgs e)
{
int rowIndex = Convert.ToInt32((sender as Label).Tag);
_grid.LastRowIndex = _grid.CurrentRowIndex;
if (_grid.CurrentRowIndex != rowIndex)
{
//Recover the old selected label.
if (_grid.CurrentRowIndex != -1)
{
_rowheadLabels[_grid.CurrentRowIndex].BackColor = SystemColors.Control;
}
//Modify the selected row.
_grid.CurrentRowIndex = Convert.ToInt32((sender as Label).Tag);
//Set the new selected label.
_rowheadLabels[_grid.CurrentRowIndex].BackColor = Color.LightBlue;
//Refresh the row background.
_grid.Invalidate();
}
}
void lable_MouseUp(object sender, MouseEventArgs e)
{
int rowIndex = Convert.ToInt32((sender as Label).Tag);
if (_grid.CurrentRowIndex != rowIndex)
{}
}
I have added this. Now in the MouseUp event the row index is always same as the CurrentRowIndex. Could you tell me where am I doing a mistake?
Hope this helps !! Sudeep My Blog- Edited bySudeep Raj 15 hours 8 minutes agotypo
-
| | Sudeep Raj 18 hours 40 minutes ago |
| |
You can use google to search for other answers |
|
|
|
| | More Threads | | | Code Snippet: System.Component Model Namespace | | How to set window system colours using API & c# | | The type or namespace name IDump,TextProperty,RemoteFilePathProperty,SourceFileproperty,TransferPorotocolProperty,ValidityCheck,DestinationFileProperty could not be found (are you missing a using directive or an assembly | | How to avoid loops with handlers? | | Internet Explorer 6.0 has stopped sending forms in email | | Can't view Form in Designer | | input number only in gridtextbox cell | | resize line control | | Clicking an invisble button | | Inheriting from ContextMenuStrip | |
|