美好的一天!在本文中,我将描述为C#Windows Form创建元素的过程。例如,我将创建具有所有DataGridView功能的表。稍后我们将继续介绍元素。我们将在多个课程中创建第一个元素。在本课程中,我们将从表格绘图中进行绘制,并且还将:创建列,行,单元格。在编写时,我们将使用Visual Studio 2019开发环境.Net FrameWork 4.7.x,首先,我们将创建一个常规的Windows Form项目。我认为没有必要展示它。然后,我们才创建项目“ Windows窗体控件库”(我们将其称为CustomControl)。接下来,我们将创建一个UserControl.cs文件。我们删除它并创建普通的类TableCustoms.cs,该类将从Control类继承。在同一文件中,我们还将创建更多类,即:列,行,单元格。让我们分别考虑一下。让我们从Column开始: [Serializable]
public class Column
{
public string Name { get; set; } = "NameColumn";
public string Caption { get; set; } = "CaptionColumn";
public int Width { get; set; } = 100;
public Color Back { get; set; } = Color.White;
public Column()
{
}
}
行类: [Serializable]
public class Row
{
public int Heigth { get; set; } = 20;
public List<Cell> Cells { get; set; } = new List<Cell>();
public Row()
{
}
public Row(List<Cell> cells)
{
Cells = cells;
}
}
单元格类(要支持复制,请添加ICloneable接口): [Serializable]
public class Cell : ICloneable
{
public object Value { get; set; } = null;
public Cell()
{
}
public object Clone()
{
return MemberwiseClone();
}
}
现在设置我们的主要TableCustoms类: public class TableCustoms : Control
{
#region
public ObservableCollection<Column> Columns { get; set; } = new ObservableCollection<Column>();
private ObservableCollection<Row> rows = new ObservableCollection<Row>();
private int countRow = 0;
#endregion
#region
public int CountRow
{
get { return countRow; }
set
{
if (value > countRow)
{
int iteration = value - countRow;
for (int i = 0; i < iteration; i++)
{
rows.Add(new Row());
}
}
if (value < countRow)
{
int iteration = countRow - value;
for (int i = 0; i < iteration; i++)
{
rows.Remove(rows[rows.Count - 1]);
}
}
countRow = value;
}
}
public ObservableCollection<Row> Rows
{
get { return rows; }
set { }
}
public int ColumnHeaderHeigth { get; set; } = 20;
public int RowHeaderWidth { get; set; } = 20;
public Color ColumnHeaderBack { get; set; } = SystemColors.Control;
public Color BorderColor { get; set; } = Color.Black;
public bool NumerableRows { get; set; } = false;
#endregion
private void EditColumn()
{
}
private void EditRows()
{
if (countRow < rows.Count)
{
rows[rows.Count - 1].Cells = CreatCells(Columns.Count);
countRow++;
}
if (CountRow > rows.Count)
{
countRow--;
}
}
private List<Cell> CreatCells(int Count)
{
List<Cell> result = new List<Cell>();
for (int i = 0; i < Count; i++)
{
result.Add(new Cell());
}
return result;
}
public TableCustoms()
{
rows.CollectionChanged += (e, v) => EditRows();
Columns.CollectionChanged += (e, v) => EditColumn();
BackColor = SystemColors.AppWorkspace;
PanelTable panelTable = new PanelTable(this);
panelTable.Dock = DockStyle.Fill;
Controls.Add(panelTable);
}
}
为了使我们具有滚动条,我们需要使用ScrollableControl,因此我们将创建PanelTable类,继承ScrollableControl并将其放置在Control上(在下一课中,我将解释为什么我们创建两个不同的控件,而不立即使用ScrollableControl): internal class PanelTable : ScrollableControl
{
private TableCustoms BParent;
public PanelTable(TableCustoms bParent)
{
HScroll = true;
VScroll = true;
AutoScroll = true;
BParent = bParent;
}
protected override void OnPaint(PaintEventArgs e)
{
Matrix m = new Matrix();
m.Translate(this.AutoScrollPosition.X, this.AutoScrollPosition.Y, MatrixOrder.Append);
e.Graphics.Transform = m;
Graphics graf = e.Graphics;
int maxWidth = 0;
int maxHeight = 0;
foreach (Column item in BParent.Columns)
{
maxWidth += item.Width;
}
foreach (Row item in BParent.Rows)
{
maxHeight += item.Heigth;
}
AutoScrollMinSize = new Size(maxWidth + 100, maxHeight + 100);
graf.Clear(BParent.BackColor);
DrawHeaderColumns(graf);
DrawHeaderRows(graf);
DrawCells(graf);
base.OnPaint(e);
}
private void DrawHeaderColumns(Graphics graf)
{
int x = 2;
Rectangle rect;
rect = new Rectangle(x, 1, BParent.RowHeaderWidth, BParent.ColumnHeaderHeigth);
graf.DrawRectangle(new Pen(BParent.BorderColor), rect);
graf.FillRectangle(new SolidBrush(BParent.ColumnHeaderBack), rect);
x += BParent.RowHeaderWidth + 1;
foreach (Column item in BParent.Columns)
{
rect = new Rectangle(x, 1, item.Width, BParent.ColumnHeaderHeigth);
graf.DrawRectangle(new Pen(BParent.BorderColor), rect);
graf.FillRectangle(new SolidBrush(BParent.ColumnHeaderBack), rect);
if (item.Caption.Length != 0)
{
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
graf.DrawString(item.Caption, new Font("Times", 9), Brushes.Black, rect, sf);
}
x += item.Width + 1;
}
}
private void DrawHeaderRows(Graphics graf)
{
int y = 1;
int i = 0;
Rectangle rect;
y += BParent.RowHeaderWidth + 1;
foreach (Row item in BParent.Rows)
{
rect = new Rectangle(2, y, BParent.RowHeaderWidth, item.Heigth);
graf.DrawRectangle(new Pen(BParent.BorderColor), rect);
graf.FillRectangle(new SolidBrush(BParent.ColumnHeaderBack), rect);
if (BParent.NumerableRows)
{
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
graf.DrawString(i.ToString(), new Font("Times", 9), Brushes.Black, rect, sf);
}
i++;
y += item.Heigth + 1;
}
}
private void DrawCells(Graphics graf)
{
int x = 2 + BParent.RowHeaderWidth + 1;
int y = 2 + BParent.ColumnHeaderHeigth;
Rectangle rect;
int i = 0;
foreach (Row itemRow in BParent.Rows)
{
foreach (Column itemColumn in BParent.Columns)
{
rect = new Rectangle(x, y, itemColumn.Width, itemRow.Heigth);
graf.DrawRectangle(new Pen(BParent.BorderColor), rect);
graf.FillRectangle(new SolidBrush(Color.White), rect);
if (itemRow.Cells[i].Value != null)
{
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
graf.DrawString(itemRow.Cells[i].Value.ToString(), new Font("Times", 9), Brushes.Black, rect, sf);
}
x += itemColumn.Width + 1;
i++;
}
i = 0;
y += itemRow.Heigth + 1;
x = 2 + BParent.RowHeaderWidth + 1;
}
}
}
之后,“重新组装元素”项目并将元素添加到表单中(在主项目中):
现在,让我们检查一下元素的一些方法: public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
tableCustoms1.Rows.Add(new Row());
tableCustoms1.Rows.Add(new Row());
tableCustoms1.Rows[0].Cells[0].Value = "1";
tableCustoms1.Rows[1].Cells[1].Value = "2";
tableCustoms1.CountRow++;
tableCustoms1.Rows[0].Cells[0].Value = "";
}
}
我们启动我们的项目: