最近,由于项目的需要,我制作了一个叫xMinTime的控件,该控件主要用于可选择时、分来设置时间,对于时分的获取与设置,使用一个属性叫HourMinute的自定义的结构体实现,其中xMinTime的控件界面如下:
HourMinute结构体的成员主要有Hour和Minute类型均为int,分别表示时、分,该结构体的定义参考了MSDN中关于在PropertyGrid中显示结构体成员的类的定义方法,并且实现了从TypeConverter接口继承的HourMinuteConverter的类,用于做HourMinute与其它类型之间的转换(主要是与格式为:"{0},{1}"的string之间的转换),这两个主要的类型定义完成后,按MSDN上的说法,应该就可以了,但是对这个HourMinute的使用却不顺利,主要问题是:
当xMinTime控件拉到窗体上时,对其HourMinute属性的初始化的代码如下:
this.xMinTime1.HourMinute = ((Test.PublicModel.HourMinute)(resources.GetObject("xMinTime1.HourMinute")));
但就我的理解,它应该写成:
this.xMinTime1.HourMinute = new HourMinute(0, 0);
上述的这种初始化的方式,如果在设计器中修改xMinTime控件的HourMinute属性的值时,有些场合下,会导致资源文件(*.resx)出错,请高手帮忙看看,成分感谢。
完整的项目代码(vs2010版)请从下面的百度网盘下载:
链接:https://pan.baidu.com/s/1rgHOcdt_ActT_3QFXXjB8w
提取码:k8dr
附: HourMinute.cs的代码如下:
using System.Runtime.Serialization.Formatters;
using System.Diagnostics;
using System;
using System.IO;
using Microsoft.Win32;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Drawing;
using System.Runtime.InteropServices;
namespace Test.PublicModel
{
[Serializable]
//[ComVisible(true)]
[TypeConverterAttribute(typeof(HourMinuteConverter)),DescriptionAttribute("展开以查看时分值。")]
public struct HourMinute : IEquatable<HourMinute>
{
public static readonly HourMinute Empty = new HourMinute(0,0);
private int _Hour;
private int _Minute;
/// <summary>
///
/// </summary>
/// <param name="Hour"></param>
/// <param name="Minute"></param>
public HourMinute(int Hour, int Minute)
{
if (Hour < 0)
Hour = 0;
else if (Hour > 24)
Hour = 24;
if (Minute < 0)
Minute = 0;
else if (Minute > 59)
Minute = 59;
if (Hour == 24)
if (Minute != 0)
Minute = 0;
this._Hour = Hour;
this._Minute = Minute;
}
//public HourMinute()
// : this(0, 0)
//{
//}
public HourMinute(HourMinute Hm)
{
this._Hour = Hm._Hour;
this._Minute = Hm._Minute;
}
//public static HourMinute operator +(HourMinute sz1, HourMinute sz2)
//{
// return Add(sz1, sz2);
//}
//public static HourMinute operator -(HourMinute sz1, HourMinute sz2)
//{
// return Subtract(sz1, sz2);
//}
public static bool operator ==(HourMinute Hm1, HourMinute Hm2)
{
//if (Hm1 == null)
// return Hm2 == null;
return Hm1.Equals(Hm2);
}
public static bool operator !=(HourMinute Hm1, HourMinute Hm2)
{
return !(Hm1 == Hm2);
}
//public static explicit operator Point(HourMinute Hm)
//{
// return new Point(Hm.Hour, Hm.Minute);
//}
[Browsable(false)]
public bool IsEmpty
{
get
{
return _Hour == 0 && _Minute == 0;
}
}
/// <summary>
/// 分时结构体之小时,必须在0~24之间
/// </summary>
[Description("分时结构体之小时,必须在0~24之间")]
public int Hour
{
get { return _Hour; }
set { _Hour = value; }
}
/// <summary>
/// 分时结构体之分钟,必须在0~59之间,且当小时为24时,必须为0
/// </summary>
[Description("分时结构体之分钟,必须在0~59之间,且当小时为24时,必须为0")]
public int Minute
{
get { return _Minute; }
set { _Minute = value; }
}
public override bool Equals(object obj)
{
if (!(obj is HourMinute))
return false;
HourMinute Hm = (HourMinute)obj;
// Note value types can't have derived classes, so we don't need to
// check the types of the objects here. -- Microsoft, 2/21/2001
return (Hm._Hour == this._Hour) &&
(Hm._Minute == this._Minute);
}
/// <summary>
/// 为派生类可重写方法 Equals() 提供值比较支持
/// </summary>
/// <param name="Hm">HourMinute Struct</param>
/// <returns>True or False</returns>
public bool Equals(HourMinute Hm)
{
//if (this == null && Hm == null)
// return true;
//else if (this == null && Hm != null || this != null && Hm == null)
// return false;
return (this.Hour == Hm.Hour) && (this.Minute == Hm.Minute);
}
public override int GetHashCode()
{
return _Hour.GetHashCode() ^ _Minute.GetHashCode();
}
public override string ToString()
{
//return string.Format("Hour={0}, Minute={1}",
// _Hour.ToString(CultureInfo.CurrentCulture), _Minute.ToString(CultureInfo.CurrentCulture));
return string.Format("{0},{1}", this._Hour, this._Minute);
}
}
}
HourMinuteConverter.cs的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Globalization;
namespace Test.PublicModel
{
class HourMinuteConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context,
System.Type destinationType)
{
if (destinationType == typeof(string))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture,
object value, Type destinationType)
{
if (destinationType == typeof(string))
{
HourMinute Hm = (HourMinute)value;
return string.Format("{0},{1}", Hm.Hour, Hm.Minute);
}
//return "0,0";
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
//if (value == null)
// return new HourMinute(0, 0);
//else
if (value is string)
{
try
{
string s = (string)value;
s = s.TrimEnd();
if (s == "")
return new HourMinute(0, 0);
char[] dlimiters = new char[] { ',' };
string[] v = s.Split(dlimiters);
if (v.Length == 0)
return new HourMinute(0, 0);
else if (v.Length == 2)
{
HourMinute Hm = new HourMinute(int.Parse(v[0]), int.Parse(v[1]));
return Hm;
}
}
catch
{
throw new ArgumentException(string.Format("无法将\"{0}\"转换为 HourMinute 类型", value));
}
}
//return new HourMinute(0, 0);
return base.ConvertFrom(context, culture, value);
}
}
}