做过上位机项目多年,越来越觉得有以下几点需要注意
1.上位机开发写出的代码不是给自己看的,人员变动,新手老手的代码风格,会导致代码的维护工作越加困难,统一的框架,变量函数命名,相似的代码风格,会让接手别人的程序上手非常快.
2.开发出的软件尽可能考虑所以防呆,功能尽可能的完善.我们的软件不是给自己用的.
在开发中处理界面数据保存时,有时会繁琐,特别是处理单个控件,如何每个控件都用TextChange事件获取会消耗大量的时间,下面介绍一种单控件同时事件通知的方式来实现控件内容的更新:INotifyPropertyChanged 属性事件,通于和控件相互通知
/// <summary>
/// 用INI文件保存的参数定义
/// </summary>
public class IniParam<T> : INotifyPropertyChanged
{
#region 属性事件,通于和控件相互通知
public event PropertyChangedEventHandler PropertyChanged;//实现 属性值更改时,UI控件也更新
private void NotifyPropertyName(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
#endregion
/// <summary>
/// 构造函数
/// </summary>
/// <param name="name">参数名字,一般与对象名一致</param>
/// <param name="fileName">所保存的ini文件名</param>
/// <param name="section">段落名</param>
/// <param name="iniParamList">保存的list</param>
/// <param name="str">不为""时,该参数被修改后将被记录</param>
public IniParam(string name, string fileName, string section, BindingList<IniParam<T>> iniParamList, string str = "")
{
this.saveFileName = fileName;
this.saveSection = section;
this.paramName = name;
this.nameExplain = str;
iniParamList.Add(this);
}
public IniParam()
{
}
/// <summary>
/// 变量说明
/// </summary>
private string nameExplain;
private string saveFileName;
private string saveSection;
private string paramName;
private T pValue;
public T PValue
{
set { pValue = value; NotifyPropertyName("PValue"); }
get { return pValue; }
}
private T prePvalue
{
set;
get;
}
public void Init()
{
try
{
string path = "d:" +saveFileName + ".ini";
if (!File.Exists(path))
{
File.Create(path).Dispose();
}
{
Inihelp iniInit = new Inihelp(path);
string errStr = null; //参数不存在时返回默认值
if (typeof(T) == typeof(Boolean))
{
errStr = "false";
}
else
errStr = "0";
pValue = (T)Convert.ChangeType(iniInit.GetIni(saveSection, paramName, errStr), typeof(T));
prePvalue = pValue;
}
}
catch (Exception ex)
{
MessageBox.Show("加载参数 " + paramName + " 异常" + string.Format("rn捕获到未处理异常:{0}rn异常信息:{1}rn异常堆栈:{2}",
ex.GetType(), ex.Message, ex.StackTrace));
}
}
public void Save()
{
try
{
string path = "d:" +saveFileName + ".ini";
if (!File.Exists(path))
{
File.Create(path).Dispose();
}
Inihelp iniInit = new Inihelp(path);
iniInit.WriteIni(saveSection, paramName, pValue.ToString());
prePvalue = pValue;
}
catch (Exception ex)
{
MessageBox.Show("保存参数 " + paramName + " 异常" + string.Format("rn捕获到未处理异常:{0}rn异常信息:{1}rn异常堆栈:{2}",
ex.GetType(), ex.Message, ex.StackTrace));
}
}
}
INI文件帮助类
class Inihelp
{
private string filename;
public string FileNmae
{
get{return filename;}
set{filename = value;}
}
public Inihelp(string filepath)
{
filename=filepath;
}
/// <summary>
/// 写入ini文件
/// </summary>
/// <param name="section">ini文件的段落名称</param>
/// <param name="key">ini文件的关键字</param>
/// <param name="val">写入的值</param>
/// <param name="filepath">ini文件路径及名称</param>
/// <returns></returns>
[DllImport("kernel32.dll")]
private static extern int WritePrivateProfileString(
string section,
string key,
string val,
string filepath
);
/// <summary>
/// 获取ini键值
/// </summary>
/// <param name="section">ini文件的段落名称</param>
/// <param name="key">ini文件的关键字</param>
/// <param name="def">无法读取时候的缺省值</param>
/// <param name="retval">读取的值</param>
/// <param name="size">数值大小</param>
/// <param name="filepath">ini文件路径及名称</param>
/// <returns></returns>
[DllImport("kernel32.dll")]
private static extern int GetPrivateProfileString(
string section,
string key,
string def,
StringBuilder retval,
int size,
string filepath
);
/// <summary>
/// 获取ini值
/// </summary>
/// <param name="section">段落名</param>
/// <param name="key">关键字</param>
/// <param name="def">默认值</param>
/// <returns></returns>
public string GetIni(string section, string key, string def)
{
try
{
StringBuilder retstr = new StringBuilder(2048);
GetPrivateProfileString(section, key, def, retstr, 2048, filename);
return retstr.ToString();
}
catch(Exception m)
{
throw m;
}
}
/// <summary>
/// 写入ini值
/// </summary>
/// <param name="section">段落</param>
/// <param name="key">关键字</param>
/// <param name="val">值</param>
public void WriteIni(string section, string key, string val)
{
try
{
WritePrivateProfileString(section, key, val, filename);
}
catch (Exception m)
{
throw m;
}
}
}
生成操作对象
#region ini参数集合
public static BindingList<IniParam<string>> ParamListString = new BindingList<IniParam<string>>();
public static BindingList<IniParam<bool>> ParamListbool = new BindingList<IniParam<bool>>();
public static BindingList<IniParam<double>> ParamListdouble = new BindingList<IniParam<double>>();
public static BindingList<IniParam<int>> ParamListint = new BindingList<IniParam<int>>();
#endregion
/// <summary>
/// Log保存地址
/// </summary>
public static IniParam<string> m_sLogSavePath = new IniParam<string>("m_sLogSavePath", "machineparam", "系统参数", ParamListString, "Log保存地址");
使用时只需要在窗体初始化将控件的属性与变量进行绑定就可以.
TB_LogSavePath.DataBindings.Add(new Binding("Text", m_sLogSavePath, "PValue"));
对单控件数据刷新非常实用特别是来说,加载保存一个函数搞定.