2010-02-18 56 views
8

我有哪些我想有模仿「軟描述」像那些在StackOverflow上的標題和標籤盒發現了一個標準的TextBox控件。實質上,當用戶的焦點進入控件時,它在這種情況下隱藏描述(「用戶名」),並將對齊和顏色設置爲標準文本控件的對齊和顏色。當用戶離開文本框時,我想檢查用戶是否實際輸入了任何內容,並將用戶名顯示備份到其他位置。修改上Leave事件TextBox控件防止Tab鍵進行控制

例如:

private void tbUsername_Enter(object sender, EventArgs e) 
    { 
     if (tbUsername.TextAlign == HorizontalAlignment.Center) 
     { 
      tbUsername.TextAlign = HorizontalAlignment.Left; 
      tbUsername.ForeColor = SystemColors.ControlText; 
      tbUsername.Text = String.Empty; 
     } 
    } 

    private void tbUsername_Leave(object sender, EventArgs e) 
    { 
     if (tbUsername.Text == String.Empty) 
     { 
      tbUsername.TextAlign = HorizontalAlignment.Center; 
      tbUsername.ForeColor = SystemColors.InactiveCaption; 
      tbUsername.Text = "Username"; 
     } 
    } 

不幸的是,當我設置這些事件,用戶不能切換出該用戶名的控制。控件只是閃爍並控制返回到文本框控件本身,直到用戶輸入了一些內容,跳過事件主體。

如果我在事件調用this.SelectNextControl(),則該事件進入一個無限循環。

有沒有人看到我在做什麼錯了?

+0

有趣..似乎有什麼東西與textAlign設置。如果我發表評論,似乎沒問題。 – SwDevMan81 2010-02-18 19:43:03

+0

+1好找。希望其中一個解決方法能夠爲你工作,儘管這兩者都不是最優的。可以將其發佈到MSDN論壇(http://social.msdn.microsoft.com/Forums/en-US/categories)以查看他們是否知道發生了什麼。 – SwDevMan81 2010-02-18 20:39:44

回答

6

看起來像它周圍的另一種方法(使用反射來看看,它並重新聚焦回控制,如果重點在那裏開始)。我認爲這是一個bug,但看起來他們只是重新使用RecreateHandleCore函數來重繪文本。因此,另一種方法是首先關注過文本框,然後繼續:

private void LeaveEvent(object sender, EventArgs e) 
    { 
    if (String.IsNullOrEmpty(tbUsername.Text)) 
    { 
     tbUsername.Text = USER_NAME; 
     tbUsername.ForeColor = SystemColors.InactiveCaption; 
     this.Focus(); 
     tbUsername.TextAlign = HorizontalAlignment.Center; 
    } 
    } 
+0

+1用於抽查時間檢查Reflector中實際發生的情況。 – Bill 2010-02-18 23:04:51

3

在TextBox控件上設置TextAlign屬性會將焦點返回給該控件。這看起來像一個錯誤。

這裏是一個快速的解決辦法:

tbUsername.Enabled = false; 
tbUsername.ForeColor = SystemColors.InactiveCaption; 
tbUsername.Text = "Username"; 
tbUsername.TextAlign = HorizontalAlignment.Center; 
tbUsername.Enabled = true; 

(儘管周圍的意外行爲一個黑客頗有幾分)。在更改對齊之前,只需禁用該控件即可。另一個「修復」是將事情保持對齊,或者測量要插入多少空間以模擬文本居中。

+0

+1 :)如果沒有其他,我必須upvote一個同胞比爾!我使用'focus'方法的唯一原因是它在我的機器上少了一點點。 – 2010-02-18 21:25:20

3

使用BeginInvoke

private void tbUsername_Leave(object sender, EventArgs e) 
    { 
     BeginInvoke(new MethodInvoker(OnLeave)); 
    } 

    private void OnLeave() 
    { 
     if (tbUsername.Text == String.Empty) 
     { 
      tbUsername.TextAlign = HorizontalAlignment.Center; 
      tbUsername.ForeColor = SystemColors.InactiveCaption; 
      tbUsername.Text = "Username"; 
     } 
    } 
+1

+1。我選擇focus()解決方案的唯一原因是它將本函數應該從定義中分離出來。 – 2010-02-18 21:34:55

+0

此解決方案主要是「意外」,即通常BeginInvoke委託將被安排爲「稍後」調用,也就是說,焦點從控件移開後 - 但它不保證以後 - OnLeave代碼實際上可以在tbUsername_Leave事件處理程序完成之前運行,並且焦點從原始控件移開。 – Bill 2010-02-18 23:03:20

+0

證據不能得到保證的地方在哪裏? 我只能重新說明BeginInvoke大部分等同於PostMessage,並將註冊消息排入窗口消息隊列以供以後處理。然後它由應用程序消息泵拾取並在主GUI線程上執行。 – 2010-02-18 23:37:37