注意:DateTimePicker.Text不靠譜


這鳥屬性把我害苦過,特此敬告一下大家。具體表現在:

獲取時:在DateTimePicker.ValueChanged事件中,獲取到的Text有可能是string.Empty!!!,特別當ValueChanged事件是在構造函數或Load、Shown等啟動事件中觸發時,得到string.Empty的幾率增大;

賦值時:有可能觸發不了TextChanged事件(該事件默認不顯示在設計器中,但的確是存在的);

可能的原因:先看Value屬性的setter源碼:

set
{
    bool flag = !DateTime.Equals(this.Value, value);
    if (!this.userHasSetValue || flag)
    {
        if ((value < this.MinDate) || (value > this.MaxDate))
        {
            throw new ArgumentOutOfRangeException("Value", SR.GetString("InvalidBoundArgument", new object[] { "Value", FormatDateTime(value), "'MinDate'", "'MaxDate'" }));
        }
        string text = this.Text;
        this.value = value;//修改value
        this.userHasSetValue = true;
        
        //判斷是否擁有句柄
        if (base.IsHandleCreated)
        {
            int wParam = 0;
            NativeMethods.SYSTEMTIME lParam = DateTimeToSysTime(value);
            //發送消息:有可能就是這廝負責改Text
            UnsafeNativeMethods.SendMessage(new HandleRef(this, base.Handle), 0x1002, wParam, lParam);
        }
        if (flag)
        {
            this.OnValueChanged(EventArgs.Empty);//觸發ValueChanged事件
        }
        if (!text.Equals(this.Text))
        {
            this.OnTextChanged(EventArgs.Empty);
        }
    }
}

當中沒有直接對this.Text賦值,這應該是為了避免陷入死循環,因為Text改變也會觸發Value改變,也可能正因為這樣,MS采取了迂回的方式來處理Text屬性——通過Windows消息機制,而該機制是依賴控件句柄的,換言之只有當控件擁有了句柄才能處理Text。對消息機制和控件句柄我不熟(玩Win32開發的童鞋們那就相當的熟了),我猜控件句柄的生成和分配由OS負責,分配時機也不一定,大概可能是控件顯現了才會分配到。所以在構造函數或Load、Shown等啟動事件中修改Value時,也許控件還未分配到句柄,所以Text未被處理,導致得不到正確結果~

上述均是猜的哦,有可能對有可能不對。

所以,無論如何,敬告大家,對於DateTimePicker控件,Value和ValueChanged才是你正確的選擇,忘掉Text和TextChanged。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM