有这样一个场景,有AB两个客户总对界面摆放有着不同的喜好,一个喜欢查询条件输入区(被放在一个groupbox中)在界面的上半部分,输入区在下半部分(被放在另一个groupbox中),另一个用户则正好相反,所以我们在界面设计确认时今天A在时,我们听他的要求,改一次,明天A去开会了,B来确认,又让我们改回来,几次下来,觉得很痛苦,如果界面有区多的区域,比如说一个查询条件输入区、一个业务数据录入区、一个输出区,这种情况下,客户的喜好更是会让你左改右改,所以我们最后决定提供以GroupBox为单位的,运行时可拖拽上下位置的功能,让不同的客户根据自己的喜好去拖拽,我们后台自动保存设定就是了。
场景描述很复杂,但代码实现却很简练:
一个全权负责拖放管理的类实现:
using System;using System.Windows.Forms;namespace Subindex{ /// <summary> /// /// </summary> public class DragDropAgent//4 groupBox control in runtime dragDrop support, Written By Linnet 2006-4-6 { private DragDropAgent() { // // TODO: 在此处添加构造函数逻辑 // }
/// <summary> /// 得到一个包含首层父控件的控件的对象名,如form1下groupbox1中的textbox1,将返回form1.textbox1 /// </summary> /// <param name="sender">要获得对象名的控件实例</param> /// <returns></returns> public static string getFullName(Control sender) { string name=sender.Name; while (sender.Parent!=null) sender=sender.Parent; return sender.Name+"."+name; }
/// <summary> /// 设置指定GroupBox控件的拖放操作,根据CanDrag和CanDrop决定拖出/放入的支持 /// </summary> /// <param name="sender">要设置拖放特性的GroupBox对象</param> /// <param name="CanDrag">是否可以拖出</param> /// <param name="CanDrop">是否可以放入</param> public static void DragDropHook(GroupBox sender,bool CanDrag,bool CanDrop) { if (CanDrag) DragHook(sender); if (CanDrop) DropHook(sender); gutPosition(sender); }
/// <summary> /// 设置指定GroupBox控件的拖放操作,同时支持拖出和放入 /// </summary> /// <param name="sender">要设置拖放特性的GroupBox对象</param> public static void DragDropHook(GroupBox sender) { DragDropHook(sender,true,true); }
private static void DragHook(GroupBox sender) { sender.MouseDown+=new MouseEventHandler(Do_Drag); }
private static void DropHook(GroupBox sender) { sender.AllowDrop=true; sender.DragDrop+=new DragEventHandler(Drag_Drop); sender.DragEnter+=new DragEventHandler(Drag_Enter); }
private static void Drag_Enter(object sender, System.Windows.Forms.DragEventArgs e) { if (e.Data.GetDataPresent(new GroupBox().GetType())) e.Effect = DragDropEffects.Move ; }
private static void Do_Drag(object sender, MouseEventArgs e) { (sender as Control) .DoDragDrop(sender, DragDropEffects.Move);
}
private static void Drag_Drop(object sender, System.Windows.Forms.DragEventArgs e) { try {
GroupBox self=sender as GroupBox;
GroupBox ct= e.Data.GetData(self.GetType()) as GroupBox;
if (self==ct) return;
Control parent=self.Parent;
int ord=parent.Controls.GetChildIndex(self);
int ordself=self.Top>ct.Top?ord+1:ord-1;
DockStyle dss=self.Dock; self.Dock=ct.Dock;; ct.Dock=dss; // System.Drawing.Point dps=self.Location; // self.Location=ct.Location; // ct.Location=dps;
if (ordself>ord) { setPosition(self,ordself); setPosition(ct,ord); } else { setPosition(ct,ord); setPosition(self,ordself); }
} catch (Exception ee) { System.Windows.Forms.MessageBox.Show(ee.Message,"Error");
} }
private static void gutPosition(GroupBox sender) {
string order=AppSettings.ReadSetting(getFullName(sender)+":Order"); string dock=AppSettings.ReadSetting(getFullName(sender)+":Dock"); try { int Position=int.Parse(order); sender.Parent.Controls.SetChildIndex(sender,Position); Position=int.Parse(dock); sender.Dock=(DockStyle)Position; } catch {
} }
private static void setPosition(GroupBox sender,int Position) { sender.Parent.Controls.SetChildIndex(sender,Position);
AppSettings.WriteSetting(getFullName(sender)+":Order",Position.ToString()); AppSettings.WriteSetting(getFullName(sender)+":Dock",((int)sender.Dock).ToString());
}
}}
只要将所有groupBox的Dock属性设为同一方向后,只需要Form_Load时调用只需一句就可实现运行时拖放:
DragDropAgent.DragDropHook(this.grpIndex); DragDropAgent.DragDropHook(this.grpWrap);//可拖动可放入,如果要设计成只可拖动或只可放入的请修改DragDropAgent类的那个实现方法的为public
另外,上述类中使用了负责配置文件写入的AppSettings类,代码也一并给出:
using System;using System.Xml; using System.Configuration;using System.Reflection;using System.IO;
namespace Subindex{ /// <summary> /// /// </summary> public class AppSettings { private static readonly string configFile; private AppSettings() { // // TODO: 在此处添加构造函数逻辑 // } static AppSettings() { configFile=getConfigFilePath(); } // public static string ReadSetting(string key)// {// string s=null;// try// {//// s= ConfigurationSettings.AppSettings[key];// }// catch (Exception e)// {// System.Windows.Forms.MessageBox.Show(e.Message);// }// return s;// }
public static string ReadSetting(string Key) { string Path="/configuration/appSettings/add"; XmlDocument doc = loadConfigDocument(); //if (doc.SelectSingleNode(Path) == null) return null; XmlElement elem = (XmlElement)doc.SelectSingleNode(string.Format(Path+"[@key='{0}']", Key)); return elem==null?null:elem.GetAttribute("value");; }
public static void WriteSetting(string Key, string Value) { XmlDocument doc = loadConfigDocument();
if (doc.SelectSingleNode("//configuration") == null) doc.AppendChild(doc.CreateNode(XmlNodeType.Element,"configuration",""));
XmlNode node = doc.SelectSingleNode("//appSettings");
if (node == null) { node=doc.CreateNode(XmlNodeType.Element,"appSettings",""); doc.SelectSingleNode("//configuration").AppendChild(node); }
try { XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='{0}']", Key));
if (elem != null) { elem.SetAttribute("value", Value); } else { elem = doc.CreateElement("add"); elem.SetAttribute("key", Key); elem.SetAttribute("value", Value); node.AppendChild(elem); } doc.Save(configFile); } catch { throw; } }
public static void RemoveSetting(string key) { XmlDocument doc = loadConfigDocument();
XmlNode node = doc.SelectSingleNode("//appSettings");
try { if (node == null) throw new InvalidOperationException("appSettings section not found in config file."); else { node.RemoveChild(node.SelectSingleNode(string.Format("//add[@key='{0}']", key))); doc.Save(configFile); } } catch (NullReferenceException e) { throw new Exception(string.Format("The key {0} does not exist.", key), e); } }
private static XmlDocument loadConfigDocument() { XmlDocument doc = null; try { doc = new XmlDocument(); doc.Load(configFile); } catch (Exception e) { System.Windows.Forms.MessageBox.Show(e.Message); } return doc;
}
public static string getConfigFilePath() { string configFile=Assembly.GetExecutingAssembly().Location + ".config"; if (!File.Exists(configFile)) CreateFile(configFile); return configFile; }
public static bool ConfigFileExist() { string configFile=Assembly.GetExecutingAssembly().Location + ".config"; return File.Exists(configFile); }
private static void CreateFile(string FileName) { XmlTextWriter writer = new XmlTextWriter(FileName,System.Text.Encoding.Default); writer.WriteStartElement("configuration"); writer.WriteStartElement("appSettings"); writer.WriteEndElement() ; writer.Flush(); writer.Close(); } }
}
