第11章 表单自动完成
在web中,可以使用cookie来记录表单的输入。而在应用程序开发中没有这项功能,需要自己写代码实现。我们经常会输入一些信息,比如用户名,如果程序能够记录常用的一些输入信息,并在下次程序开启的时候加载这些表单信息,能够减少用户输入。
首先是表单保存的方式。由于是本地表单的数据保存,所以保存的方式可以是保存程序的目录下的一个配置文件,或者利用AppSettings(AppConfiguration)里面。这个没有什么太大的区别。
再次是表单的格式。表单项格式一般是“名称:值”的方式。值是表单的值,比如密码输入框中的密码。而名称应该包含输入框的信息。名称的选择是一个比较难以把握的问题。假如仅仅通过输入框的Name作为表单项的记录,那么重复率会很高。我们可以在输入框的Name的基础上再加上这个输入框的类的名称。这时候就基本没有可能存在的重复了。因为类的名称(包括域名)是唯一的,类中的输入框的名称也是唯一的。
最后考虑下程序可能升级,部分类的名称或者输入框的名称会改变,从而导致部分记录无效,所以最好设置最大的记录数和最长记录时间。
讲到这里,本章内容的理论差不多完了,下面附上部分主要代码仅供参考。
1)表单记录的类
public class RemeberSheetFillAssist
{
#region 属性
private List<RemeberSheetFillItem> m_items = new List<RemeberSheetFillItem>();
private static RemeberSheetFillAssist s_assist;
#endregion
#region 对外属性
[XmlIgnore()]
protected static string FileName
{
get { return Path.Combine(PathService.EnvironmentPath, "sheetFill.xml"); }
}
/// <summary>
/// 包含的条目
/// </summary>
public List<RemeberSheetFillItem> Items
{
get { return m_items; }
}
#endregion
#region 获得数据
/// <summary>
/// 获得表单数据,返回是否存在这个值得
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <param name="valueType"></param>
/// <returns></returns>
public static bool GetSheetFillValue(string name, out string value)
{
if (s_assist == null)
{
if (File.Exists(FileName))
{
LoadWithTip();
}
else
{
s_assist = new RemeberSheetFillAssist();
}
}
value = null;
lock (s_assist.Items)
{
foreach (RemeberSheetFillItem item in s_assist.Items)
{
if (item.Name == name)
{
value = item.ItemValue;
item.LastAccessTime = DateTime.Now.ToShortDateString();
return true;
}
}
}
return false;
}
/// <summary>
/// 获得表单数据,返回是否存在这个值得
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool GetSheetFillValue(string name, out Hashtable value)
{
string valueStr;
if (GetSheetFillValue(name, out valueStr) == false)
{
value = null;
return false;
}
value = Parse(valueStr);
return true;
}
/// <summary>
/// 获得表单数据,返回是否存在这个值得
/// </summary>
/// <param name="methodType"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool GetSheetFillValue(System.Reflection.MethodBase methodFrom, out string value)
{
string s = GetMethodKey(methodFrom);
return GetSheetFillValue(s,out value);
}
/// <summary>
/// 获得表单数据,返回是否存在这个值得
/// </summary>
/// <param name="methodType"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool GetSheetFillValue(System.Reflection.MethodBase methodFrom, out Hashtable value)
{
string s = GetMethodKey(methodFrom);
return GetSheetFillValue(s, out value);
}
#endregion
#region 设置表单
/// <summary>
/// 设置一个表单值
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <param name="valueType"></param>
public static void SetSheetFillValue(string name, string value)
{
if (s_assist == null)
{
if (File.Exists(FileName))
{
LoadWithTip();
}
else
{
s_assist = new RemeberSheetFillAssist();
}
}
lock (s_assist.Items)
{
foreach (RemeberSheetFillItem item in s_assist.Items)
{
if (item.Name == name)
{
if ((item.ItemValue != value)
|| (item.LastAccessTime != DateTime.Now.Date.ToString()))
{
item.ItemValue = value;
item.LastAccessTime = DateTime.Now.ToShortDateString();
s_assist.Save();
}
return;
}
}
RemeberSheetFillItem newItem = new RemeberSheetFillItem(name, value, DateTime.Now.ToShortDateString());
s_assist.Items.Add(newItem);
if (s_assist.Items.Count > 100)
{
s_assist.Items.Sort(new SheetFillItemCmper());
for (int i = 0; i < 30; i++)
{
s_assist.Items.RemoveAt(0);
}
}
}
s_assist.Save();
}
/// <summary>
/// 设置一个表单值
/// </summary>
/// <param name="methodType">当前方法的名称</param>
/// <param name="value"></param>
/// <param name="valueType"></param>
public static void SetSheetFillValue(System.Reflection.MethodBase methodFrom, string value)
{
string s = GetMethodKey(methodFrom);
SetSheetFillValue(s, value);
}
/// <summary>
/// 设置一个表单值
/// </summary>
/// <param name="methodType"></param>
/// <param name="value"></param>
/// <param name="valueType"></param>
public static void SetSheetFillValue(System.Reflection.MethodBase methodFrom, Hashtable value)
{
string s = GetMethodKey(methodFrom);
SetSheetFillValue(s, value);
}
/// <summary>
/// 设置一个表单值
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <param name="valueType"></param>
public static void SetSheetFillValue(string name, Hashtable value)
{
if (value == null)
throw new Exception("RemeberSheetFillAssist中输入Value不能为空");
string s = ToString(value);
SetSheetFillValue(name, s);
}
#endregion
#region 格式化判断
/// <summary>
/// 获得Method的key
/// </summary>
/// <param name="methodFrom"></param>
/// <returns></returns>
private static string GetMethodKey(System.Reflection.MethodBase methodFrom)
{
return (methodFrom.DeclaringType.Name + methodFrom.Name).GetHashCode().ToString();
}
/// <summary>
/// 格式化输出
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private static Hashtable Parse(string s)
{
if (s == null)
return null;
string prefix="Split=";
if (s.StartsWith(prefix) == false)
return null;
char SplitChar = s[prefix.Length];
string valueStr = s.Substring(prefix.Length + 1);
Hashtable ht = new Hashtable();
string[] cs = valueStr.Split(SplitChar);
for (int i = 0; i < cs.Length; i++)
{
int n = cs[i].IndexOf('=');
if (n > 0)
{
string key=cs[i].Substring(0,n);
string value=null;
if (n + 1 < cs[i].Length)
value = cs[i].Substring(n + 1);
if (ht.ContainsKey(key) == false)
{
ht.Add(key, value);
}
}
}
return ht;
}
/// <summary>
/// 转换为字符串
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static string ToString(Hashtable value)
{
IDictionaryEnumerator itor= value.GetEnumerator();
StringBuilder sb=new StringBuilder();
string prefix = "Split=";
char oldSplitChar = (char)4;
while (itor.MoveNext())
{
sb.Append(itor.Key + "=" + itor.Value);
sb.Append(oldSplitChar);
}
char[] nSplitChars = new char[] { '@', '#', '$', '%', '^', '&', '*', '[', ']', ':', ';', '|', ',', '.' };
string s=sb.ToString();
bool eNSplit = false;
char newSplitChar='&';
//特殊字符表示
for (int i = 0; i < nSplitChars.Length; i++)
{
if (s.IndexOf(nSplitChars[i]) < 0)
{
newSplitChar = nSplitChars[i];
eNSplit = true;
break;
}
}
//字母表示
if (eNSplit == false)
{
int zv=(char)'z'+1;
for (int i = (char)'a'; i < zv; i++)
{
if (s.IndexOf((char)i) < 0)
{
newSplitChar = (char)i;
eNSplit = true;
break;
}
}
}
//数值表示
if (eNSplit == false)
{
int zv = (char)'9' + 1;
for (int i = (char)'0'; i < zv; i++)
{
if (s.IndexOf((char)i) < 0)
{
newSplitChar = (char)i;
eNSplit = true;
break;
}
}
}
//它全部包含了,这么悲剧
if (eNSplit == false)
throw new Exception("RemeberSheetFillAssist.ToString(Hashtable value)竟然能把所有的字符串占用了...");
sb.Insert(0, prefix + oldSplitChar.ToString());
s = sb.ToString().Replace(oldSplitChar, newSplitChar);
return s;
}
#endregion
#region 表单的自动完成
/// <summary>
/// 把textbox的内容填充到toSetSheetFill中
/// </summary>
/// <param name="toSetSheetFill"></param>
/// <param name="textbox"></param>
public static void GetComponentSheetFill(Hashtable toSetSheetFill,TextBox textbox)
{
if(toSetSheetFill==null)
throw new ArgumentException("toFillCell不能为空", "toSetSheetFill");
toSetSheetFill.Add(textbox.Name, textbox.Text);
}
/// <summary>
/// 从toGetSheetFill获得数据并放到textbox中
/// </summary>
/// <param name="toGetSheetFill"></param>
/// <param name="textbox"></param>
public static void SetComponentSheetFill(Hashtable toGetSheetFill, TextBox textbox)
{
if (toGetSheetFill == null)
throw new ArgumentException("toFillCell不能为空", "toFillCell");
if (toGetSheetFill.ContainsKey(textbox.Name))
{
textbox.Text = toGetSheetFill[textbox.Name].ToString();
}
}
#endregion
#region 加载
/// <summary>
/// 加载数据
/// </summary>
/// <returns></returns>
private static RemeberSheetFillAssist Load()
{
string fileName = FileName;
if (!File.Exists(fileName))
{
return new RemeberSheetFillAssist();
}
// start out with the default instance
RemeberSheetFillAssist settings = new RemeberSheetFillAssist();
try
{
XmlSerializer ser = new XmlSerializer(typeof(RemeberSheetFillAssist));
using (TextReader tr = new StreamReader(fileName))
{
settings = (RemeberSheetFillAssist)ser.Deserialize(tr);
}
}
catch (Exception ex)
{
File.Delete(fileName);
}
return settings;
}
/// <summary>
/// 加载数据(显示Tip)
/// </summary>
private static void LoadWithTip()
{
Form form = new Form();
form.FormBorderStyle = FormBorderStyle.None;
form.Size = new System.Drawing.Size(200, 100);
PictureBox pb = new PictureBox();
pb.Size = new System.Drawing.Size(64, 64);
pb.Location = new System.Drawing.Point(18, 18);
pb.BackgroundImage = WorldWind.Properties.Resources.loading;
pb.BackgroundImageLayout = ImageLayout.Stretch;
Label label = new Label();
label.Font = new System.Drawing.Font("微软雅黑", 9);
label.Location = new System.Drawing.Point(80, 20);
label.AutoSize = false;
label.Size = new System.Drawing.Size(100, 60);
label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
label.Text = "加载表格的数据,请稍等...";
form.Controls.Add(pb);
form.Controls.Add(label);
form.StartPosition = FormStartPosition.CenterScreen;
form.TopMost = true;
Thread thread = new Thread(new ParameterizedThreadStart(LoadData));
thread.Start(form);
form.ShowDialog();
}
/// <summary>
/// 加载数据中
/// </summary>
/// <param name="formObj"></param>
private static void LoadData(object formObj)
{
s_assist = Load();
Form form = formObj as Form;
CloseForm(form);
}
/// <summary>
/// 关闭窗口
/// </summary>
/// <param name="form"></param>
private static void CloseForm(Form form)
{
if (form.InvokeRequired)
{
CloseFormDelegate svw = new CloseFormDelegate(CloseForm);
form.Invoke(svw, new object[] { form });
}
else
{
form.Close();
}
}
delegate void CloseFormDelegate(Form form);
#endregion
#region 保存
/// <summary>
/// 保存数据
/// </summary>
private void Save()
{
XmlSerializer ser = null;
try
{
ser = new XmlSerializer(this.GetType());
using (TextWriter tw = new StreamWriter(FileName))
{
ser.Serialize(tw, this);
}
}
catch (Exception ex)
{
throw new System.Exception(String.Format("Saving settings class '{0}' to {1} failed", this.GetType().ToString(), FileName), ex);
}
}
#endregion
}
/// <summary>
/// 表单记录项
/// </summary>
public class RemeberSheetFillItem
{
#region 属性
private string m_name;
private string m_itemValue;
private string m_lastAccessTime;
#endregion
#region 对外属性
public string Name
{
get { return m_name; }
set { m_name = value; }
}
public string ItemValue
{
get { return m_itemValue; }
set { m_itemValue = value; }
}
public string LastAccessTime
{
get { return m_lastAccessTime; }
set { m_lastAccessTime = value; }
}
#endregion
#region 构造函数
public RemeberSheetFillItem()
{
}
public RemeberSheetFillItem(string name, string value, string accessTime)
{
m_name = name;
m_itemValue = value;
m_lastAccessTime = accessTime;
}
#endregion
}
/// <summary>
/// 表单记录项的比较函数
/// </summary>
internal class SheetFillItemCmper : IComparer<RemeberSheetFillItem>
{
#region IComparer<RemeberSheetFillItem> 成员
public int Compare(RemeberSheetFillItem x, RemeberSheetFillItem y)
{
return string.Compare(x.LastAccessTime, y.LastAccessTime);
}
#endregion
}
下面是调用的代码:
private void RemeberSheet(bool toGet)
{
if (toGet)
{
Hashtable sheetHt;
WorldWind.Aide.RemeberSheetFillAssist.GetSheetFillValue(System.Reflection.MethodBase.GetCurrentMethod(),
out sheetHt);
if (sheetHt != null)
{
WorldWind.Aide.RemeberSheetFillAssist.SetComponentSheetFill(sheetHt, this.textBox_latitude);
WorldWind.Aide.RemeberSheetFillAssist.SetComponentSheetFill(sheetHt, this.textBox_longitude);
WorldWind.Aide.RemeberSheetFillAssist.SetComponentSheetFill(sheetHt, this.textBox_X);
WorldWind.Aide.RemeberSheetFillAssist.SetComponentSheetFill(sheetHt, this.textBox_Y);
}
}
else
{
Hashtable sheetHt=new Hashtable();
WorldWind.Aide.RemeberSheetFillAssist.GetComponentSheetFill(sheetHt, this.textBox_latitude);
WorldWind.Aide.RemeberSheetFillAssist.GetComponentSheetFill(sheetHt, this.textBox_longitude);
WorldWind.Aide.RemeberSheetFillAssist.GetComponentSheetFill(sheetHt, this.textBox_X);
WorldWind.Aide.RemeberSheetFillAssist.GetComponentSheetFill(sheetHt, this.textBox_Y);
WorldWind.Aide.RemeberSheetFillAssist.SetSheetFillValue(System.Reflection.MethodBase.GetCurrentMethod(),
sheetHt);
}
}