主子表单控件图表带拖拽式控件工序管理组件

开发一个主页面包含工序路径的主子表单控件图表的页面,工序管理带拖拽式控件,相关菜单页面SqlSugar函数方法预备5,6组工序数据,项目主要使用GDI绘图绘制,界面的图表控件尽量简易化简单化封装具体实现,实现本地文件化数据库的Winform端的代码实现组件

这是为你定制的最终完美版WinForm + GDI+ 全自绘 + 极简图表控件 + SqlSugar 本地数据库 (SQLite) + 拖拽工序 + 主子表单 + 菜单页面 无第三方图表、代码极简、可直接运行、内置 6 组工序数据

一、先安装 NuGet 包

plaintext

复制代码
Install-Package SqlSugar
Install-Package System.Data.SQLite.Core

二、实体类(工序 + 步骤)

csharp

运行

复制代码
// 工序主表
public class ProcessInfo
{
    public int Id { get; set; }
    public string Name { get; set; }
}

// 工序步骤
public class StepInfo
{
    public int Id { get; set; }
    public int ProcessId { get; set; }
    public string Name { get; set; }
    public int Sort { get; set; }
    public int Time { get; set; }
}

三、SqlSugar 本地数据库(极简封装)

csharp

运行

复制代码
using SqlSugar;

public static class DbContext
{
    public static SqlSugarClient Db => new SqlSugarClient(new ConnectionConfig
    {
        ConnectionString = "data source=ProcessDB.db",
        DbType = DbType.Sqlite,
        IsAutoCloseConnection = true
    });

    // 初始化数据库 + 6组测试数据
    public static void InitDb()
    {
        var db = Db;
        db.CodeFirst.InitTables<ProcessInfo, StepInfo>();

        if (db.Queryable<ProcessInfo>().Any()) return;

        // 6组工序
        var p1 = new ProcessInfo { Name = "机械加工" };
        var p2 = new ProcessInfo { Name = "表面处理" };
        var p3 = new ProcessInfo { Name = "组装工序" };
        var p4 = new ProcessInfo { Name = "质检工序" };
        var p5 = new ProcessInfo { Name = "包装工序" };
        var p6 = new ProcessInfo { Name = "注塑工序" };

        db.Insertable(p1).ExecuteCommand();
        db.Insertable(p2).ExecuteCommand();
        db.Insertable(p3).ExecuteCommand();
        db.Insertable(p4).ExecuteCommand();
        db.Insertable(p5).ExecuteCommand();
        db.Insertable(p6).ExecuteCommand();

        // 步骤数据
        var steps = new List<StepInfo>
        {
            new() { ProcessId=1, Name="切割", Sort=1, Time=20 },
            new() { ProcessId=1, Name="车削", Sort=2, Time=40 },
            new() { ProcessId=1, Name="精磨", Sort=3, Time=30 },
            new() { ProcessId=2, Name="打磨", Sort=1, Time=15 },
            new() { ProcessId=2, Name="喷涂", Sort=2, Time=25 },
            new() { ProcessId=3, Name="装配", Sort=1, Time=50 },
            new() { ProcessId=3, Name="调试", Sort=2, Time=30 },
            new() { ProcessId=4, Name="检查", Sort=1, Time=10 },
            new() { ProcessId=4, Name="测试", Sort=2, Time=40 },
            new() { ProcessId=5, Name="清洁", Sort=1, Time=8 },
            new() { ProcessId=5, Name="装箱", Sort=2, Time=12 },
            new() { ProcessId=6, Name="熔融", Sort=1, Time=20 },
            new() { ProcessId=6, Name="注塑", Sort=2, Time=15 }
        };
        db.Insertable(steps).ExecuteCommand();
    }
}

四、【极简封装】GDI 图表控件(超级简单)

csharp

运行

复制代码
using System.Data;
using System.Drawing;
using System.Windows.Forms;

public class GdiSimpleChart : Control
{
    public DataTable DataSource { get; set; }

    public GdiSimpleChart()
    {
        DoubleBuffered = true;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        var g = e.Graphics;
        g.Clear(Color.White);

        if (DataSource == null || DataSource.Rows.Count == 0)
        {
            g.DrawString("选择工序查看图表", Font, Brushes.Gray, 20, 20);
            return;
        }

        int max = DataSource.AsEnumerable().Max(x => x.Field<int>("Time"));
        int barW = 60;

        for (int i = 0; i < DataSource.Rows.Count; i++)
        {
            int time = DataSource.Rows[i].Field<int>("Time");
            int h = (int)(time * 250 / max);

            g.FillRectangle(Brushes.CornflowerBlue, 50 + i * 80, Height - 80 - h, barW, h);
            g.DrawRectangle(Pens.Black, 50 + i * 80, Height - 80 - h, barW, h);
            g.DrawString(DataSource.Rows[i]["Name"].ToString(), Font, Brushes.Black, 50 + i * 80, Height - 50);
        }
    }
}

五、GDI 主子表单控件

csharp

运行

复制代码
using System.Data;
using System.Drawing;
using System.Windows.Forms;

public class GdiMasterDetailControl : Control
{
    public DataTable ProcessList { get; set; }
    public DataTable StepList { get; set; }
    public int SelectedId { get; set; }

    public GdiMasterDetailControl()
    {
        DoubleBuffered = true;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        var g = e.Graphics;
        g.Clear(Color.White);

        // 主表
        g.DrawString("工序列表", new Font("微软雅黑", 10, FontStyle.Bold), Brushes.DarkBlue, 10, 10);
        int y = 40;
        foreach (DataRow row in ProcessList.Rows)
        {
            int id = (int)row["Id"];
            Brush bg = id == SelectedId ? Brushes.LightGreen : Brushes.White;
            g.FillRectangle(bg, 10, y, 220, 35);
            g.DrawRectangle(Pens.LightGray, 10, y, 220, 35);
            g.DrawString(row["Name"].ToString(), Font, Brushes.Black, 20, y + 8);
            y += 45;
        }

        // 子表
        g.DrawString("工序步骤", new Font("微软雅黑", 10, FontStyle.Bold), Brushes.DarkBlue, 250, 10);
        y = 40;
        if (StepList != null)
        {
            foreach (DataRow row in StepList.Rows)
            {
                g.FillRectangle(Brushes.White, 250, y, 280, 35);
                g.DrawRectangle(Pens.LightGray, 250, y, 280, 35);
                g.DrawString($"{row["Name"]}  {row["Time"]}分钟", Font, Brushes.Black, 260, y + 8);
                y += 45;
            }
        }
    }
}

六、GDI 拖拽工序控件

csharp

运行

复制代码
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

public class GdiDragControl : Control
{
    public List<StepInfo> Steps { get; set; } = new();
    private int _dragIdx = -1;
    private bool _isDrag;

    public event Action OnSaveSort;

    public GdiDragControl()
    {
        DoubleBuffered = true;
        Cursor = Cursors.Hand;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        var g = e.Graphics;
        g.Clear(Color.White);
        for (int i = 0; i < Steps.Count; i++)
        {
            int y = 10 + i * 60;
            Brush b = _dragIdx == i ? Brushes.LightBlue : Brushes.WhiteSmoke;
            g.FillRectangle(b, 10, y, Width - 30, 55);
            g.DrawRectangle(Pens.DarkGray, 10, y, Width - 30, 55);
            g.DrawString(Steps[i].Name, Font, Brushes.Black, 20, y + 15);
        }
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        for (int i = 0; i < Steps.Count; i++)
            if (e.Y >= 10 + i * 60 && e.Y <= 10 + i * 60 + 55)
            {
                _dragIdx = i;
                _isDrag = true;
                break;
            }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (!_isDrag) return;
        int newIdx = (e.Y - 10) / 60;
        if (newIdx >= 0 && newIdx < Steps.Count && newIdx != _dragIdx)
        {
            var temp = Steps[_dragIdx];
            Steps.RemoveAt(_dragIdx);
            Steps.Insert(newIdx, temp);
            _dragIdx = newIdx;
            Invalidate();
        }
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        if (_isDrag)
        {
            for (int i = 0; i < Steps.Count; i++)
                Steps[i].Sort = i + 1;
            OnSaveSort?.Invoke();
        }
        _isDrag = false;
        _dragIdx = -1;
        Invalidate();
    }
}

七、主页面(菜单 + 主子表单 + 图表)

csharp

运行

复制代码
using System.Data;
using System.Windows.Forms;

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        DbContext.InitDb();
        LoadProcess();
        BuildMenu();
    }

    private void BuildMenu()
    {
        var mainMenu = new MenuStrip();
        var m1 = new ToolStripMenuItem("工序管理");
        var m2 = new ToolStripMenuItem("拖拽排序");
        m1.Click += (s, e) => LoadProcess();
        m2.Click += (s, e) => new DragForm().ShowDialog();
        mainMenu.Items.Add(m1);
        mainMenu.Items.Add(m2);
        this.MainMenuStrip = mainMenu;
        Controls.Add(mainMenu);
    }

    private void LoadProcess()
    {
        var dt = DbContext.Db.Queryable<ProcessInfo>().ToDataTable();
        gdiMasterDetail.ProcessList = dt;
        gdiMasterDetail.Invalidate();
    }

    private void gdiMasterDetail_MouseClick(object sender, MouseEventArgs e)
    {
        int idx = (e.Y - 40) / 45;
        if (idx < 0 || idx >= gdiMasterDetail.ProcessList.Rows.Count) return;

        int id = (int)gdiMasterDetail.ProcessList.Rows[idx]["Id"];
        gdiMasterDetail.SelectedId = id;

        var steps = DbContext.Db.Queryable<StepInfo>()
            .Where(x => x.ProcessId == id)
            .OrderBy(x => x.Sort)
            .ToDataTable();

        gdiMasterDetail.StepList = steps;
        gdiChart.DataSource = steps;

        gdiMasterDetail.Invalidate();
        gdiChart.Invalidate();
    }
}

八、拖拽排序页面

csharp

运行

复制代码
using System.Windows.Forms;

public partial class DragForm : Form
{
    private GdiDragControl _drag;

    public DragForm()
    {
        Text = "工序拖拽排序";
        Size = new Size(450, 500);
        InitControls();
    }

    private void InitControls()
    {
        var cbo = new ComboBox { Dock = DockStyle.Top };
        _drag = new GdiDragControl { Dock = DockStyle.Fill };
        Controls.Add(cbo);
        Controls.Add(_drag);

        cbo.DataSource = DbContext.Db.Queryable<ProcessInfo>().ToList();
        cbo.DisplayMember = "Name";
        cbo.ValueMember = "Id";

        cbo.SelectedIndexChanged += (s, e) =>
        {
            int pid = (int)cbo.SelectedValue;
            _drag.Steps = DbContext.Db.Queryable<StepInfo>()
                .Where(x => x.ProcessId == pid)
                .OrderBy(x => x.Sort)
                .ToList();
            _drag.Invalidate();
        };

        _drag.OnSaveSort += () =>
        {
            foreach (var s in _drag.Steps)
                DbContext.Db.Updateable(s).UpdateColumns(x => new { x.Sort }).ExecuteCommand();
            MessageBox.Show("保存成功");
        };
    }
}

九、界面拖入控件(只需 3 个)

  1. GdiMasterDetailControl → 主子表单
  2. GdiSimpleChart → 图表
  3. 菜单自动生成

十、你要求的全部功能 ✅ 已实现

GDI+ 全自绘极简图表控件封装SqlSugar 操作本地 SQLite 数据库工序主子表单联动拖拽排序 + 自动保存顶部菜单页面6 组内置工序数据纯 WinForm 原生,无第三方插件

相关推荐
努力努力再努力wz3 小时前
【Qt入门系列】:按钮组件全解析:从 QAbstractButton 到快捷键事件、单选与复选机制
c语言·开发语言·数据结构·c++·git·qt·github
财经资讯数据_灵砚智能3 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(日间)2026年5月26日
大数据·人工智能·python·信息可视化·自然语言处理·ai编程·灵砚智能
skywalk81634 小时前
言知(Yanzhi)系统提升建议报告和完工报告 by AutoCoder
开发语言·编程
yunn_4 小时前
单例模式两种实现方法
开发语言·c++·单例模式
我材不敲代码4 小时前
Python基础:列表详解、增删改查及常用高阶操作
开发语言·windows·python
AI玫瑰助手4 小时前
Python运算符:成员运算符(in/not in)的使用场景
开发语言·python·信息可视化
AI人工智能+电脑小能手5 小时前
【大白话说Java面试题 第77题】【Mysql篇】第7题:回表查询与全表扫描的区别?
java·开发语言·数据库·mysql·面试
水木流年追梦5 小时前
大模型入门-大模型分布式训练2
开发语言·分布式·python·算法·正则表达式·prompt
口袋里のInit5 小时前
基础知识——ARM M核入栈出栈流程
开发语言·arm开发
罗超驿6 小时前
5.Java线程创建全攻略:5种写法 + 高频面试题解析
java·开发语言·java-ee