2013-03-06 37 views
1

有一個TextBox,我想限制輸入範圍。
在這個簡單的例子Int32從0到300.
在現實生活中,範圍更復雜,我不想讓用戶界面參與,除了接收和顯示有效的值。TextBox Not Honoring值返回獲取

如果我輸入333,它會得到300和300的文本框。

這裏的問題是:
然後,如果我添加一個數字爲3001套分配的300
得到一個值調用,並返回300
但3001仍然是在文本框。

如果我粘貼3001,那麼它正確顯示300.
它只有當一個按鍵筆畫使4(或更大)的數字,它失敗。

<TextBox Text="{Binding Path=LimitInt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="60" Height="20"/> 

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

    private Int32 limitInt = 0; 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    public Int32 LimitInt 
    { 
     get { return limitInt; } 
     set 
     { 
      if (limitInt == value) return; 
      limitInt = value; 
      if (limitInt < 0) limitInt = 0; 
      if (limitInt > 300) limitInt = 300; 
      NotifyPropertyChanged("LimitInt"); 
     } 
    } 
} 
+1

您需要實現驗證。看看[這篇博文](http://weblogs.asp.net/monikadyrda/archive/2009/06/24/wpf-textbox-validation.aspx)。 – 2013-03-06 19:18:44

+0

@MichaelPerrenoud假裝我不想使用驗證。爲什麼通過在UI中獲取不是那個值來返回值? 301顯示300. -1顯示0.但3001顯示3001. – Paparazzi 2013-03-06 19:28:43

+0

我沒有得到同樣的問題...我複製/粘貼你的代碼,當我按'1'爲'3001'時,它給了我'300'。 – 2013-03-06 20:08:21

回答

3

我相信會發生這種情況,因爲您在綁定操作過程中正在更改綁定源的值。當您在綁定上使用UpdateSourceTrigger=PropertyChanged時,您告訴它在每次按鍵時重新評估。在這種情況下,Binding正在將該值推送給源,而不是試圖通過從源拉取目標來更新目標。

即使在您提出您的NotifyPropertyChanged後,我想象因爲您處於綁定操作的中間,目標不會被更新。

您可以通過刪除UpdateSourceTrigger並將其保留爲默認值(LostFocus)來解決此問題。只要您在用戶選項卡出來之後熟悉它,這樣做就可以工作。

<TextBox Text="{Binding Path=LimitInt}" Width="60" Height="20"/> 

(Mode = TwoWay是TextBox的默認值,所以您可以刪除它)。

如果你想在每次按鍵時評估它,我會建議尋找蒙面編輯,並處理keypress/keydown,以防止值進入TextBox,而不是試圖在他們'已經進入。

+0

的另一個原因我不同意你的說法,「不要試圖通過從源代碼來更新目標」。 Get被調用並返回適當的值。 -1正確顯示爲0. 301正確顯示300.獲取3001集合正確返回300,但UI不顯示300. – Paparazzi 2013-03-06 19:54:37

+0

我沒有調試框架代碼,所以我在這裏進行推測並努力解釋清楚,但我並不是想說Source永遠不會被取消 - NotifyPropertyChanged會強制它調用get - 但是在將新值推送到Source的過程中發生這種情況,而TextBox仍在處理文本輸入。沒有通過框架,我的猜測是,拉是否被目標放棄,因爲它處於推送操作的中間,或者目標值在推送到源時被「鎖定」。 – 2013-03-06 20:11:37

+0

謝謝。如果我使用LostFocus,它就可以工作。不是我想要的效果。我會按照Perrenoud的建議嘗試驗證。 +1 – Paparazzi 2013-03-06 20:33:29

1

這是一個更好的使用驗證。

方法如下:

定義您的XAML來檢查PreviewTextInput

<TextBox Text="{Binding Path=LimitInt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" PreviewTextInput="CheckNumberValidationHandler" Width="60" Height="20"/> 

然後設置您的驗證處理程序:

/// <summary> 
/// Check to make sure the input is valid 
/// </summary> 
/// <param name="sender"></param> 
/// <param name="e"></param> 
private void CheckNumberValidationHandler(object sender, TextCompositionEventArgs e) { 
    if(IsTextAllowed(e.Text)) { 
    Int32 newVal; 
    newVal = Int32.Parse(LimitInt.ToString() + e.Text); 
    if(newVal < 0) { 
     LimitInt = 0; 
     e.Handled = true; 
    } 
    else if(newVal > 300) { 
     LimitInt = 300; 
     e.Handled = true; 
    } 
    else { 
     e.Handled = false; 
    } 
    } 
    else { 
    e.Handled = true; 
    } 
} 

/// <summary> 
/// Check if Text is allowed 
/// </summary> 
/// <param name="text"></param> 
/// <returns></returns> 
private static bool IsTextAllowed(string text) { 
    Regex regex = new Regex("[^0-9]+"); 
    return !regex.IsMatch(text); 
} 

編輯:我查了一下,和它的作品在.NET 4.0中:)

+0

我懷疑這是正確的,所以給它+1。但現在我正在與LostFocus合作。直到我測試它不能給它檢查。 – Paparazzi 2013-03-07 02:11:33

+0

@Blam不用擔心,它確實是一種更好的方法,因爲使用'PreviewTextInput'可以防止輸入值,而不是在賦值後進行檢查。 – 2013-03-08 20:27:05