C/S Winform开发框架 - 单表基础资料窗体实现主从表资料管理
C/S Winform开发框架 - 单表基础资料窗体实现主从表资料管理
一、引言
单表窗体是指管理与维护单表基础数据的Winform窗体,通常用于管理与维护客户、产品、货币、单位等基础资料。
我们在实际开发过程中,往往单表窗体也会衍生出主从表结构的数据,本文将介绍基于单表窗体扩展主从表结构。
二、开发过程
本文以《客户资料》管理窗体为例,扩展客户收货地址,作为客户资料的明细表,请参考以下步骤快速开发。
1、表结构,主键,外键关系
dt_Customer:客户表,主键:CustomerCode
dt_Address:地址表,外键:OwnerCode,对应客户表的 CustomerCode
2、绑定明细表的数据源
vs 打开 frm_Customer窗体,在 DoBindingSummaryEditor 方法内获取明细表资料,并绑定表格数据源。
C# 全选
protected override void DoBindingSummaryEditor(object summary)
{
this.DoBindingEditorPanel(pcDetailEditor, summary);
this.DoBindingEditorPanel(tpDocParams, summary);
//在这里绑定明细表数据源
var listAddress = _BLL.GetDetails(_BLL.DataBinder.CustomerCode);
gcAddress.DataSource = listAddress;
}
3、实现BLL、DAL层 GetDetails 方法
C# 全选
/// <summary>
/// 获取客户收货地址
/// </summary>
/// <param name="customerCode"></param>
/// <returns></returns>
public List<dt_Address> GetDetails(string customerCode)
{
var q = _Database.GetQueryable<dt_Address>();
return q.Where(w => w.OwnerType == AddressOwnerType.Customer.ToString()
&& w.OwnerCode == customerCode).ToList();
}
4、实现BLL层自定义 Update 方法
因为提交2个表的资料,需要扩展BLL.Update方法,增加一个 listAddress 参数。
C# 全选
/// <summary>
/// 扩展 Update 方法,传入地址管理表格的数据源
/// </summary>
/// <param name="type">当前操作模式(add/edit)</param>
/// <param name="listAddress">地址管理表格的数据源</param>
/// <returns></returns>
public virtual bool Update(UpdateType type, List<dt_Address> listAddress)
{
//更新公共字段的数据
SetDetailCommonValue(_DataBinder);
var data = this.CreateSaveData(type, _DataBinder);
var input = new CustomerUpdateModel
{
MasterDataUpdate = data,
Address = listAddress,
};
//调用数据层的方法提交数据
return _Bridge.Update(input);
}
5、DoSave 方法 调用 _BLL.Update
C# 全选
/// <summary>
/// 保存资料,btnSave按钮事件
/// </summary>
public override void DoSave(IButtonInfo sender)
{
try
{
//省略代码...
var listAddress = gvAddress.GetDataSource<dt_Address>();
bool result = _BLL.Update(_UpdateType, listAddress);//调用业务逻辑层接口保存数据
if (result)
{
//省略代码...
}
}
6、扩展 DAL层的Update方法
C# 全选
public bool Update(CustomerUpdateModel input)
{
try
{
_Database.BeginTransaction();
//提交主表:客户资料
base.Update(input.MasterDataUpdate, _Database, false);
#region 提交明细表:客户地址资料
SetCommonValue<dt_Address>(input.Address);
//获取当前客户编码,作为客户地址表的外键值
var customerCode = input.MasterDataUpdate.VisibleList.First().CustomerCode;
foreach (var v in input.Address)
{
//新增记录,设置默认值
if (v.isid.IsEmpty())
{
v.isid = IdHelper.GetId();
v.OwnerType = PublicEnum.AddressOwnerType.Customer.ToString();
v.OwnerCode = customerCode;
}
}
//删除旧数据
_Database.Remove<dt_Address>(w => w.OwnerType == PublicEnum.AddressOwnerType.Customer.ToString() && w.OwnerCode == customerCode);
//保存地址
_Database.Add(input.Address);
#endregion
_Database.CommitTransaction();
return true;
}
catch (System.Exception)
{
_Database.RollbackTransaction();
throw;
}
}
7、客户资料提交数据模型
C# 全选
/// <summary>
/// 客户资料提交数据模型
/// </summary>
public class CustomerUpdateModel
{
//主表数据
public MasterDataUpdate<dt_Customer> MasterDataUpdate { get; set; }
/// <summary>
/// 明细表数据
/// </summary>
public List<dt_Address> Address { get; set; }
//
//在这里可以添加多个明细表
//
}
8、客户地址表格添加【新增】、【删除】按钮
下面代码包括 客户地址表格样式设置、初始化表格的新增、删除按钮。
C# 全选
frmGridCustomize.RegisterGrid(gvAddress);//注册表格组件,自动添加右键弹出菜单功能
DevStyle.SetGridControlLayout(gcAddress, true);//明细表表格样式设置
DevStyle.SetDetailGridViewLayout(gvAddress);//明细表表格样式设置
gcAddress.EmbeddedNavigator.ButtonClick += new NavigatorButtonClickEventHandler(this.OnEmbeddedNavigatorButtonClick_Process); //绑定明细表格的按钮事件
C# 全选
/// <summary>
/// 明细表格按钮事件
/// </summary>
/// <param name="sender">GridControlNavigator组件</param>
/// <param name="e">事件参数</param>
private void OnEmbeddedNavigatorButtonClick_Process(object sender, NavigatorButtonClickEventArgs e)
{
try
{
GridControl gc = (GridControl)((GridControlNavigator)sender).Parent;
GridView gv = (GridView)gc.Views[0]; //明细表格:取GridControl第一个GridView组件.
//新增或插入记录
if (e.Button.ImageIndex == DetailButtons.Add || e.Button.ImageIndex == DetailButtons.Insert)
{
var row = new dt_Address();
row.OwnerCode = txtCustomerCode.Text;
row.OwnerType = PublicEnum.AddressOwnerType.Customer.ToString();
if (e.Button.ImageIndex == DetailButtons.Add)//增加-Add
{
gv.AddRow(row);
}
else if (e.Button.ImageIndex == DetailButtons.Insert)//插入-Insert
{
gv.InsertRow(row);
}
gv.FocusedColumn = gv.VisibleColumns[0];//第1列设置焦点单元格
}
else if (e.Button == gc.EmbeddedNavigator.Buttons.CustomButtons[DetailButtons.Delete])
{
if (Msg.AskQuestion("确定要删除这条记录?"))
gv.DeleteRow(gv.FocusedRowHandle);
}
e.Handled = true;
}
catch (Exception ex)
{
LogUserOperate.Write(ex);
Msg.ShowException(ex);
}
}
9、ButtonStateChanged 事件处理控件状态
C# 全选
protected override void ButtonStateChanged(UpdateType currentState)
{
base.ButtonStateChanged(currentState);
this.SetDetailEditorsAccessable(tpDocParams, this.DataChanged);
this.SetDetailEditorsAccessable(tpAddress, this.DataChanged);
gvAddress.OptionsBehavior.Editable = this.DataChanged;
}
三、数据编辑页拆分为多个标签页面
拆分目的:当资料列数量较多,或者需要按类型区分管理
操作步骤:
步骤1:添加标签页
选择 tcBusiness 组件,点右侧小三角图标,点击 Add Tab Page 菜单添加标签页。
步骤2:重写 ShowSummaryPage / ShowDetailPage 方法
C# 全选
protected override void ShowSummaryPage(bool disableDetailPage)
{
base.ShowSummaryPage(disableDetailPage);
if (disableDetailPage)
{
tpDocParams.PageEnabled = false;
tpAddress.PageEnabled = false;
}
}
C# 全选
protected override void ShowDetailPage(bool disableSummaryPage)
{
this.tpDetail.PageEnabled = true;
tpSummary.PageEnabled = !disableSummaryPage;
tpDocParams.PageEnabled = true;
tpAddress.PageEnabled = true;
if (tcBusiness.SelectedTabPage == tpSummary)
tcBusiness.SelectedTabPage = this.tpDetail;
}
步骤3:修改 DoBindingSummaryEditor 方法,绑定数据源
C# 全选
protected override void DoBindingSummaryEditor(object summary)
{
this.DoBindingEditorPanel(pcDetailEditor, summary);
this.DoBindingEditorPanel(tpDocParams, summary); //绑定拆分标签页的数据源
//省略代码...
}
步骤4:状态控制 ButtonStateChanged
C# 全选
protected override void ButtonStateChanged(UpdateType currentState)
{
base.ButtonStateChanged(currentState);
//扩展的标签页组件状态控制
this.SetDetailEditorsAccessable(tpDocParams, this.DataChanged);
this.SetDetailEditorsAccessable(tpAddress, this.DataChanged);
gvAddress.OptionsBehavior.Editable = this.DataChanged;
//省略代码....
}
四、效果图
版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
NewDoc C/S框架网