2016-04-23 13 views
0

最近MVVMで遊んでいましたが、私が遭遇する前に多くの問題を遭遇しました。WPFで浮動小数点入力フィールドをバインドする際の問題

は基本的に私はUpdateSourceTriggerがにPropertyChangedに設定されるテキストボックスのTextプロパティにバインドされたINotifyPropertyChangedインターフェイスを実装、私のViewModelに文字列プロパティにリンクされていた私のモデル、でdouble型のプロパティを持っていましたただし、テキストボックスでは小数点以下の桁やマイナス記号を入力できません。また、アプリケーションがクラッシュすることなくテキストボックスを空白に設定することもできます。

私はこれを解決するために徹底的に検索し、いくつかの面で機能する可能性のある解決策をたくさん見つけましたが、他の問題を残しました。最後に、私はこの問題を回避するためのものの組み合わせを使用しました:

私は有用であることがthisを発見し、そして配置することで:

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

をApp.xaml.csで、私は今、小数点を挿入することができ私のテキストボックスの場所。私はまだ ' - 'を使用することも、テキストボックスを空白にすることもできませんでした。

これを回避するには2つのことを行いました。私のXAMLでは、データバインディングに次のStringFormatを追加しました。

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

「 - 」「N2」の前には、入力にマイナス記号を私を許可されますが、私は最初の数値を入力して、入力された場合を除き - コードがエラーを投げた番号の先頭に「」を。この問題を回避する、と私はエラーに実行せずに、空白のテキストボックスを設定することができなかったという事実は、私は私のViewModelにこれをしなかったために:これが働くかもしれないが

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

上部のテキストボックスにフォーカスがあります。 2番目のテキストボックスに「-34」と「-34」と入力したところ、viewmodelを介してバインドされました。次に、私はガベージを入力し、最初のTextBoxは文字列をdoubleに変換できませんでしたので、デフォルトの検証によって赤色の境界線が表示され、viewmodelのプロパティは更新されず、 。ユーザーには問題があることがわかります。

ここでの唯一の目標は、ユーザーに2倍の値を与えることだけであれば、上記のことだけで十分です。

ユーザーが何が起こっているのかを理解するのに役立つUIを追加する場合は、you can write a style or template trigger on Validation.HasError

数字以外のキーストロークを受け入れることを拒否している巨大なファンではありません。マイナス記号で自分の経験を見たように、正しく動作させるのは難しいからです。私はそれについて宗教的ではないが、私は彼らにエラーを表示し、どの文字をいつ入力するかを決定させることを好む。

また、概念的には、あなたのビューモデルはこの種の検証について知ってはいけません。ビューモデルは、ダブルが範囲外であることを心配するのは理にかなっていますが、ユーザーが入力しているものについては心配していません。 viewmodelはdoubleプロパティを持ち、そこに誰かがそれを設定し、それがそれです。エンド・ユーザーが入力した文字を確認することは、ビュー・モデルではなくビューに対するジョブです。 TextBox(実際には、その作業を行うのはBindingとなる可能性がありますが、何らかの理由で私が決して見つけられないほど悩むことはありません)、それが所属するビューに保持されます。

あなたはa custom value converter on the bindingを使いこなそうとしているかもしれませんが、あなたがやろうとしていることを行う方法はないと思います。しかし、私の好みは、Microsoftがそれを出荷した方法でWPFの二重変換を使用することです。私は一般的に彼らがその車輪を発明した方法に満足しています。 1つの例外:「-34e10」と入力してください。「1」になると「ヘルプ」を試みます。しかし、UpdateSourceTriggerをデフォルトのままにしておくと修正可能です。TextBox.TextLostFocusです(DependencyPropertyが宣言クラスに登録されている場合はthat defaultとなります)。

+0

私はあなたが実際にテキストボックスのTextプロパティに倍精度をバインドすることができなかったことを告白しなければならない、だから私はなぜ文字列を使っていたのですか?まさに私が探していたものです、ありがとう! –

+0

@Howard_Schmidtt NP! WPFの学習曲線の大部分は、それがどれだけ理解できるか(また何が突然何かを突き止めることができないかを知ることもできる)を理解するようになっています。 –

関連する問題