C_TXT_Digital.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983
  1. /*******************************************************************************
  2. * Copyright(c) 2014 DongkeSoft All rights reserved. / Confidential
  3. * 类的信息:
  4. * 1.程序名称:C_TXT_Digital.cs
  5. * 2.功能描述:数字文本框
  6. * 编辑履历:
  7. * 作者 日期 版本 修改内容
  8. * 陈晓野 2014/09/29 1.00 新建
  9. *******************************************************************************/
  10. using System;
  11. using System.Collections;
  12. using System.ComponentModel;
  13. using System.ComponentModel.Design.Serialization;
  14. using System.Drawing;
  15. using System.Globalization;
  16. using System.Reflection;
  17. using System.Text.RegularExpressions;
  18. using System.Windows.Forms;
  19. namespace Dongke.IBOSS.PRD.Basics.BaseControls
  20. {
  21. /// <summary>
  22. /// 数字文本框
  23. /// </summary>
  24. public partial class C_TXT_Digital : DKTextBoxBase
  25. {
  26. #region 常量
  27. /// <summary>
  28. /// [^{0}{1}0-9]
  29. /// </summary>
  30. private const string REJECT_CHARS = "[^{0}{1}0-9]";
  31. /// <summary>
  32. /// [-]
  33. /// </summary>
  34. private const string NEGATIVE = "-";
  35. /// <summary>
  36. /// [.]
  37. /// </summary>
  38. private const string D_POINT = ".";
  39. /// <summary>
  40. /// [,]
  41. /// </summary>
  42. private const string D_COMMA = ",";
  43. #endregion
  44. #region 成员变量
  45. private Point _number = Point.Empty;
  46. private decimal _maxValue = decimal.MaxValue;
  47. private decimal _minValue = decimal.MinValue;
  48. private decimal _maxNumberValue = decimal.MaxValue;
  49. private decimal _minNumberValue = decimal.MinValue;
  50. private decimal? _dataValue = null;
  51. private bool _allowNegative = true;
  52. private bool _allowZero = true;
  53. private bool _hasComma = true;
  54. private bool _showDecimal = true;
  55. private bool _isEnter = false;
  56. #endregion
  57. #region 构造函数
  58. /// <summary>
  59. /// 构造函数
  60. /// </summary>
  61. public C_TXT_Digital()
  62. {
  63. InitializeComponent();
  64. this.ContinueWndProc = false;
  65. // 屏蔽输入法
  66. this.ImeMode = System.Windows.Forms.ImeMode.Off;
  67. //this.TextAlign = HorizontalAlignment.Right;
  68. // 设正则
  69. this.SetRejectCharsPattern();
  70. }
  71. public void InitControl()
  72. {
  73. this._number = Point.Empty;
  74. this._maxValue = decimal.MaxValue;
  75. this._minValue = decimal.MinValue;
  76. this._maxNumberValue = decimal.MaxValue;
  77. this._minNumberValue = decimal.MinValue;
  78. this.SetRejectCharsPattern();
  79. }
  80. #endregion
  81. #region 属性
  82. /// <summary>
  83. /// 获取或设置数字的精度,Number.X为整数位的有效位数,Number.Y为小数位的有效位数
  84. /// </summary>
  85. [Description("获取或设置数字的精度,Number.X为整数位的有效位数,Number.Y为小数位的有效位数"), Category("CustomerEx")]
  86. [DefaultValue(typeof(Point), "0, 0")]
  87. public Point Number
  88. {
  89. get
  90. {
  91. return this._number;
  92. }
  93. set
  94. {
  95. // Reject改变text
  96. if (this._number != value)
  97. {
  98. this._number = value;
  99. bool needReset = this.SetNumberValue();
  100. needReset = !this.SetRejectCharsPattern() && needReset;
  101. //if (needReset)
  102. //{
  103. // this.SetText(this.Text);
  104. //}
  105. this.SetText(this.Text);
  106. }
  107. }
  108. }
  109. /// <summary>
  110. /// 获取或设置允许输入的数字最大值
  111. /// </summary>
  112. [Description("获取或设置允许输入的数字最大值"), Category("CustomerEx")]
  113. [DefaultValue(typeof(decimal), "MaxValue")]
  114. public decimal MaxValue
  115. {
  116. get
  117. {
  118. return this._maxValue;
  119. }
  120. set
  121. {
  122. // Reject改变text
  123. //value = Math.Min(value, this._maxNumberValue);
  124. if (value < this._minValue)
  125. {
  126. return;
  127. }
  128. if (this._maxValue != value)
  129. {
  130. this._maxValue = value;
  131. bool needReset = this.SetNumberValue();
  132. if (needReset)
  133. {
  134. this.SetText(this.Text);
  135. }
  136. }
  137. }
  138. }
  139. /// <summary>
  140. /// 获取或设置允许输入的数字最小值
  141. /// </summary>
  142. [Description("获取或设置允许输入的数字最小值"), Category("CustomerEx")]
  143. [DefaultValue(typeof(decimal), "MinValue")]
  144. public decimal MinValue
  145. {
  146. get
  147. {
  148. return this._minValue;
  149. }
  150. set
  151. {
  152. // Reject改变text
  153. //value = Math.Max(value, this._minNumberValue);
  154. if (value > this._maxValue)
  155. {
  156. return;
  157. }
  158. if (this._minValue != value)
  159. {
  160. this._minValue = value;
  161. bool needReset = this.SetNumberValue();
  162. if (needReset)
  163. {
  164. this.SetText(this.Text);
  165. }
  166. }
  167. }
  168. }
  169. /// <summary>
  170. /// 获取或设置文本框的数字
  171. /// </summary>
  172. [Description("获取或设置文本框的数字"), Category("CustomerEx")]
  173. [DefaultValue(null)]
  174. public decimal? DataValue
  175. {
  176. get
  177. {
  178. return this._dataValue;
  179. }
  180. set
  181. {
  182. // 改变text
  183. if (this._dataValue != value)
  184. {
  185. this._dataValue = value;
  186. this.SetText((this._dataValue == null) ? "" : this._dataValue.ToString());
  187. }
  188. }
  189. }
  190. /// <summary>
  191. /// 获取或设置是否允许输入负数
  192. /// </summary>
  193. [Description("获取或设置是否允许输入负数"), Category("CustomerEx")]
  194. [DefaultValue(true)]
  195. public bool AllowNegative
  196. {
  197. get
  198. {
  199. return this._allowNegative;
  200. }
  201. set
  202. {
  203. // 改变text
  204. if (this._allowNegative != value)
  205. {
  206. this._allowNegative = value;
  207. bool needReset = this.SetNumberValue();
  208. needReset = !this.SetRejectCharsPattern() && needReset;
  209. if (needReset)
  210. {
  211. this.SetText(this.Text);
  212. }
  213. }
  214. }
  215. }
  216. /// <summary>
  217. /// 获取或设置是否允许零值
  218. /// </summary>
  219. [Description("获取或设置是否允许零值"), Category("CustomerEx")]
  220. [DefaultValue(true)]
  221. public bool AllowZero
  222. {
  223. get
  224. {
  225. return this._allowZero;
  226. }
  227. set
  228. {
  229. if (this._allowZero != value)
  230. {
  231. this._allowZero = value;
  232. this.SetText(this.Text);
  233. }
  234. }
  235. }
  236. /// <summary>
  237. /// 获取或设置是否有千分符(逗号)
  238. /// </summary>
  239. [Description("获取或设置是否有千分符(逗号)"), Category("CustomerEx")]
  240. [DefaultValue(true)]
  241. public bool HasComma
  242. {
  243. get
  244. {
  245. return this._hasComma;
  246. }
  247. set
  248. {
  249. if (this._hasComma != value)
  250. {
  251. this._hasComma = value;
  252. this.SetText(this.Text);
  253. }
  254. }
  255. }
  256. /// <summary>
  257. /// 获取或设置是否显示补齐小数有效位数
  258. /// </summary>
  259. [Description("获取或设置是否显示补齐小数有效位数"), Category("CustomerEx")]
  260. [DefaultValue(true)]
  261. public bool ShowDecimal
  262. {
  263. get
  264. {
  265. return this._showDecimal;
  266. }
  267. set
  268. {
  269. if (this._showDecimal != value)
  270. {
  271. this._showDecimal = value;
  272. this.SetText(this.Text);
  273. }
  274. }
  275. }
  276. #endregion
  277. #region 事件处理
  278. #endregion
  279. #region 公有方法/函数
  280. #endregion
  281. #region 受保护方法/函数
  282. /// <summary>
  283. /// 限制输入文本
  284. /// </summary>
  285. /// <param name="text"></param>
  286. /// <returns></returns>
  287. protected virtual string RejectDigitalChars(string text)
  288. {
  289. if (string.IsNullOrEmpty(text))
  290. {
  291. this._dataValue = null;
  292. return text;
  293. }
  294. // 过滤非数字
  295. string reject = "[^-.0-9]";
  296. text = Regex.Replace(text, reject, string.Empty);
  297. // 负号处理
  298. if (this._allowNegative && text.StartsWith(NEGATIVE))
  299. {
  300. text = NEGATIVE + text.Replace(NEGATIVE, string.Empty);
  301. }
  302. else
  303. {
  304. text = text.Replace(NEGATIVE, string.Empty);
  305. }
  306. // 小数点处理
  307. //if (this._number.Y > 0 && text.Contains(D_POINT))
  308. //{
  309. // int pointIndex = text.IndexOf(D_POINT);
  310. // text = text.Replace(D_POINT, string.Empty);
  311. // text = text.Insert(pointIndex, D_POINT);
  312. //}
  313. //else
  314. //{
  315. // text = text.Replace(D_POINT, string.Empty);
  316. //}
  317. if (text.Contains(D_POINT))
  318. {
  319. int pointIndex = text.IndexOf(D_POINT);
  320. text = text.Replace(D_POINT, string.Empty);
  321. text = text.Insert(pointIndex, D_POINT);
  322. }
  323. if (!this._isEnter)
  324. {
  325. // 数值限制
  326. decimal value;
  327. if (decimal.TryParse(text, out value))
  328. {
  329. if (value > this._maxNumberValue)
  330. {
  331. value = this._maxNumberValue;
  332. }
  333. if (value < this._minNumberValue)
  334. {
  335. value = this._minNumberValue;
  336. }
  337. string dec = null;
  338. //if (this._number.Y > 0 && this._showDecimal)
  339. //{
  340. // if (this._showDecimal)
  341. // {
  342. // dec = D_POINT.PadRight(this._number.Y + 1, '0');
  343. // }
  344. // else
  345. // {
  346. // dec = ".#";
  347. // }
  348. //}
  349. if (this._number.Y > 0)
  350. {
  351. if (this._showDecimal)
  352. {
  353. dec = D_POINT.PadRight(this._number.Y + 1, '0');
  354. }
  355. else
  356. {
  357. dec = D_POINT.PadRight(this._number.Y + 1, '#');
  358. }
  359. }
  360. string comma = null;
  361. if (this._hasComma)
  362. {
  363. comma = "#,##0";
  364. text = value.ToString(comma + dec);
  365. }
  366. else
  367. {
  368. comma = "####0";
  369. text = value.ToString(comma + dec);
  370. }
  371. //this._dataValue = value;
  372. this._dataValue = Convert.ToDecimal(text);
  373. }
  374. else
  375. {
  376. this._dataValue = null;
  377. }
  378. }
  379. return text;
  380. }
  381. /// <summary>
  382. /// 校验输入文本
  383. /// </summary>
  384. /// <param name="text"></param>
  385. /// <returns></returns>
  386. protected override bool CheckText(string text)
  387. {
  388. bool check = base.CheckText(text);
  389. if (!check)
  390. {
  391. return false;
  392. }
  393. if (!this._allowZero && this._dataValue.HasValue && this._dataValue == 0)
  394. {
  395. this.HasError = true;
  396. this.ErrorMessage = "不能输入零";
  397. return false;
  398. }
  399. this.HasError = false;
  400. this.ErrorMessage = string.Empty;
  401. return true;
  402. }
  403. /// <summary>
  404. /// 设置文本
  405. /// </summary>
  406. /// <param name="text"></param>
  407. protected override bool SetText(string text)
  408. {
  409. this.TextValue = null;
  410. text = this.RejectDigitalChars(text);
  411. if (this.CheckText(text))
  412. {
  413. this.TextValue = text;
  414. }
  415. if (base.Text != text)
  416. {
  417. this.IsSetText = true;
  418. int selectionStart = this.SelectionStart;
  419. int length = 0;
  420. if (this._isEnter)
  421. {
  422. length = base.Text.Length - text.Length;
  423. }
  424. base.Text = text;
  425. if (this._isEnter)
  426. {
  427. int start = selectionStart - length;
  428. this.SelectionStart = (start > 0 ? start : 0);
  429. }
  430. return true;
  431. }
  432. return true;
  433. }
  434. protected override void OnEnter(EventArgs e)
  435. {
  436. this._isEnter = true;
  437. this.SetText(this.Text);
  438. base.OnEnter(e);
  439. }
  440. protected override void OnLeave(EventArgs e)
  441. {
  442. this._isEnter = false;
  443. this.SetText(this.Text);
  444. base.OnLeave(e);
  445. }
  446. #endregion
  447. #region 私有方法/函数
  448. private bool SetNumberValue()
  449. {
  450. if (this._number.IsEmpty)
  451. {
  452. this._maxNumberValue = decimal.MaxValue;
  453. this._minNumberValue = (this._allowNegative ? decimal.MinValue : 0);
  454. }
  455. else
  456. {
  457. this._maxNumberValue = DNumber.ToDecimal(this._number);//this._number.ToDecimal() ;
  458. this._minNumberValue = (this._allowNegative ? 0 - this._maxNumberValue : 0);
  459. }
  460. bool isChanged = false;
  461. if (this._maxValue < this._maxNumberValue)
  462. {
  463. isChanged = true;
  464. this._maxNumberValue = this._maxValue;
  465. }
  466. if (this._minValue > this._minNumberValue)
  467. {
  468. isChanged = true;
  469. this._minNumberValue = this._minValue;
  470. }
  471. return isChanged;
  472. }
  473. /// <summary>
  474. /// 设置输入现状
  475. /// </summary>
  476. private bool SetRejectCharsPattern()
  477. {
  478. string rejectChars = string.Format(REJECT_CHARS,
  479. this._allowNegative ? NEGATIVE : string.Empty,
  480. this._number.Y > 0 ? "." : string.Empty);
  481. if (base.RejectChars != rejectChars)
  482. {
  483. base.RejectChars = rejectChars;
  484. return true;
  485. }
  486. else
  487. {
  488. return false;
  489. }
  490. }
  491. #endregion
  492. }
  493. /// <summary>
  494. /// 小数精度
  495. /// </summary>
  496. [TypeConverter(typeof(DNumberConverter))]
  497. [Serializable]
  498. public struct DNumber
  499. {
  500. private int _x;
  501. private int _y;
  502. /// <summary>
  503. /// 整数位精度
  504. /// </summary>
  505. public int X
  506. {
  507. get
  508. {
  509. return this._x;
  510. }
  511. set
  512. {
  513. if (value > 0)
  514. {
  515. this._x = value;
  516. }
  517. else
  518. {
  519. this._x = 0;
  520. }
  521. }
  522. }
  523. /// <summary>
  524. /// 小数位精度
  525. /// </summary>
  526. public int Y
  527. {
  528. get
  529. {
  530. return this._y;
  531. }
  532. set
  533. {
  534. if (value > 0)
  535. {
  536. this._y = value;
  537. }
  538. else
  539. {
  540. this._y = 0;
  541. }
  542. }
  543. }
  544. /// <summary>
  545. /// 是否为空值
  546. /// </summary>
  547. [Browsable(false)]
  548. public bool IsEmpty
  549. {
  550. get
  551. {
  552. return this._x == 0 && this._y == 0;
  553. }
  554. }
  555. public static readonly DNumber Empty = new DNumber();
  556. /// <summary>
  557. /// 是否相等
  558. /// </summary>
  559. /// <param name="obj"></param>
  560. /// <returns></returns>
  561. public override bool Equals(object obj)
  562. {
  563. if ((obj is DNumber))
  564. {
  565. DNumber n = (DNumber)obj;
  566. return n.X == this._x && n.Y == this._y;
  567. }
  568. return false;
  569. }
  570. public override int GetHashCode()
  571. {
  572. return this._x ^ this._y;
  573. }
  574. /// <summary>
  575. /// 比较两个 Number 对象。此结果指定两个 Number 对象的 Number.X 或 Number.Y 属性的值是否不等。
  576. /// </summary>
  577. /// <param name="left">要比较的 Number</param>
  578. /// <param name="right">要比较的 Number</param>
  579. /// <returns>如果 left 和 right 的 Number.X 属性值或 Number.Y 属性值不等,则为true;否则为 false</returns>
  580. public static bool operator !=(DNumber left, DNumber right)
  581. {
  582. return (left.X != right.X || left.Y != right.Y);
  583. }
  584. /// <summary>
  585. /// 比较两个 Number 对象。此结果指定两个 Number 对象的 Number.X 或 Number.Y 属性的值是否相等。
  586. /// </summary>
  587. /// <param name="left">要比较的 Number</param>
  588. /// <param name="right">要比较的 Number</param>
  589. /// <returns>如果 left 和 right 的 Number.X 属性值或 Number.Y 属性值不等,则为true;否则为 false</returns>
  590. public static bool operator ==(DNumber left, DNumber right)
  591. {
  592. return (left.X == right.X && left.Y == right.Y);
  593. }
  594. /// <summary>
  595. /// 构造
  596. /// </summary>
  597. /// <param name="x"></param>
  598. /// <param name="y"></param>
  599. public DNumber(int x, int y)
  600. {
  601. if (x > 0)
  602. {
  603. this._x = x;
  604. }
  605. else
  606. {
  607. this._x = 0;
  608. }
  609. if (y > 0)
  610. {
  611. this._y = y;
  612. }
  613. else
  614. {
  615. this._y = 0;
  616. }
  617. }
  618. /// <summary>
  619. /// 最大数值
  620. /// </summary>
  621. /// <returns></returns>
  622. public decimal ToDecimal()
  623. {
  624. if (!this.IsEmpty)
  625. {
  626. string dec = null;
  627. if (this._x > 0)
  628. {
  629. dec = string.Empty.PadLeft(this._x, '9');
  630. }
  631. else
  632. {
  633. dec = "0";
  634. }
  635. if (this._y > 0)
  636. {
  637. dec += ".".PadRight(this._y + 1, '9');
  638. }
  639. return Convert.ToDecimal(dec);
  640. }
  641. return 0;
  642. }
  643. public static decimal ToDecimal(Point p)
  644. {
  645. if (!p.IsEmpty)
  646. {
  647. string dec = null;
  648. if (p.X > 0)
  649. {
  650. dec = string.Empty.PadLeft(p.X, '9');
  651. }
  652. else
  653. {
  654. dec = "0";
  655. }
  656. if (p.Y > 0)
  657. {
  658. dec += ".".PadRight(p.Y + 1, '9');
  659. }
  660. return Convert.ToDecimal(dec);
  661. }
  662. return 0;
  663. }
  664. public override string ToString()
  665. {
  666. return string.Concat(new string[]
  667. {
  668. "{X=",
  669. this.X.ToString(CultureInfo.CurrentCulture),
  670. ",Y=",
  671. this.Y.ToString(CultureInfo.CurrentCulture),
  672. "}"
  673. });
  674. }
  675. }
  676. /// <summary>
  677. /// Converts a <see cref="T:DNumber" /> object from one data type to another. Access this class through the <see cref="T:System.ComponentModel.TypeDescriptor" /> object.
  678. /// </summary>
  679. /// <filterpriority>1</filterpriority>
  680. public class DNumberConverter : TypeConverter
  681. {
  682. /// <summary>
  683. /// Determines if this converter can convert an object in the given source type to the native type of the converter.
  684. /// </summary>
  685. /// <returns>true if this object can perform the conversion; otherwise, false.
  686. /// </returns>
  687. /// <param name="context">
  688. /// A formatter context. This object can be used to get additional information about the environment this converter is being called from. This may be null, so you should always check. Also, properties on the context object may also return null.
  689. /// </param>
  690. /// <param name="sourceType">
  691. /// The type you want to convert from.
  692. /// </param>
  693. /// <filterpriority>1</filterpriority>
  694. public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
  695. {
  696. return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
  697. }
  698. /// <summary>
  699. /// Gets a value indicating whether this converter can convert an object to the given destination type using the context.
  700. /// </summary>
  701. /// <returns>true if this converter can perform the conversion; otherwise, false.
  702. /// </returns>
  703. /// <param name="context">
  704. /// An <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> object that provides a format context.
  705. /// </param>
  706. /// <param name="destinationType">
  707. /// A <see cref="T:System.Type" /> object that represents the type you want to convert to.
  708. /// </param>
  709. /// <filterpriority>1</filterpriority>
  710. public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
  711. {
  712. return destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
  713. }
  714. /// <summary>
  715. /// Converts the specified object to a <see cref="T:DNumber" /> object.
  716. /// </summary>
  717. /// <returns>
  718. /// The converted object.
  719. /// </returns>
  720. /// <param name="context">
  721. /// A formatter context. This object can be used to get additional information about the environment this converter is being called from. This may be null, so you should always check. Also, properties on the context object may also return null.
  722. /// </param>
  723. /// <param name="culture">
  724. /// An object that contains culture specific information, such as the language, calendar, and cultural conventions associated with a specific culture. It is based on the RFC 1766 standard.
  725. /// </param>
  726. /// <param name="value">
  727. /// The object to convert.
  728. /// </param>
  729. /// <exception cref="T:System.NotSupportedException">
  730. /// The conversion cannot be completed.
  731. /// </exception>
  732. /// <filterpriority>1</filterpriority>
  733. public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
  734. {
  735. string text = value as string;
  736. if (text == null)
  737. {
  738. return base.ConvertFrom(context, culture, value);
  739. }
  740. string text2 = text.Trim();
  741. if (text2.Length == 0)
  742. {
  743. return null;
  744. }
  745. if (culture == null)
  746. {
  747. culture = CultureInfo.CurrentCulture;
  748. }
  749. char c = culture.TextInfo.ListSeparator[0];
  750. string[] array = text2.Split(new char[]
  751. {
  752. c
  753. });
  754. int[] array2 = new int[array.Length];
  755. TypeConverter converter = TypeDescriptor.GetConverter(typeof(int));
  756. for (int i = 0; i < array2.Length; i++)
  757. {
  758. array2[i] = (int)converter.ConvertFromString(context, culture, array[i]);
  759. }
  760. if (array2.Length == 2)
  761. {
  762. return new DNumber(array2[0], array2[1]);
  763. }
  764. //throw new ArgumentException(SR.GetString("TextParseFailedFormat", new object[]
  765. //{
  766. // text2,
  767. // "x, y"
  768. //}));
  769. throw new ArgumentException("TextParseFailedFormat");
  770. }
  771. /// <summary>
  772. /// Converts the specified object to the specified type.
  773. /// </summary>
  774. /// <returns>
  775. /// The converted object.
  776. /// </returns>
  777. /// <param name="context">
  778. /// A formatter context. This object can be used to get additional information about the environment this converter is being called from. This may be null, so you should always check. Also, properties on the context object may also return null.
  779. /// </param>
  780. /// <param name="culture">
  781. /// An object that contains culture specific information, such as the language, calendar, and cultural conventions associated with a specific culture. It is based on the RFC 1766 standard.
  782. /// </param>
  783. /// <param name="value">
  784. /// The object to convert.
  785. /// </param>
  786. /// <param name="destinationType">
  787. /// The type to convert the object to.
  788. /// </param>
  789. /// <exception cref="T:System.NotSupportedException">
  790. /// The conversion cannot be completed.
  791. /// </exception>
  792. /// <filterpriority>1</filterpriority>
  793. public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
  794. {
  795. if (destinationType == null)
  796. {
  797. throw new ArgumentNullException("destinationType");
  798. }
  799. if (value is DNumber)
  800. {
  801. if (destinationType == typeof(string))
  802. {
  803. DNumber dnumber = (DNumber)value;
  804. if (culture == null)
  805. {
  806. culture = CultureInfo.CurrentCulture;
  807. }
  808. string separator = culture.TextInfo.ListSeparator + " ";
  809. TypeConverter converter = TypeDescriptor.GetConverter(typeof(int));
  810. string[] array = new string[2];
  811. int num = 0;
  812. array[num++] = converter.ConvertToString(context, culture, dnumber.X);
  813. array[num++] = converter.ConvertToString(context, culture, dnumber.Y);
  814. return string.Join(separator, array);
  815. }
  816. if (destinationType == typeof(InstanceDescriptor))
  817. {
  818. DNumber dnumber2 = (DNumber)value;
  819. ConstructorInfo constructor = typeof(DNumber).GetConstructor(new Type[]
  820. {
  821. typeof(int),
  822. typeof(int)
  823. });
  824. if (constructor != null)
  825. {
  826. return new InstanceDescriptor(constructor, new object[]
  827. {
  828. dnumber2.X,
  829. dnumber2.Y
  830. });
  831. }
  832. }
  833. }
  834. return base.ConvertTo(context, culture, value, destinationType);
  835. }
  836. /// <summary>
  837. /// Creates an instance of this type given a set of property values for the object.
  838. /// </summary>
  839. /// <returns>
  840. /// The newly created object, or null if the object could not be created. The default implementation returns null.
  841. /// </returns>
  842. /// <param name="context">
  843. /// A type descriptor through which additional context can be provided.
  844. /// </param>
  845. /// <param name="propertyValues">
  846. /// A dictionary of new property values. The dictionary contains a series of name-value pairs, one for each property returned from <see cref="M:DNumberConverter.GetProperties(System.ComponentModel.ITypeDescriptorContext,System.Object,System.Attribute[])" />.
  847. /// </param>
  848. /// <filterpriority>1</filterpriority>
  849. public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
  850. {
  851. if (propertyValues == null)
  852. {
  853. throw new ArgumentNullException("propertyValues");
  854. }
  855. object obj = propertyValues["X"];
  856. object obj2 = propertyValues["Y"];
  857. if (obj == null || obj2 == null || !(obj is int) || !(obj2 is int))
  858. {
  859. throw new ArgumentException("PropertyValueInvalidEntry");
  860. }
  861. return new DNumber((int)obj, (int)obj2);
  862. }
  863. /// <summary>
  864. /// Determines if changing a value on this object should require a call to <see cref="M:DNumberConverter.CreateInstance(System.ComponentModel.ITypeDescriptorContext,System.Collections.IDictionary)" /> to create a new value.
  865. /// </summary>
  866. /// <returns>true if the <see cref="M:DNumberConverter.CreateInstance(System.ComponentModel.ITypeDescriptorContext,System.Collections.IDictionary)" /> method should be called when a change is made to one or more properties of this object; otherwise, false.
  867. /// </returns>
  868. /// <param name="context">
  869. /// A <see cref="T:System.ComponentModel.TypeDescriptor" /> through which additional context can be provided.
  870. /// </param>
  871. /// <filterpriority>1</filterpriority>
  872. public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
  873. {
  874. return true;
  875. }
  876. /// <summary>
  877. /// Retrieves the set of properties for this type. By default, a type does not return any properties.
  878. /// </summary>
  879. /// <returns>
  880. /// The set of properties that are exposed for this data type. If no properties are exposed, this method might return null. The default implementation always returns null.
  881. /// </returns>
  882. /// <param name="context">
  883. /// A type descriptor through which additional context can be provided.
  884. /// </param>
  885. /// <param name="value">
  886. /// The value of the object to get the properties for.
  887. /// </param>
  888. /// <param name="attributes">
  889. /// An array of <see cref="T:System.Attribute" /> objects that describe the properties.
  890. /// </param>
  891. /// <filterpriority>1</filterpriority>
  892. public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
  893. {
  894. PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(DNumber), attributes);
  895. return properties.Sort(new string[]
  896. {
  897. "X",
  898. "Y"
  899. });
  900. }
  901. /// <summary>
  902. /// Determines if this object supports properties. By default, this is false.
  903. /// </summary>
  904. /// <returns>true if <see cref="M:DNumberConverter.GetProperties(System.ComponentModel.ITypeDescriptorContext,System.Object,System.Attribute[])" /> should be called to find the properties of this object; otherwise, false.
  905. /// </returns>
  906. /// <param name="context">
  907. /// A <see cref="T:System.ComponentModel.TypeDescriptor" /> through which additional context can be provided.
  908. /// </param>
  909. /// <filterpriority>1</filterpriority>
  910. public override bool GetPropertiesSupported(ITypeDescriptorContext context)
  911. {
  912. return true;
  913. }
  914. }
  915. }