2016-04-23 67 views
0

我最近開始玩MVVM,在偶遇之前,我偶然發現了一個似乎很多的問題。在WPF中綁定浮點輸入字段時出現問題

本質上我有一個在我的模型中的double類型的屬性,該屬性鏈接到ViewModel中的字符串屬性,實現INotifyPropertyChanged接口,該接口綁定到文本框的Text屬性,UpdateSourceTrigger設置爲PropertyChanged ,但是文本框不會讓我輸入小數位或減號,也不能在沒有應用程序崩潰的情況下將文本框設置爲空白。

我徹底搜索瞭解決方案,發現了很多可能的解決方案,但在某些方面起作用,但留下了其他問題。最終我用的東西相結合來解決這個問題:

我發現this要使用,並通過將:

public App() 
{ 
    System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false; 
} 

在App.xaml.cs我現在可以插入小數放置在我的文本框中。但是我仍然不能使用' - ',也不能將文本框設置爲空白。

爲了解決這個問題,我做了兩件事。在我的XAML中,我將下面的StringFormat添加到了我的數據綁定中。

<TextBox Text="{Binding StringLinkedToDouble, UpdateSourceTrigger=PropertyChanged, StringFormat=-N2}"/> 

的「 - 」的「N2」之前,讓我輸入一個減號,但除非我第一次輸入的數值,然後進入了「 - 」在號碼開頭的代碼拋出一個錯誤。爲了解決這個問題,而事實上,我不能設置文本框爲空,而不會在一個錯誤,我做這在我的視圖模型:

public StringLinkedToDouble 
{ 
    get { return _model.DoubleToBeLinked.ToString(); } 
    set 
    { 
     if ((value != "") && (value != "-")) 
     _model.DoubleToBeLinked = Convert.ToDouble(value); 
     RaisePropertyChanged("StringLinkedToDouble"); 
    } 
} 

雖然這工作,我是新來的MVVM和我發佈這個的原因是因爲這個解決方案看起來非常簡單,幾乎太簡單了,我擔心MVVM可能不會「好」。我有一半希望被告知這不公平哈哈!如果是這樣的話,有人可能會提出一個更好的選擇?提前致謝! 另外,如果還有什麼我已經做了哪些是不適當MVVM那麼請讓我知道:)

+0

將文本框綁定到視圖模型上的字符串應該是微不足道的。我認爲你做錯了「..在我的模型,這是鏈接到一個字符串屬性.. ..雙重..」 – Crowcoder

回答

1

我不會說你的解決方案「太簡單」。你自願做了框架想爲你做的許多工作。

這裏是我會做:

視圖模型

public class ViewModel : INotifyPropertyChanged 
{ 
    private double _doubleValue = 0; 
    public double DoubleValue 
    { 
     get { return _doubleValue; } 
     set 
     { 
      _doubleValue = value; 
      PropertyChanged?.Invoke(this, 
       new PropertyChangedEventArgs(nameof(DoubleValue))); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

XAML

<Window 
    x:Class="WPFTest.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WPFTest" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 

    <Window.DataContext> 
     <local:ViewModel /> 
    </Window.DataContext> 

    <Grid> 
     <StackPanel Orientation="Vertical"> 
      <StackPanel Orientation="Horizontal" Margin="2"> 
       <Label>Double Value</Label> 
       <TextBox 
        Text="{Binding DoubleValue, UpdateSourceTrigger=PropertyChanged}" 
        Width="300" /> 
      </StackPanel> 
      <StackPanel Orientation="Horizontal" Margin="2"> 
       <Label>Double Value</Label> 
       <TextBox Text="{Binding DoubleValue}" Width="300" /> 
      </StackPanel> 
     </StackPanel> 
    </Grid> 
</Window> 

而且截圖:

Entering a broken double

頂部的文本框有焦點。我通過視圖模型綁定在第二個文本框中鍵入「-34」和「-34」。然後我輸入垃圾,第一個TextBox無法將字符串轉換爲double,所以默認驗證顯示紅色錯誤邊框 - 並且viewmodel上的屬性未更新,因此第二個文本框未更新。用戶可以看到有問題。

如果您在這裏唯一的目標只是讓用戶爲您提供雙倍的價值,以上就是您所需要的。

如果你想添加更多的用戶界面來幫助用戶瞭解正在發生什麼,you can write a style or template trigger on Validation.HasError

我不是數字領域的巨人,根本就拒絕接受非數字鍵擊,因爲很難讓它正常工作 - 就像你在減號方面的經驗一樣。我對此沒有信心,但我更喜歡向他們展示錯誤,並讓他們決定他們想要鍵入哪些字符以及何時輸入。

此外,從概念上講,您的viewmodel不應該知道這種驗證。對於視圖模型而言,擔心雙倍超出範圍是有意義的,但不涉及用戶正在輸入的內容。視圖模型應該有一個雙重屬性,有人在那裏設置它,就是這樣。檢查最終用戶輸入的字符是視圖的作業,而不是視圖模型。將它保留在TextBox(實際上,它可能是Binding正在執行此操作;出於某種原因,我從來沒有困擾過),從而將它保留在它所屬的視圖中。

你可能會試圖搞亂a custom value converter on the binding,但我不認爲有什麼辦法可以讓你做所有你想做的事情。但我的首選是使用微軟發佈它的方式使用WPF雙重轉換。我通常對他們發明那個車輪的方式很滿意。一個例外:嘗試輸入「-34e10」,並嘗試在「1」時「幫助」。但可以通過將UpdateSourceTrigger作爲默認值來修復,對於TextBox.TextLostFocusthat defaultDependencyProperty在註冊類中註冊時確定)。

+0

我必須承認,我實際上並不知道你可以綁定雙打文本屬性的文本框,所以我爲什麼使用一個字符串哈哈!正是我所期待的,非常感謝! –

+0

@Howard_Schmidtt NP! WPF學習曲線的很大一部分是要了解它能夠爲自己弄清楚多少(也知道它突然無法找出什麼地方)。 –