为字符属性定义选项[web自定义控件]
当我们定义一个enum属性时,通过IDE的属性页能看到一个下拉的列表。能不能为一个字符属性也定义一个下拉列表呢?实现也不是很复杂,需要定义一个TypeConverter,看下面代码
上面的MyStrConfigurations是一个管理这个字符列表的类,主要使用其属性数组Names。先不管这个,看一下如何使用该类
过程就是上面的两步就可以了。
上面所说的MyStrConfigurations,我给他的任务是两个
1.添加默认的配置文件(Mystrings.xml)到网站的App_Data目录下。我原指望web.config,发现设计时读取几乎不可能。干脆自己定义一个配置文件。
2.读取网站app_data目录下的Mystrings.xml构造属性下拉列表。
读取项目所在目录,一般都使用下面的代码,代码思路是取项目被选中的项。注意当前打开的文件可能不是当前被选中的项
解决方案一般有几个项目,如果之前打开了一个设计的aspx,偶尔又选择并打开其他项目下的文件编辑,回到前面的aspx编辑时当前活动的文本对象就不是当前选中的项,路径就错了。能否取得当前活动文档对象的项目呢?通过宏编辑器尝试了不少的方法,结果发现以下代码简单可靠。是否有什么不足呢?
使用的方法, MyStrConfigurations类的静态方法GetConfig
public class MyStrTypeConverter : TypeConverter
{
public MyStrTypeConverter (){
}
private TypeConverter.StandardValuesCollection values;
public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) {
if (this.values == null)
{
MyStrConfigurations conf = MyStrConfigurations.GetConfig();
string[] arr = new string[conf.Names.Length];
for (int i = 0; i < arr.Length; i++)
arr[i] = conf.Names[i];
this.values = new TypeConverter.StandardValuesCollection(arr);
}
return this.values;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) {
return true;
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context) {
return true;
}
public override bool IsValid(ITypeDescriptorContext context, object value) {
if (value is string)
{
string str = (string)value;
MyStrConfigurations conf = MyStrConfigurations.GetConfig();
for (int i = 0; i < conf.AdTypes.Length; i++)
{
if (conf.Names[i] == str)
return true;
}
}
return false;
}
}
{
public MyStrTypeConverter (){
}
private TypeConverter.StandardValuesCollection values;
public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) {
if (this.values == null)
{
MyStrConfigurations conf = MyStrConfigurations.GetConfig();
string[] arr = new string[conf.Names.Length];
for (int i = 0; i < arr.Length; i++)
arr[i] = conf.Names[i];
this.values = new TypeConverter.StandardValuesCollection(arr);
}
return this.values;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) {
return true;
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context) {
return true;
}
public override bool IsValid(ITypeDescriptorContext context, object value) {
if (value is string)
{
string str = (string)value;
MyStrConfigurations conf = MyStrConfigurations.GetConfig();
for (int i = 0; i < conf.AdTypes.Length; i++)
{
if (conf.Names[i] == str)
return true;
}
}
return false;
}
}
上面的MyStrConfigurations是一个管理这个字符列表的类,主要使用其属性数组Names。先不管这个,看一下如何使用该类
private string mStrAdType;
[TypeConverter(typeof(MyStrTypeConverter))]
public string AdStrType{
get{return this.mStrAdType;}
set{this.mStrAdType = value;}
}
关键是定义属性的TypeConverter(typeof(MyStrTypeConverter))[TypeConverter(typeof(MyStrTypeConverter))]
public string AdStrType{
get{return this.mStrAdType;}
set{this.mStrAdType = value;}
}
过程就是上面的两步就可以了。
上面所说的MyStrConfigurations,我给他的任务是两个
1.添加默认的配置文件(Mystrings.xml)到网站的App_Data目录下。我原指望web.config,发现设计时读取几乎不可能。干脆自己定义一个配置文件。
2.读取网站app_data目录下的Mystrings.xml构造属性下拉列表。
读取项目所在目录,一般都使用下面的代码,代码思路是取项目被选中的项。注意当前打开的文件可能不是当前被选中的项
string path = "";
EnvDTE.DTE devenv = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.8.0");//vs2005. vs2003应是VisualStudio.DTE.7.1
Array projects = (System.Array)devenv.ActiveSolutionProjects;
if ((projects.Length == 0) || (projects.Length > 1))
{
//path = "Exactly one project must be active";
}
else
{
EnvDTE.Project project = (EnvDTE.Project)(projects.GetValue(0));
System.IO.FileInfo info = new System.IO.FileInfo(project.FullName);
path = info.Directory.FullName;
}
EnvDTE.DTE devenv = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.8.0");//vs2005. vs2003应是VisualStudio.DTE.7.1
Array projects = (System.Array)devenv.ActiveSolutionProjects;
if ((projects.Length == 0) || (projects.Length > 1))
{
//path = "Exactly one project must be active";
}
else
{
EnvDTE.Project project = (EnvDTE.Project)(projects.GetValue(0));
System.IO.FileInfo info = new System.IO.FileInfo(project.FullName);
path = info.Directory.FullName;
}
解决方案一般有几个项目,如果之前打开了一个设计的aspx,偶尔又选择并打开其他项目下的文件编辑,回到前面的aspx编辑时当前活动的文本对象就不是当前选中的项,路径就错了。能否取得当前活动文档对象的项目呢?通过宏编辑器尝试了不少的方法,结果发现以下代码简单可靠。是否有什么不足呢?
string path = "";
EnvDTE.DTE devenv = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.8.0");
System.IO.FileInfo info = new System.IO.FileInfo(devenv.ActiveDocument.ProjectItem.ContainingProject.FullName);
path = info.Directory.FullName;
EnvDTE.DTE devenv = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.8.0");
System.IO.FileInfo info = new System.IO.FileInfo(devenv.ActiveDocument.ProjectItem.ContainingProject.FullName);
path = info.Directory.FullName;
如何向站点输出默认的配置xml文件呢?
首先编辑默认的xml作为“嵌入的资源”作为控件库项目的一项内容发布
最后就是控件读取自身资源输出到项目指定目录下。以下是读取输出的一段代码,参考自http://www.codeproject.com/KB/custom-controls/MP3PlayerControl.aspx
/// <summary>
/// Writes Flash File from assembly resources
/// </summary>
/// <param name="FilePath">Directory Path to flash file</param>
/// <param name="FileName">Flash file name</param>
/// <param name="AssemblyReference">Reference to assembly with resource file</param>
/// <param name="ResourceName">Name of resource to write to file</param>
/// <param name="OverWrite">Whether method should overwrite existing file if detected</param>
private static void FileFromResource(string FilePath, string FileName, Assembly AssemblyReference, string ResourceName, bool OverWrite)
{
//Only write file if it's not already there
if (!File.Exists(FilePath + FileName) || OverWrite)
{
//Create Destination Directory if not in existence
DirectoryInfo DirInfo = new DirectoryInfo(FilePath);
if (!DirInfo.Exists)
{
Directory.CreateDirectory(FilePath);
}
//Create Stream from Resource in Assembly
Stream InputStream = AssemblyReference.GetManifestResourceStream(ResourceName);
BinaryReader Reader = new BinaryReader(InputStream);
FileStream OutputStream = new FileStream(FilePath + FileName, FileMode.Create);
BinaryWriter Writer = new BinaryWriter(OutputStream);
//Read through stream and write to file
bool LoopRead = true;
try
{
while (LoopRead)
{
byte NextByte = Reader.ReadByte();
if (Convert.ToInt32(NextByte) == -1)
{
LoopRead = false;
}
OutputStream.WriteByte(NextByte);
}
}
catch
{
//Catch exception when end of stream is reached and close all streams
InputStream.Close();
OutputStream.Close();
Reader.Close();
Writer.Close();
}
}
}
/// Writes Flash File from assembly resources
/// </summary>
/// <param name="FilePath">Directory Path to flash file</param>
/// <param name="FileName">Flash file name</param>
/// <param name="AssemblyReference">Reference to assembly with resource file</param>
/// <param name="ResourceName">Name of resource to write to file</param>
/// <param name="OverWrite">Whether method should overwrite existing file if detected</param>
private static void FileFromResource(string FilePath, string FileName, Assembly AssemblyReference, string ResourceName, bool OverWrite)
{
//Only write file if it's not already there
if (!File.Exists(FilePath + FileName) || OverWrite)
{
//Create Destination Directory if not in existence
DirectoryInfo DirInfo = new DirectoryInfo(FilePath);
if (!DirInfo.Exists)
{
Directory.CreateDirectory(FilePath);
}
//Create Stream from Resource in Assembly
Stream InputStream = AssemblyReference.GetManifestResourceStream(ResourceName);
BinaryReader Reader = new BinaryReader(InputStream);
FileStream OutputStream = new FileStream(FilePath + FileName, FileMode.Create);
BinaryWriter Writer = new BinaryWriter(OutputStream);
//Read through stream and write to file
bool LoopRead = true;
try
{
while (LoopRead)
{
byte NextByte = Reader.ReadByte();
if (Convert.ToInt32(NextByte) == -1)
{
LoopRead = false;
}
OutputStream.WriteByte(NextByte);
}
}
catch
{
//Catch exception when end of stream is reached and close all streams
InputStream.Close();
OutputStream.Close();
Reader.Close();
Writer.Close();
}
}
}
使用的方法, MyStrConfigurations类的静态方法GetConfig
public static MyStrConfigurations GetConfig()
{
string strProPath = getProjectPath();
string strPath = string.Format("{0}\\App_Data\\MyStrings.xml", strProPath);
//检查文件是否存在,不存在时读取dll中的资源文件输出
System.IO.FileInfo info = new FileInfo(strPath);
if (!info.Exists)
{
if (!info.Directory.Exists)
info.Directory.Create();
Assembly assemblyReference = Assembly.GetExecutingAssembly();
FileFromResource(strProPath + "\\App_Data\\", "MyStrings.xml", assemblyReference, "Kvn.Web.UI.Controls.MyStrings.xml", true);
}
//通过xml反序化为配置对象
object obj = null;
System.IO.StreamReader read = null;
try
{
read = new System.IO.StreamReader(strPath);
//读取字符串
XmlSerializer ser = new XmlSerializer(typeof(MyStrConfigurations));
obj = ser.Deserialize(read);
}
catch (Exception ee)
{
throw ee;
}
finally
{
if(read!=null)
read.Close();
}
MyStrConfigurations cf= (MyStrConfigurations)obj;
cf.WorkProject = strProPath;
return cf;
}
{
string strProPath = getProjectPath();
string strPath = string.Format("{0}\\App_Data\\MyStrings.xml", strProPath);
//检查文件是否存在,不存在时读取dll中的资源文件输出
System.IO.FileInfo info = new FileInfo(strPath);
if (!info.Exists)
{
if (!info.Directory.Exists)
info.Directory.Create();
Assembly assemblyReference = Assembly.GetExecutingAssembly();
FileFromResource(strProPath + "\\App_Data\\", "MyStrings.xml", assemblyReference, "Kvn.Web.UI.Controls.MyStrings.xml", true);
}
//通过xml反序化为配置对象
object obj = null;
System.IO.StreamReader read = null;
try
{
read = new System.IO.StreamReader(strPath);
//读取字符串
XmlSerializer ser = new XmlSerializer(typeof(MyStrConfigurations));
obj = ser.Deserialize(read);
}
catch (Exception ee)
{
throw ee;
}
finally
{
if(read!=null)
read.Close();
}
MyStrConfigurations cf= (MyStrConfigurations)obj;
cf.WorkProject = strProPath;
return cf;
}