还有就是如果我在窗体上创建这个定义的TextBox的一个实例,并在属性窗口的WaterMark属性上右击选"重置",再按F5,一定会出现下图的错误消息:
同时,属性窗口中WaterMark前面的+号也消失,不会再出现里面的Text和Color属性
下观是节选的部分代码:
//
//自定义的TextBox中WaterMark属性的定义
//
static object WaterMarkChangedEvent = new object();
/// <summary>
/// 当WaterMark属性更改时触发.
/// </summary>
public event EventHandler WaterMarkChanged
{
add { Events.AddHandler(WaterMarkChangedEvent, value); }
remove { Events.RemoveHandler(WaterMarkChangedEvent, value); }
}
WaterMarkStyle waterMark = new WaterMarkStyle("",SystemColors.GrayText);
/// <summary>
/// 获取或设置控件的水印效果.
/// </summary>
[DefaultValue(typeof(WaterMarkStyle),"")]
[Browsable(true)]
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark==value) return ;
waterMark = value;
OnWaterMarkChanged(EventArgs.Empty);
}
}
//... ...
//
//WaterMarkStyle类型定义
//
/// <summary>
/// 可编辑控件的水印样式
/// </summary>
[TypeConverter(typeof(WaterMarkStyleTypeConverter))]
[ComVisible(true)]
[Serializable]
public struct WaterMarkStyle
{
string text;
Color color;
/// <summary>
/// 获取或设置水印文本.
/// </summary>
[DefaultValue("")]
public string Text
{
get { return text; }
set
{
if (text == value) return;
text = value;
}
}
/// <summary>
/// 获取或设置水印颜色.
/// </summary>
[DefaultValue(typeof(Color),"GrayText")]
public Color Color
{
get { return color; }
set
{
if (color==value) return ;
color = value;
}
}
/// <summary>
/// 重写父类的判等方法.
/// </summary>
/// <param name="obj">与当前实例比较的目标对象</param>
/// <returns>如果两个对象相等则返回true,否则返回false.</returns>
public override bool Equals(object obj)
{
if (obj == null || !(obj is WaterMarkStyle)) return false;
WaterMarkStyle wms = (WaterMarkStyle)obj;
return this.text == wms.text && this.color == wms.color;
}
/// <summary>
/// 获取类型当前实例的哈希码.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return this.text.GetHashCode() ^ this.color.GetHashCode();
}
/// <summary>
/// 获取类型当前实例的文本值.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return this.text;
}
/// <summary>
/// 判断给定两个参数是否相等
/// </summary>
/// <param name="wm1"></param>
/// <param name="wm2"></param>
/// <returns></returns>
public static bool operator ==(WaterMarkStyle wm1,WaterMarkStyle wm2)
{
if (wm1==null ^wm2==null)
{
return false;
}
return wm1.text == wm2.text && wm1.color.ToArgb() == wm2.color.ToArgb();
}
/// <summary>
/// 判断给定两个参数是否不等.
/// </summary>
/// <param name="wm1"></param>
/// <param name="wm2"></param>
/// <returns></returns>
public static bool operator !=(WaterMarkStyle wm1, WaterMarkStyle wm2)
{
if (wm1 == null ^ wm2 == null)
{
return true;
}
return wm1.text != wm2.text || wm1.color.ToArgb() != wm2.color.ToArgb();
}
/// <summary>
/// 根据给定的文本和文本颜色,构造当前类型实例.
/// </summary>
/// <param name="text"></param>
/// <param name="color"></param>
public WaterMarkStyle(string text,Color color):this()
{
this.text = text;
this.color = color;
}
/// <summary>
/// 根据给定的文本和默认颜色,构造当前类型实例.
/// </summary>
/// <param name="text"></param>
public WaterMarkStyle(string text) : this()
{
this.text = text;
this.color =SystemColors.GrayText;
}
}
//类型转换器
class WaterMarkStyleTypeConverter:TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType==typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType ==typeof( InstanceDescriptor) || base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value != null)// return new WaterMarkStyle("",SystemColors.GrayText);// throw new ArgumentNullException("value");
{
if (value is string)
{
WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
if (obj == null || obj.Color == Color.Empty)
{
return new WaterMarkStyle(value.ToString(), SystemColors.GrayText);
}
return new WaterMarkStyle(value.ToString(), obj.Color);
}
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType==null)
{
throw new ArgumentNullException("destinationType");
}
if (value != null)
{
WaterMarkStyle wms = (WaterMarkStyle)value;
if (destinationType == typeof(string))
{
return wms.Text;
}
if (destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ctor = typeof(WaterMarkStyle).GetConstructor(new Type[] { typeof(string), typeof(Color) });
if (ctor != null)
{
return new InstanceDescriptor(ctor, new object[] { wms.Text, wms.Color });
}
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return TypeDescriptor.GetProperties(typeof(WaterMarkStyle), attributes).Sort(new string[] { "Text", "Color" });
}
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
{
if (propertyValues == null)
{
throw new ArgumentNullException("propertyValues");
}
object obj2 = propertyValues["Text"];
object obj3 = propertyValues["Color"];
if (((obj2 == null) || (obj3 == null)) || (!(obj2 is string) || !(obj3 is Color)))
{
throw new ArgumentException("无效属性值!");
}
return new WaterMarkStyle(obj2 as string, (Color)obj3);
}
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}
}
以上是水印样式的类型定义及类型转换器的定义.请高手们给看下,如果还需要其他的代码我再往上加!
16 个解决方案
#1
先站个沙发,顶~
#2
已经说得很清楚了 :未将对象设置到对象的实例,所设置的变量为空值或没有取到值,一般出现在传递参数的时候出现这个问题, waterMark = value;
看看值有没有,另外 :控件名称与codebehind里面的没有对应,
解决方法:
(1)使用try..catch...finally捕捉错误,或直接用response.write()输出所取的变量值
(2)查看代码中是否存在未初始化的变量
看看值有没有,另外 :控件名称与codebehind里面的没有对应,
解决方法:
(1)使用try..catch...finally捕捉错误,或直接用response.write()输出所取的变量值
(2)查看代码中是否存在未初始化的变量
#3
功能简单一点的可以直接用ExpandableObjectConverter。
如果要添加一些功能,象字符串转换,以及生成好看一些的代码,则可以提供自定义的TypeConverter:
public class MyTextBox : TextBox
{
WaterMarkStyle waterMark = new WaterMarkStyle("", SystemColors.GrayText);
/// <summary>
/// 获取或设置控件的水印效果.
/// </summary>
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark != value)
{
waterMark = value;
}
}
}
/// <summary>
/// 可编辑控件的水印样式
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))] //<---
public class WaterMarkStyle
{
public WaterMarkStyle() : this("", SystemColors.GrayText)
{
}
public WaterMarkStyle(string text, Color color)
{
this.Text = text;
this.Color = color;
}
/// <summary> 获取或设置水印文本. </summary>
public string Text { get; set;}
/// <summary> 获取或设置水印颜色. </summary>
public Color Color {get; set;}
#region 重写判等方法
public override bool Equals(object obj)
{
return this == (obj as WaterMarkStyle);
}
public override int GetHashCode()
{
return (this.Text ?? "").GetHashCode() ^ this.Color.GetHashCode();
}
public override string ToString()
{
return this.Text;
}
public static bool operator ==(WaterMarkStyle wm1, WaterMarkStyle wm2)
{
if (object.ReferenceEquals(wm1, null) || object.ReferenceEquals(wm2, null) )
{
return object.ReferenceEquals(wm1, wm2);
}
return wm1.Text == wm2.Text && wm1.Color == wm2.Color;
}
public static bool operator !=(WaterMarkStyle wm1, WaterMarkStyle wm2)
{
return !(wm1 == wm2);
}
#endregion
}
}
}
如果要添加一些功能,象字符串转换,以及生成好看一些的代码,则可以提供自定义的TypeConverter:
private class WaterMarkStyleTypeConverter : ExpandableObjectConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
Color color = SystemColors.GrayText;
if (context != null && context.Instance != null && context.PropertyDescriptor != null)
{
WaterMarkStyle old = context.PropertyDescriptor.GetValue(context.Instance) as WaterMarkStyle;
if (old != null && old.Color != SystemColors.GrayText) color = old.Color;
}
return new WaterMarkStyle((string)value, color);
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (value is WaterMarkStyle && destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ctor = typeof(WaterMarkStyle).GetConstructor(new Type[] { typeof(string), typeof(Color) });
if (ctor != null)
{
WaterMarkStyle wms = (WaterMarkStyle)value;
return new InstanceDescriptor(ctor, new object[] { wms.Text, wms.Color });
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
#4
#5
应该先判断一下OnWaterMarkChanged是否为空:
/// <summary>
/// 获取或设置控件的水印效果.
/// </summary>
[DefaultValue(typeof(WaterMarkStyle),"")]
[Browsable(true)]
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark==value) return ;
waterMark = value;
if(OnWaterMarkChanged != null)
OnWaterMarkChanged(EventArgs.Empty);
}
}
#6
是个办法
调试,看具体是那个地方出现了问题
#7
LZ为了你的1点过发帖的工作精神 先帮顶一个来
#8
LZ这是我以前做的水印图片
这是生成验证码
-----------------------
--------------------
这是水印
--------
这是生成验证码
-----------------------
/**
* IRequiresSessionState是一个空接口,仅用来
* 标记handler是否对session拥有读写权
*/
public void ProcessRequest(HttpContext context)
{
//1、建立画板
Bitmap bitmap = new Bitmap(80, 30);
//2、建立画布(绘图类)
Graphics g = Graphics.FromImage(bitmap);
//3、填充画布
g.FillRectangle(Brushes.White, 0, 0, 80, 30);
//4、设置字体
Font f = new Font("隶书", 16);
//5、在画布上写入字符
string letters = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
//6、定义变量,接受生成的随机字符串
StringBuilder sb = new StringBuilder();
//7、取字符
Random r=new Random();
//接受生成的单个随机字符
string result = string.Empty;
for (int i = 0; i < 4; i++)
{
result=letters.Substring(r.Next(0, letters.Length - 1), 1);
sb.Append(result);
g.DrawString(result, f, Brushes.Red, i * 15, r.Next(0, 10));
}
//8、输出到响应流
context.Response.ContentType = "image/Jpg";
bitmap.Save(context.Response.OutputStream, ImageFormat.Jpeg);
//9、保存随机字符串到session
context.Session["yanzheng"] = sb.ToString();
//释放资源
bitmap.Dispose();
g.Dispose();
context.Response.End();
}
--------------------
这是水印
--------
public void ProcessRequest(HttpContext context)
{
string path = context.Request.PhysicalPath;
if (File.Exists(path))
{
System.Drawing.Image image = Image.FromFile(path);
Graphics g = Graphics.FromImage(image);
Font f = new Font("楷体", 12);
g.DrawString("水印", f, Brushes.Red, 0, 0);
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
g.Dispose();
image.Dispose();
context.Response.End();
}
}
#9
这是上传的图片
protected void btnUpload_Click(object sender, EventArgs e)
{
//获取图片路径
string filePath = this.fuplImg.PostedFile.FileName;
//获取文件名
string fileName = this.fuplImg.FileName;
//获取扩展名
FileInfo info = new FileInfo(fileName);
string type = info.Extension;
//判断图片类型是否允许上传
if (type == ".jpg" || type == ".bmp" || type == ".gif")
{
//获取图片存储位置的物理路径
string path = Server.MapPath("Images//" + fileName);
//上传保存
this.fuplImg.PostedFile.SaveAs(path);
//加载图片
Image imgFile = new Image();
imgFile.Width = 200;
imgFile.Height = 150;
imgFile.ImageUrl = @"~/Images/" + fileName;
this.imgDiv.Controls.Add(imgFile);
Page.ClientScript.RegisterStartupScript(typeof(Page), "", "alert('上传成功!')", true);
}
else
{
Page.ClientScript.RegisterStartupScript(typeof(Page), "", "alert('请检查上传图片的格式!')", true);
}
}
#10
楼主这种错误就是传参数的时候出的错误
再传参数的时候都加个判断就可以了
再传参数的时候都加个判断就可以了
#11
同意这个看法,其他人的回复都是答非所问。
我在使用自定义事件的时候,都会加上是否为null的判断,所以从未出现过问题,这是个好习惯,任何可能出现null的地方,在使用前都要加为空判断。也许VS2008的编译机制和VS2010不一样了,导致你移植到VS2010去就报错。
#12
首先谢谢大家的热情参与和讨论,下面我再说几点:
1.关于事件检查为空的问题,是在OnWaterMarkChanged这个方法内部进行的:
protected virtual void OnWaterMarkChanged(EventArgs e)
{
EventHandler handle=Events[MaterMarkChangedEvent] as EventHandler;
if(handle!=null && handle.GetInvokedList().Length>0)
{
... ...
}
}
2.关于加try块调试,单从表面上看,错误的信息比较具体,但我可以比较确定的是和转换器的实现有很大关系,也就是说这个错误是在设计时支持里的,调试起来比较困难,因为你根本没法逐步的去调试,就算加上了Try块,我也不知道设计器会在什么时候执行这段代码并抛出异常.
3.说下目前的情况吧,其他的都差不多了,就还剩下一个问题,就是我设置了WaterMark属性后,F5运行,没有任何问题,包括后台自动生成的代码也可以了,但是我在这个属性上右击选"重置"后,就会出现上面图片上所示的错误,
理解是好理解,因为重置后WaterMark属性为空了呗,但我想知道,这个属性初始化定义的时候我是给了他值的,并且也使用了DefaultValueAttribute设置的默认值,就是空字符串,经过转换器后这个空串也应该被转换为一个空文本和GrayText颜色的WaterMarkStyle对象才对呀,怎么它就成了Null了呢?
最后感谢一下zyloveyrf吧,因为我这个是WinForm的,不是Web,所谓的这个水印效果就是当文本框 没有文本且没有焦点是时候在上面显示一个提示文本,如果输入的内容或获取地焦点,则不显示
这个问题能解决与否都没关系,希望大家都讨论一下!如果有不明白的请留言!
1.关于事件检查为空的问题,是在OnWaterMarkChanged这个方法内部进行的:
protected virtual void OnWaterMarkChanged(EventArgs e)
{
EventHandler handle=Events[MaterMarkChangedEvent] as EventHandler;
if(handle!=null && handle.GetInvokedList().Length>0)
{
... ...
}
}
2.关于加try块调试,单从表面上看,错误的信息比较具体,但我可以比较确定的是和转换器的实现有很大关系,也就是说这个错误是在设计时支持里的,调试起来比较困难,因为你根本没法逐步的去调试,就算加上了Try块,我也不知道设计器会在什么时候执行这段代码并抛出异常.
3.说下目前的情况吧,其他的都差不多了,就还剩下一个问题,就是我设置了WaterMark属性后,F5运行,没有任何问题,包括后台自动生成的代码也可以了,但是我在这个属性上右击选"重置"后,就会出现上面图片上所示的错误,
理解是好理解,因为重置后WaterMark属性为空了呗,但我想知道,这个属性初始化定义的时候我是给了他值的,并且也使用了DefaultValueAttribute设置的默认值,就是空字符串,经过转换器后这个空串也应该被转换为一个空文本和GrayText颜色的WaterMarkStyle对象才对呀,怎么它就成了Null了呢?
最后感谢一下zyloveyrf吧,因为我这个是WinForm的,不是Web,所谓的这个水印效果就是当文本框 没有文本且没有焦点是时候在上面显示一个提示文本,如果输入的内容或获取地焦点,则不显示
这个问题能解决与否都没关系,希望大家都讨论一下!如果有不明白的请留言!
#13
你的转换器写错了,问题应该在这段代码,自己调试去:
这句:WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
ConvertFrom方法是用来将你的空字符串翻译到那个WaterMarkStyle 结构(注意,结构体不可能为空),你并未使用外部给的字符串来转换内部结构,而是用了自己的值来转换。if(obj == null)这个判断永不成立,当然,之前如果就是null的话WaterMarkStyle obj = ...这步就会报错,无法将null转换为WaterMarkStyle结构体,如果是类,不会报错,但是你这个是结构体,没有为null的结构体。
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value != null)// return new WaterMarkStyle("",SystemColors.GrayText);// throw new ArgumentNullException("value");
{
if (value is string)
{
WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
if (obj == null || obj.Color == Color.Empty)
{
return new WaterMarkStyle(value.ToString(), SystemColors.GrayText);
}
return new WaterMarkStyle(value.ToString(), obj.Color);
}
}
return base.ConvertFrom(context, culture, value);
}
这句:WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
ConvertFrom方法是用来将你的空字符串翻译到那个WaterMarkStyle 结构(注意,结构体不可能为空),你并未使用外部给的字符串来转换内部结构,而是用了自己的值来转换。if(obj == null)这个判断永不成立,当然,之前如果就是null的话WaterMarkStyle obj = ...这步就会报错,无法将null转换为WaterMarkStyle结构体,如果是类,不会报错,但是你这个是结构体,没有为null的结构体。
#14
你原先代码是转换器ConvertFrom里有问题:
WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor...
我在3楼的代码,如果要支持重置,则WaterMarkStyle类不能是MyText的内嵌类(不知道Vistual Studio编辑器为什么要挑剔这个),要单独出来。
[DefaultValue(typeof(WaterMarkStyle), "")]
public WaterMarkStyle WaterMark
{
get { return waterMark; }
...
WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor...
我在3楼的代码,如果要支持重置,则WaterMarkStyle类不能是MyText的内嵌类(不知道Vistual Studio编辑器为什么要挑剔这个),要单独出来。
[DefaultValue(typeof(WaterMarkStyle), "")]
public WaterMarkStyle WaterMark
{
get { return waterMark; }
...
#15
设置一个属性值就ok了
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark != value)
{
waterMark = value;
}
}
}
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark != value)
{
waterMark = value;
}
}
}
#16
谢谢qldsrx和gomoku了
的确是这样,问题的确就出在WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
因为重置后,TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
得到值为空,此处会引发异常,由于ConvertFrom方法没有返回值,所以会提示一个空引用的异常.
的确是这样,问题的确就出在WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
因为重置后,TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
得到值为空,此处会引发异常,由于ConvertFrom方法没有返回值,所以会提示一个空引用的异常.
#1
先站个沙发,顶~
#2
已经说得很清楚了 :未将对象设置到对象的实例,所设置的变量为空值或没有取到值,一般出现在传递参数的时候出现这个问题, waterMark = value;
看看值有没有,另外 :控件名称与codebehind里面的没有对应,
解决方法:
(1)使用try..catch...finally捕捉错误,或直接用response.write()输出所取的变量值
(2)查看代码中是否存在未初始化的变量
看看值有没有,另外 :控件名称与codebehind里面的没有对应,
解决方法:
(1)使用try..catch...finally捕捉错误,或直接用response.write()输出所取的变量值
(2)查看代码中是否存在未初始化的变量
#3
功能简单一点的可以直接用ExpandableObjectConverter。
如果要添加一些功能,象字符串转换,以及生成好看一些的代码,则可以提供自定义的TypeConverter:
public class MyTextBox : TextBox
{
WaterMarkStyle waterMark = new WaterMarkStyle("", SystemColors.GrayText);
/// <summary>
/// 获取或设置控件的水印效果.
/// </summary>
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark != value)
{
waterMark = value;
}
}
}
/// <summary>
/// 可编辑控件的水印样式
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))] //<---
public class WaterMarkStyle
{
public WaterMarkStyle() : this("", SystemColors.GrayText)
{
}
public WaterMarkStyle(string text, Color color)
{
this.Text = text;
this.Color = color;
}
/// <summary> 获取或设置水印文本. </summary>
public string Text { get; set;}
/// <summary> 获取或设置水印颜色. </summary>
public Color Color {get; set;}
#region 重写判等方法
public override bool Equals(object obj)
{
return this == (obj as WaterMarkStyle);
}
public override int GetHashCode()
{
return (this.Text ?? "").GetHashCode() ^ this.Color.GetHashCode();
}
public override string ToString()
{
return this.Text;
}
public static bool operator ==(WaterMarkStyle wm1, WaterMarkStyle wm2)
{
if (object.ReferenceEquals(wm1, null) || object.ReferenceEquals(wm2, null) )
{
return object.ReferenceEquals(wm1, wm2);
}
return wm1.Text == wm2.Text && wm1.Color == wm2.Color;
}
public static bool operator !=(WaterMarkStyle wm1, WaterMarkStyle wm2)
{
return !(wm1 == wm2);
}
#endregion
}
}
}
如果要添加一些功能,象字符串转换,以及生成好看一些的代码,则可以提供自定义的TypeConverter:
private class WaterMarkStyleTypeConverter : ExpandableObjectConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
Color color = SystemColors.GrayText;
if (context != null && context.Instance != null && context.PropertyDescriptor != null)
{
WaterMarkStyle old = context.PropertyDescriptor.GetValue(context.Instance) as WaterMarkStyle;
if (old != null && old.Color != SystemColors.GrayText) color = old.Color;
}
return new WaterMarkStyle((string)value, color);
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (value is WaterMarkStyle && destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ctor = typeof(WaterMarkStyle).GetConstructor(new Type[] { typeof(string), typeof(Color) });
if (ctor != null)
{
WaterMarkStyle wms = (WaterMarkStyle)value;
return new InstanceDescriptor(ctor, new object[] { wms.Text, wms.Color });
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
#4
#5
应该先判断一下OnWaterMarkChanged是否为空:
/// <summary>
/// 获取或设置控件的水印效果.
/// </summary>
[DefaultValue(typeof(WaterMarkStyle),"")]
[Browsable(true)]
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark==value) return ;
waterMark = value;
if(OnWaterMarkChanged != null)
OnWaterMarkChanged(EventArgs.Empty);
}
}
#6
是个办法
调试,看具体是那个地方出现了问题
#7
LZ为了你的1点过发帖的工作精神 先帮顶一个来
#8
LZ这是我以前做的水印图片
这是生成验证码
-----------------------
--------------------
这是水印
--------
这是生成验证码
-----------------------
/**
* IRequiresSessionState是一个空接口,仅用来
* 标记handler是否对session拥有读写权
*/
public void ProcessRequest(HttpContext context)
{
//1、建立画板
Bitmap bitmap = new Bitmap(80, 30);
//2、建立画布(绘图类)
Graphics g = Graphics.FromImage(bitmap);
//3、填充画布
g.FillRectangle(Brushes.White, 0, 0, 80, 30);
//4、设置字体
Font f = new Font("隶书", 16);
//5、在画布上写入字符
string letters = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
//6、定义变量,接受生成的随机字符串
StringBuilder sb = new StringBuilder();
//7、取字符
Random r=new Random();
//接受生成的单个随机字符
string result = string.Empty;
for (int i = 0; i < 4; i++)
{
result=letters.Substring(r.Next(0, letters.Length - 1), 1);
sb.Append(result);
g.DrawString(result, f, Brushes.Red, i * 15, r.Next(0, 10));
}
//8、输出到响应流
context.Response.ContentType = "image/Jpg";
bitmap.Save(context.Response.OutputStream, ImageFormat.Jpeg);
//9、保存随机字符串到session
context.Session["yanzheng"] = sb.ToString();
//释放资源
bitmap.Dispose();
g.Dispose();
context.Response.End();
}
--------------------
这是水印
--------
public void ProcessRequest(HttpContext context)
{
string path = context.Request.PhysicalPath;
if (File.Exists(path))
{
System.Drawing.Image image = Image.FromFile(path);
Graphics g = Graphics.FromImage(image);
Font f = new Font("楷体", 12);
g.DrawString("水印", f, Brushes.Red, 0, 0);
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
g.Dispose();
image.Dispose();
context.Response.End();
}
}
#9
这是上传的图片
protected void btnUpload_Click(object sender, EventArgs e)
{
//获取图片路径
string filePath = this.fuplImg.PostedFile.FileName;
//获取文件名
string fileName = this.fuplImg.FileName;
//获取扩展名
FileInfo info = new FileInfo(fileName);
string type = info.Extension;
//判断图片类型是否允许上传
if (type == ".jpg" || type == ".bmp" || type == ".gif")
{
//获取图片存储位置的物理路径
string path = Server.MapPath("Images//" + fileName);
//上传保存
this.fuplImg.PostedFile.SaveAs(path);
//加载图片
Image imgFile = new Image();
imgFile.Width = 200;
imgFile.Height = 150;
imgFile.ImageUrl = @"~/Images/" + fileName;
this.imgDiv.Controls.Add(imgFile);
Page.ClientScript.RegisterStartupScript(typeof(Page), "", "alert('上传成功!')", true);
}
else
{
Page.ClientScript.RegisterStartupScript(typeof(Page), "", "alert('请检查上传图片的格式!')", true);
}
}
#10
楼主这种错误就是传参数的时候出的错误
再传参数的时候都加个判断就可以了
再传参数的时候都加个判断就可以了
#11
同意这个看法,其他人的回复都是答非所问。
我在使用自定义事件的时候,都会加上是否为null的判断,所以从未出现过问题,这是个好习惯,任何可能出现null的地方,在使用前都要加为空判断。也许VS2008的编译机制和VS2010不一样了,导致你移植到VS2010去就报错。
#12
首先谢谢大家的热情参与和讨论,下面我再说几点:
1.关于事件检查为空的问题,是在OnWaterMarkChanged这个方法内部进行的:
protected virtual void OnWaterMarkChanged(EventArgs e)
{
EventHandler handle=Events[MaterMarkChangedEvent] as EventHandler;
if(handle!=null && handle.GetInvokedList().Length>0)
{
... ...
}
}
2.关于加try块调试,单从表面上看,错误的信息比较具体,但我可以比较确定的是和转换器的实现有很大关系,也就是说这个错误是在设计时支持里的,调试起来比较困难,因为你根本没法逐步的去调试,就算加上了Try块,我也不知道设计器会在什么时候执行这段代码并抛出异常.
3.说下目前的情况吧,其他的都差不多了,就还剩下一个问题,就是我设置了WaterMark属性后,F5运行,没有任何问题,包括后台自动生成的代码也可以了,但是我在这个属性上右击选"重置"后,就会出现上面图片上所示的错误,
理解是好理解,因为重置后WaterMark属性为空了呗,但我想知道,这个属性初始化定义的时候我是给了他值的,并且也使用了DefaultValueAttribute设置的默认值,就是空字符串,经过转换器后这个空串也应该被转换为一个空文本和GrayText颜色的WaterMarkStyle对象才对呀,怎么它就成了Null了呢?
最后感谢一下zyloveyrf吧,因为我这个是WinForm的,不是Web,所谓的这个水印效果就是当文本框 没有文本且没有焦点是时候在上面显示一个提示文本,如果输入的内容或获取地焦点,则不显示
这个问题能解决与否都没关系,希望大家都讨论一下!如果有不明白的请留言!
1.关于事件检查为空的问题,是在OnWaterMarkChanged这个方法内部进行的:
protected virtual void OnWaterMarkChanged(EventArgs e)
{
EventHandler handle=Events[MaterMarkChangedEvent] as EventHandler;
if(handle!=null && handle.GetInvokedList().Length>0)
{
... ...
}
}
2.关于加try块调试,单从表面上看,错误的信息比较具体,但我可以比较确定的是和转换器的实现有很大关系,也就是说这个错误是在设计时支持里的,调试起来比较困难,因为你根本没法逐步的去调试,就算加上了Try块,我也不知道设计器会在什么时候执行这段代码并抛出异常.
3.说下目前的情况吧,其他的都差不多了,就还剩下一个问题,就是我设置了WaterMark属性后,F5运行,没有任何问题,包括后台自动生成的代码也可以了,但是我在这个属性上右击选"重置"后,就会出现上面图片上所示的错误,
理解是好理解,因为重置后WaterMark属性为空了呗,但我想知道,这个属性初始化定义的时候我是给了他值的,并且也使用了DefaultValueAttribute设置的默认值,就是空字符串,经过转换器后这个空串也应该被转换为一个空文本和GrayText颜色的WaterMarkStyle对象才对呀,怎么它就成了Null了呢?
最后感谢一下zyloveyrf吧,因为我这个是WinForm的,不是Web,所谓的这个水印效果就是当文本框 没有文本且没有焦点是时候在上面显示一个提示文本,如果输入的内容或获取地焦点,则不显示
这个问题能解决与否都没关系,希望大家都讨论一下!如果有不明白的请留言!
#13
你的转换器写错了,问题应该在这段代码,自己调试去:
这句:WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
ConvertFrom方法是用来将你的空字符串翻译到那个WaterMarkStyle 结构(注意,结构体不可能为空),你并未使用外部给的字符串来转换内部结构,而是用了自己的值来转换。if(obj == null)这个判断永不成立,当然,之前如果就是null的话WaterMarkStyle obj = ...这步就会报错,无法将null转换为WaterMarkStyle结构体,如果是类,不会报错,但是你这个是结构体,没有为null的结构体。
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value != null)// return new WaterMarkStyle("",SystemColors.GrayText);// throw new ArgumentNullException("value");
{
if (value is string)
{
WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
if (obj == null || obj.Color == Color.Empty)
{
return new WaterMarkStyle(value.ToString(), SystemColors.GrayText);
}
return new WaterMarkStyle(value.ToString(), obj.Color);
}
}
return base.ConvertFrom(context, culture, value);
}
这句:WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
ConvertFrom方法是用来将你的空字符串翻译到那个WaterMarkStyle 结构(注意,结构体不可能为空),你并未使用外部给的字符串来转换内部结构,而是用了自己的值来转换。if(obj == null)这个判断永不成立,当然,之前如果就是null的话WaterMarkStyle obj = ...这步就会报错,无法将null转换为WaterMarkStyle结构体,如果是类,不会报错,但是你这个是结构体,没有为null的结构体。
#14
你原先代码是转换器ConvertFrom里有问题:
WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor...
我在3楼的代码,如果要支持重置,则WaterMarkStyle类不能是MyText的内嵌类(不知道Vistual Studio编辑器为什么要挑剔这个),要单独出来。
[DefaultValue(typeof(WaterMarkStyle), "")]
public WaterMarkStyle WaterMark
{
get { return waterMark; }
...
WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor...
我在3楼的代码,如果要支持重置,则WaterMarkStyle类不能是MyText的内嵌类(不知道Vistual Studio编辑器为什么要挑剔这个),要单独出来。
[DefaultValue(typeof(WaterMarkStyle), "")]
public WaterMarkStyle WaterMark
{
get { return waterMark; }
...
#15
设置一个属性值就ok了
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark != value)
{
waterMark = value;
}
}
}
public WaterMarkStyle WaterMark
{
get { return waterMark; }
set
{
if (waterMark != value)
{
waterMark = value;
}
}
}
#16
谢谢qldsrx和gomoku了
的确是这样,问题的确就出在WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
因为重置后,TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
得到值为空,此处会引发异常,由于ConvertFrom方法没有返回值,所以会提示一个空引用的异常.
的确是这样,问题的确就出在WaterMarkStyle obj = (WaterMarkStyle)TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
因为重置后,TypeDescriptor.GetProperties(typeof(TextBox))["WaterMark"].GetValue(context.Instance);
得到值为空,此处会引发异常,由于ConvertFrom方法没有返回值,所以会提示一个空引用的异常.