前言
该项目使用的是VS2019与Dev19.2.6的版本进行开发,可能各版本之间存在差异。
该文章用于记录作为个人第一次真正进行WinForms项目开发所接触的各类知识点与技巧,也希望同时能够帮助到一些初步接触的人。
正文
一、GridView
1.1 设置新增数据行
1.2 GridView中的多个字段数据进行拼接
var dataTable = gridControl1.DataSource as DataTable; // 如果数据源是DataTable
if (dataTable != null)
{
// 在这里处理dataTable
// 拼接结果字符串
var result = string.Join("|", dataTable.Rows.Cast<DataRow>().Select(row =>
{
var inspectItem = row["inspectitem"].ToString();
var status = (bool)row["pass"] ? "pass" :
(bool)row["fail"] ? "fail" :
(bool)row["unchecked"] ? "不适用" : "";
var type = (bool)row["fga"] ? "FGA" :
(bool)row["finish"] ? "成品" : "";
return $"{inspectItem}_{status}{(string.IsNullOrEmpty(type) ? "" : $"_{type}")}";
}));
model.InspectItem = result;
}
1.3 获取聚焦行字段的值
gridView1.GetFocusedRowCellDisplayText("shift")
1.4 在GridView显示的日期字段,对内容进行格式化处理
/// <summary>
/// 格式化日期
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gridView2_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
{
if (e.Column.FieldName == "shiftdate") // 替换成你的日期字段名
{
e.DisplayText = (DateTime.Parse(e.DisplayText)).ToString("yyyy-MM-dd");
}
}
1.5 改变单元格颜色
/// <summary>
/// 表格样式设计
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gridView1_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
{
if (e.Column.FieldName == "Usage") // 替换成你的日期字段名
{
e.DisplayText = decimal.Parse(e.DisplayText).ToString("f2");
}
if (e.Column.FieldName == "NeddsAccount") // 替换成你的日期字段名
{
e.DisplayText = decimal.Parse(e.DisplayText).ToString("f2");
}
if (e.Column.FieldName == "InventoryAccount") // 替换"YourColumnName"为你的列名
{
// 尝试将单元格值转换为可比较的数值类型
// 注意:这里假设单元格值是数值型,根据实际情况可能需要其他转换
if (e.CellValue is decimal)
{
decimal value = Convert.ToDecimal(e.CellValue);
// 如果值小于0
if (value < 0)
{
// 更改单元格的背景色为红色
e.Appearance.BackColor = Color.Red;
}
}
}
}
1.6 改变数据行颜色
/// <summary>
/// 改变数据行颜色
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gridView3_RowStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowStyleEventArgs e)
{
if(e.RowHandle >= 0)
{
int isLower = Convert.ToInt32(gridView3.GetRowCellValue(e.RowHandle, gridView3.Columns["IsLower"]));
if(isLower == 1)
{
e.Appearance.BackColor = Color.LightGreen;
e.HighPriority = true;
}
}
}
1.7 显示页脚
gridView1.OptionsView.ShowFooter = true;
gridView1.Columns["sku"].Summary.Add(DevExpress.Data.SummaryItemType.Count, "material", "总行数:{0}");
二、ComboBox
2.1 绑定方法一:通过DataTable进行绑定
DataTable dt_shift = new ManufactureProductionRecords_BLL().Query_ClassTypeByShiftDate_DT(shiftdate, "Shift");
comboBox2.Text = null;
comboBox2.DataSource = dt_shift;
comboBox2.DisplayMember = "shift";
comboBox2.ValueMember = "shift";
2.2 绑定方法二:通过List<string>进行绑定
List<ProductionRecords> sku_list = new ManufactureProductionRecords_BLL().Query_ClassTypeByShiftDate_Shift_List(shiftdate, shift, "SKU");
List<string> skus = sku_list
.Select(x => x.sku).ToList();
comboBox3.Text = null;
comboBox3.Items.Clear();
comboBox3.Items.AddRange(skus.ToArray());
2.3 模糊查询
/// <summary>
/// SKU模糊查询
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void comboBox3_TextChanged(object sender, EventArgs e)
{
try
{
string filterText = comboBox3.Text;
this.comboBox3.Items.Clear();
skus.Clear();
skus = sku_list.Where(x => x.sku.Contains(filterText)).Select(x => x.sku).ToList();
this.comboBox3.Items.AddRange(skus.ToArray());
this.comboBox3.SelectionStart = this.comboBox3.Text.Length;
Cursor = Cursors.Default;
this.comboBox3.DroppedDown = true;
}
catch (Exception)
{
}
}
三、SchedulerControl
3.1 选择显示的日期类型(按周、按月等)
默认显示的类型无法在Views里的显示选项中关闭
3.2 日程项绑定
public void RefreshData()
{
startdate = schedulerControl1.Start;
var calendars_dt = Plan_Date();
//数据绑定DataTable
schedulerDataStorage1.Appointments.DataSource = calendars_dt;
schedulerDataStorage1.Labels.DataSource = calendars_dt;
}
3.3 设置日程项颜色
/// <summary>
/// 日程项颜色
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void schedulerControl1_AppointmentViewInfoCustomizing(object sender, DevExpress.XtraScheduler.AppointmentViewInfoCustomizingEventArgs e)
{
DevExpress.XtraScheduler.Drawing.AppointmentViewInfo viewInfo = e.ViewInfo as DevExpress.XtraScheduler.Drawing.AppointmentViewInfo;
if (e.ViewInfo.Appointment.PercentComplete == 0)
{
viewInfo.Appearance.BackColor = System.Drawing.Color.Blue;
}
if (e.ViewInfo.Appointment.PercentComplete == 1)
{
viewInfo.Appearance.BackColor = System.Drawing.Color.Green;
}
if (e.ViewInfo.Appointment.PercentComplete == 2 )
{
viewInfo.Appearance.BackColor = System.Drawing.Color.Yellow;
}
}
3.4 设置日程主题背景
3.5 设置start与end不在日程项中显示
3.6 日程项点击事件
/// <summary>
/// 日程项点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void schedulerControl1_Click(object sender, EventArgs e)
{
if (schedulerControl1.SelectedAppointments.Count > 0)
{
selectDate = schedulerControl1.SelectedAppointments[0].Start;
var selectShift = schedulerControl1.SelectedAppointments[0].Subject;
var nowRecords = records_date.Where(x => x.shiftdate == selectDate && x.shift==selectShift).ToList();
records = ConvertToMethods.ConvertToDataTable(nowRecords);
gridControl2.DataSource = records;
}
}
四、获取控件修改后的值
4.1 RepositoryItemComboBox
/// <summary>
/// Sku下拉框选项更改事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void repositoryItemComboBox3_EditValueChanged(object sender, EventArgs e)
{
ComboBoxEdit editor = sender as ComboBoxEdit;
if(editor != null)
{
var newValue = editor.EditValue.ToString();
SKU sku_standardProductivity = new SKU_BLL().GetSku(newValue);
int focused = gridView2.FocusedRowHandle;
//确保有选中行
if(focused >= 0 && sku_standardProductivity != null)
{
double standardproductivity = sku_standardProductivity.cycletime;
double planQty = double.Parse(gridView2.GetFocusedRowCellDisplayText("planqty"));
gridView2.SetFocusedRowCellValue("standardproductivity", standardproductivity);
if(standardproductivity != 0)
{
string workTime = (planQty / standardproductivity).ToString("f2");
gridView2.SetFocusedRowCellValue("worktime", workTime);
}
}
else
{
MessageBox.Show("当前选中的sku的节拍数据未维护!");
}
}
}
4.2 RepositoryItemCheckEdit
/// <summary>
/// sku勾选事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void repositoryItemCheckEdit1_EditValueChanged(object sender, EventArgs e)
{
CheckEdit editor = sender as CheckEdit;
var isChecked = (bool)editor.EditValue;
string sku = gridView1.GetFocusedRowCellDisplayText("Material");
if (isChecked)
{
sku_list.Add(sku);
sku_list = sku_list.Distinct().ToList();
repositoryItemComboBox3.Items.Clear();
repositoryItemComboBox3.Items.AddRange(sku_list);
#region 新增绑定数据行
var shiftDate = DateTime.Parse(dateTimePicker1.Text).ToString("yyyy-MM-dd");
var shift = comboBox2.Text;
var workShop = comboBox1.Text;
var planQty = textEdit1.Value;
var proccess = comboBox3.Text;
var line = comboBox4.Text;
DataRow newRow = records.NewRow();
newRow["shiftdate"] = shiftDate;
newRow["shift"] = shift;
newRow["line"] = line;
newRow["sku"] = sku;
newRow["workshop"] = workShop;
newRow["process"] = proccess;
newRow["planqty"] = planQty;
newRow["finqty"] = 0;
SKU sku_standardProductivity = new SKU_BLL().GetSku(sku);
if(sku_standardProductivity != null && sku_standardProductivity.cycletime >= 0)
{
double standardproductivity = sku_standardProductivity.cycletime;
string workTime = ((double)planQty / standardproductivity).ToString("f2");
newRow["standardproductivity"] = standardproductivity;
newRow["worktime"] = workTime;
}
else
{
newRow["standardproductivity"] = -1;
newRow["worktime"] = -1;
}
#endregion
records.Rows.Add(newRow);
}
else
{
sku_list.Remove(sku);
repositoryItemComboBox3.Items.Clear();
repositoryItemComboBox3.Items.AddRange(sku_list);
}
}
五、导入Excel表
5.1 Excel表导入与进度条显示
/// <summary>
/// 导入按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void simpleButton1_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog openFileDialog = new OpenFileDialog
{
Filter = "Excel Files|*.xls;*.xlsx",
Title = "Select an File"
};
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string filePath = openFileDialog.FileName;
simpleButton1.Visible = false;
await Task.Run(() => ProcessExcelFile(filePath));
simpleButton1.Visible = true;
gridControl1.DataSource = new BomStructure_BLL().BomStructure_DT();
gridView1.OptionsView.ShowFooter = true;
gridView1.Columns["sku"].Summary.Add(DevExpress.Data.SummaryItemType.Count, "material", "总行数:{0}");
}
}
catch (Exception)
{
simpleButton1.Visible = true;
MessageBox.Show("导入异常,请检查Excel表格");
//throw;
}
}
private void ProcessExcelFile(string filePath)
{
List<BomStructure> boms = ReadExcel(filePath);
if (boms.Count > 0)
{
int resultnum = new BomStructure_BLL().ClearBomStructure_DT();
resultnum = 0;
this.Invoke(new Action(() =>
{
progressBar1.Maximum = boms.Count;
progressBar1.Value = 0;
progressBar1.Visible = true;
label1.Visible = true;
}));
int num = 0;
foreach (var item in boms)
{
resultnum = new BomStructure_BLL().InsertBomStructure_DT(item);
num++;
this.Invoke(new Action(() =>
{
progressBar1.Value += 1;
label1.Text = ((double)num / boms.Count * 100).ToString("f2") + "%";
label1.Refresh();
}));
}
MessageBox.Show($"成功导入【{num}】条数据");
}
}
/// <summary>
/// 读取数据行
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
private List<BomStructure> ReadExcel(string filePath)
{
DateTime nowTime = DateTime.Now;
List<BomStructure> boms = new List<BomStructure>();
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var result = reader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = (_) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
DataTable dataTable = result.Tables[0];
foreach (DataRow row in dataTable.Rows)
{
if (row["Material"].ToString().Length == 0)
{
continue;
}
BomStructure bom = new BomStructure
{
Sku = row["Material"].ToString(),
Level = int.Parse(row["Level"].ToString()),
Component = row["Component"].ToString(),
ImportTime = nowTime,
};
boms.Add(bom);
}
}
}
return boms;
}
5.2 其中关于异步方法的使用
//调用异步方法
await Task.Run(() => ProcessExcelFile(filePath));
//在异步方法中更新控件的数据
this.Invoke(new Action(() =>
{
progressBar1.Maximum = boms.Count;
progressBar1.Value = 0;
progressBar1.Visible = true;
label1.Visible = true;
}));
//实现显示值的刷新
label1.Refresh();
六、导出Excel表
/// <summary>
/// 导出Excel
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void simpleButton2_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog = new SaveFileDialog
{
Filter = "Excel Files|*.xlsx",
Title = "Save an Excel File"
};
if(saveFileDialog.ShowDialog() == DialogResult.OK)
{
string filePath = saveFileDialog.FileName;
ExporToExcel(filePath);
MessageBox.Show("Excel导出成功");
}
}
/// <summary>
/// 自定义表格内容
/// </summary>
/// <param name="filePath"></param>
public void ExporToExcel(string filePath)
{
using(var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add("可排订单表");
//添加表头
worksheet.Cells[1, 1].Value = "SalesOrd.";
worksheet.Cells[1, 2].Value = "PONumber";
worksheet.Cells[1, 3].Value = "Custrname";
//设置表头样式
using (var range = worksheet.Cells[1,1,1,3])
{
range.Style.Font.Bold = true;
range.Style.Font.Size = 12;
range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
range.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGreen);
//列宽自适应
range.AutoFitColumns();
}
//添加数据
for (int i = 0; i < orderPlans.Count; i++)
{
worksheet.Cells[i + 2, 1].Value = orderPlans[i].SalesOrd;
worksheet.Cells[i + 2, 2].Value = orderPlans[i].PONumber;
worksheet.Cells[i + 2, 3].Value = orderPlans[i].CustrName;
}
//列宽自适应
worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
//保存到文件
var fileInfo = new FileInfo(filePath);
package.SaveAs(fileInfo);
}
}
七、快速转换为DataTable
/// <summary>
/// 类型转换
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="items"></param>
/// <returns></returns>
public static DataTable ConvertToDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
// 获取所有属性
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo prop in Props)
{
// 设置DataTable列名为属性名
dataTable.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
// 插入属性值
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
后序
本来想分两次来写的,写着写着就干脆一次性写完好了。
因为本来经理给我分配的任务是让我去写uni-app的,但是都快写完了,突然说那个不用写了。所以才来接手写这个WinForms项目,需要开发的页面与功能也就少很多了。
关于写uni-app的项目后端使用的是.Net Core,如果后面有时间能把它完善的差不多了的话,再分享出来给初学者进行简单的个人项目开发。