2017-06-07 7 views
0

これはWPFのちょっとした奇妙なものです。それは単純に列Aの項目のリストを持っているWPFのnull可能なデータ型へのバインド

<DataGrid x:Name="Rates" AlternatingRowBackground="#FCFCFC" AutoGenerateColumns="False" CanUserReorderColumns="True" CanUserResizeColumns="True" CanUserAddRows="False" SelectionUnit="FullRow" CanUserSortColumns="True"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Item" Width="Auto" IsReadOnly="True" Binding="{Binding item}"/> 
     <DataGridTextColumn Header="Rate" Width ="*" Binding="{Binding rate, UpdateSourceTrigger=PropertyChanged}"/> 
    </DataGrid.Columns> 

を、我々はB.は十分に簡単に聞こえる列にレートを入力する必要があります。だから、私はこのようなDataGridを持っています。

ここには、それが結合されているViewModelのプロパティがあります。ここで

private BindableCollection<Rate> _rates; 

public BindableCollection<Rate> Rates 
{ 
    get 
    { 
     return _rates; 
    } 

    set 
    { 
     if (value == _rates) 
     { 
      return; 
     } 

     _rates = value; 
     NotifyOfPropertyChange(); 
    } 
} 

Rateの定義です:だから

public partial class Rate 
{ 
    public int ID { get; set; } 
    public string client { get; set; } 
    public string item { get; set; } 
    public Nullable<decimal> rate { get; set; } 
} 

、私DataGridの2列目はNullable<decimal>あるRate.rateに結合しつつあります。ここに問題がある。 Nullable<decimal>NULLを受け入れますが、TextBoxは空白の値を入力できません。さらに、5のような値を入力して削除すると、ViewModelは以前の値を保持します。

私はIValueConverterを含むソリューションを見てきましたが、私はXAMLベースのソリューションを好んでいました。何かありますか?私はDataTypeNullableであるいくつかのモジュールを持っており、毎回IValueConverterを使用しなければならないと、すぐに非常に面倒になることがあります。

私は結合として、したがって、どこでも動作しませんTargetNullValue=''を使用して、Caliburn.Microを使用しています

EDITは自動的に行われます。上記の例では、bindingが明示されています。

+0

Nullable 10進数をstringに置き換えて、ユーザー入力を検証したり、ユーザー入力を制限してテキストボックスクラスのtext changedイベントまたはpreviewKeydownイベントを拡張することによって10進値のみを許可することもできます。 –

答えて

2

あなたはCaliburn.Microを使用している場合は、CMがあなたのビューとあなたのViewModel間の自動バインディングを適用する方法を設定することができます。あなたがソースプロパティがNullableであれば、このコードはBindingTargetNullValueプロパティを設定し、見ることができるように

protected override void Configure() 
{ 
    ConventionManager.SetBinding = delegate(Type viewModelType, string path, PropertyInfo property, FrameworkElement element, ElementConvention convention, DependencyProperty bindableProperty) 
    { 
     Binding binding = new Binding(path); 
     ConventionManager.ApplyBindingMode(binding, property); 
     ConventionManager.ApplyValueConverter(binding, bindableProperty, property); 
     ConventionManager.ApplyStringFormat(binding, convention, property); 
     ConventionManager.ApplyValidation(binding, viewModelType, property); 
     ConventionManager.ApplyUpdateSourceTrigger(bindableProperty, element, binding, property); 

     if (Nullable.GetUnderlyingType(property.PropertyType) != null) 
     { 
      binding.TargetNullValue = String.Empty; 
     } 

     BindingOperations.SetBinding(element, bindableProperty, binding); 
    }; 

    // Your own configurations... 
} 

は、だからあなたのBootstrapperクラッセのConfigure方法であなたのような何かを書くことができます。これは、アプリケーションでCMが自動的に作成するすべての自動バインディングに適用されます。

私はそれが役に立ちそうです。あなたの最後のコメントについて

EDIT

、それは「自動結合」を適用したときにカリバーンマイクロは、プロパティに既にバインドされFrameworkElement S(XAMLで)を処理していないことを考えます。

あなたは自動的にあなたの「マニュアル」バインディングのTargetNullValueを設定したいのであれば、うまく最も単純なアイデアは、独自のバインディングを作成することです。その後、

public class NullableBinding : Binding 
{ 
    public NullableBinding(string path) 
     : base(path) 
    { 
     TargetNullValue = String.Empty; 
    } 

    public NullableBinding() 
     : base() 
    { 
     TargetNullValue = String.Empty; 
    } 
} 

とあなたのXAMLでそれを使用します。

<DataGridTextColumn Header="Rate" Width ="*" Binding="{local:NullableBinding rate}"/> 
+1

でした。 https://github.com/Caliburn-Micro/Caliburn.Micro/issues/448の正式回答はありませんでした。私は 'type'を' GetType() 'に変更しました。 –

+0

さて、コードでひっくり返って、ついにこれはうまくいきました: 'var existingApplyValidation = ConventionManager.ApplyValidation; ConventionManager.ApplyValidation =(binding、viewModelType、property)=> { existingApplyValidation(binding、viewModelType、property); //既存の動作を保持する if(Nullable.GetUnderlyingType(property.PropertyType)!= null) binding.TargetNullValue = String.Empty; }; ' コードが助けになりました。コードから条件文をコピーしました。 –

+0

私はこのソリューションをテストしていましたが、Caliburn.Microが自動的に要素をバインドする場所でのみ動作します。例えば、これはここで動作します: ''。しかし、バインディングが手動で定義されている場所では、 ''のようには機能しません。どのようにしてアプリケーション全体のバインディングに対してデフォルトのTargetNullValueを設定できますか? –

関連する問題