2011-01-17 19 views
3

私は最近、VS 2008 .NET 3.5プロジェクトからVS2010 .NET 4プロジェクトに変換したアプリケーションを持っています。プロジェクト内の一部のWPFダイアログは、変換後に動作が異なります。私は何がこの行動の違いを引き起こしているのか理解したいので、今問題があるかもしれない他の領域を見つけて修正することができます。.NET 4と.NET 3.5のバインド設定が異なる動作をする理由

たとえば、ユーザーが番号を入力できるMVVMダイアログがあります。数値は内部的にdoubleとして格納され、ユーザーが入力するテキストが有効なdoubleである場合にのみダイアログを受け入れることができます。だから、私はViewModelの文字列にバインドされたテキストボックスと、文字列が有効な倍精度浮動小数点数型の場合にのみ有効にされているOKボタンがあります。関連するXAMLは次のようになります。

<TextBox Text="{Binding ValueString, UpdateSourceTrigger=PropertyChanged}"/> 
<Button IsEnabled="{Binding ValueIsValid}">OK</Button> 

とViewModelには、次のようになります。

class ViewModel : INotifyPropertyChanged 
{ 
    private double actualValue; 
    public string ValueString 
    { 
     get { return actualValue.ToString("G3"); } 
     set 
     { 
      double doubleValue; 
      if (double.TryParse(value, NumberStyles.Float, CultureInfo.CurrentCulture, out doubleValue)) 
      { 
       actualValue = doubleValue; 
       ValueIsValid = true; 
       RaisePropertyChanged("ValueString"); 
      } 
      else 
      { 
       ValueIsValid = false; 
      } 
     } 
    } 

    private bool valueIsValid = true; 
    public bool ValueIsValid 
    { 
     get { return valueIsValid; } 
     set 
     { 
      if (valueIsValid != value) 
      { 
       valueIsValid = value; 
       RaisePropertyChanged("ValueIsValid"); 
      } 
     } 
    } 

    private void RaisePropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

これは、.NET 3.5でうまくいきましたが、それはときに、ユーザーに問題がある.NET 4で実行されているとき番号を入力しています。たとえば、ユーザーが.NET 3.5バージョンのテキストボックスに「3.05555」と入力すると、すべて正常です。しかし、.NET 4バージョンでは3.05を入力することができますが、次の「5」を入力するとテキストボックスの値が「3.06」に変わり、5をもう一度押すと「3.07」に変わります。これは、値がValueStringのプロパティから設定されるとすぐに読み取られているため(つまり、「G3」としてフォーマットされているように)、.NET 3.5では発生しませんでした。

私はWhat's New in the .NET Framework 4What's New in WPF Version 4を含む)を見てきましたが、この変更については何も見つかりませんでした。

これを自分で見たい場合は、download from hereという小さなサンプルのVS2010ソリューションを作成しました。 BindingTest2008プロジェクトはVS 2008から変換され、.NET 3.5をターゲットとし、BindingTest2010プロジェクトは.NET 2010をターゲットとしたVS 2010で作成されました。コードは両方のプロジェクトで同じですが、.NET 4プロジェクトにはこの問題があります。

なぜこのようなことが起こっているのか理解していただければ幸いです。おかげさまで

更新:動作を変更していないコールRaisePropertyChanged("ValueIsValid");を削除し、無効な番号(例えば「3.1A」)を入力する途中、その場合の最後の有効な番号(例えば「3.1」に置き換えられません。 )。また、数字は3桁の有効数字よりも高い精度で入力することができます。例えば。 "3.0545555" - 入力したばかりのものが第3位の数字を四捨五入すると問題が発生したように見えます。

答えて

5

この動作の違いの理由は次のとおりです。

3.5で

、結合が のTextBoxのテキストを変更することなく、各 キーストロークの後に戻って元に新しい 値を記述します。しかし、そのテキストは、ソースが何か他の に(プロパティのセッターで)値 を変更したため 、フォーマット変換、または が含まれていないかもしれないので、正確に元の値 を示すものではありませ かもしれません。これにより、 の激しい苦情が発生しました。人々は のテキストボックスに、 という値を表示するようにしました。 と同じコンバータと書式設定の同じプロパティにバインドされている場合は、TextBlockと同じです。 UI には、エンドユーザーが入力した内容ではなく、実際には のデータが表示されます。 4.0のバグのこのクラスを修正するには

、結合 は現在の書式設定とすべての更新後に元の新しい値 へ 変換を適用します。 (LostFocus バインディングは既に3.5でこれを行っていました) TextBoxはデータ内に何を表示しているのかを で示していますが、これによりユーザーの入力はより複雑になります 我々は、少なくとも2つの方法で 次のリリースでは、このシナリオを改善することを計画し

:TextBoxのテキストは古い 文字列のために働い改訂文字列、挿入 ポイント(カーソル)に置き換えられた場合 1.あり の新しい文字列には間違っています。がカーソルを置く場所を推測するヒューリスティックは、 を改善することができます。 2.各 のキーストロークの後に、 の部分的な検証でLostFocus(またはExplicit)更新を行う方法がバインディングによって公開されます。 の書式設定/変換は、フォーカスが変更されたときにのみ適用されます。 すべてのキーストローク後にユーザーが確認フィードバック を取得します。

  • サム(WPFチーム)

Changed behaviour from .Net 3.5 to .Net 4.0 of WPF TextBox formatting when PropertyChanged is used as UpdateSourceTrigger

+0

ここでは、4.5が出ていて、動作が改善されておらず、本当の代替手段もありません。編集行為は、少なくとも言わないと奇妙です。その変化を巻き返す時間、多分? –

2

問題は、この行にあるように見えます:

get { return actualValue.ToString("G3"); } 

値が3桁があることを意味し、「G3」形式の文字列を、使用してフォーマットされているためネット4バージョンが正しく動作結果文字列(3.055は3.06になります)。

3.5と4の違いは、明らかに結合系がわずかに変化したことです。 3.5では、プロパティのセッターが呼び出され、PropertyChangedイベントが発生すると、バインディングは再評価されません(ゲッターは呼び出されません)。 .Net 4では、PropertyChangedイベントが発生した後、バインディングが再評価されます。つまり、プロパティISのゲッターが呼び出され、ゲッターによって返された値がテキストボックスに表示されます。

+0

から、それはそう、私が欲しいんどの(丸めた理由は、getメソッドであるため、フォーマットであることを正しいです最初にダイアログを表示したときに値が3記号の数字として表示されます)。しかし、RaisePropertyChangedへの呼び出しを削除しても、問題はまだ発生します。 – Wilka

+0

はい、RaisePropertyChangedは違いはありません。バインディングシステムはちょうどこの方法で動作します - ソースからの値をリフレッシュします。バインディングのUpdateSourceTriggerをLostFocusに変更することで、目的の動作を達成できます。 –

+1

ソースからの値を常にリフレッシュしていた場合は、「a」と入力すると最後の有効な数値に置き換えられます。ソースが最後の有効な番号のみを格納するのを見る。 – Wilka

関連する問題