2017-03-05 7 views
0

私はUWP、x:Bindとデータ検証に少し苦労しています。 非常に簡単な使用例があります。ユーザがTextBoxを離れるとすぐに、TextBoxintを入力し、TextBlockに番号を表示します。 TextBoxInputScope="Number"を設定することはできますが、キーボードでタイプしてアルファベットを入力する(または何かを貼り付ける)ことはできません。 問題は、Mode=TwoWayのフィールドをバインドすると、できないように見えるSystem.ArgumentExceptionの場合は、バインドするフィールドがintと宣言されていないことを防ぎます。入力が数字の場合はsetメソッドをチェックしたかったのですが、その前に例外が発生しました。 私(非常に単純な)ViewModelに(ここでは無いモデルは、私はできるだけそれをシンプルに保つために試してみました):UWP:x:数値フィールドのバインドとデータ検証

public class MyViewModel : INotifyPropertyChanged 
{ 
    private int _MyFieldToValidate; 
    public int MyFieldToValidate 
    { 
     get { return _MyFieldToValidate; } 
     set 
     { 
      this.Set(ref this._MyFieldToValidate, value); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisedPropertyChanged([CallerMemberName]string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    protected bool Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null) 
    { 
     if (Equals(storage, value)) 
     { 
      return false; 
     } 
     else 
     { 
      storage = value; 
      this.RaisedPropertyChanged(propertyName); 
      return true; 
     } 
    } 
} 

背後にある私のコード:

public sealed partial class MainPage : Page 
{ 
    public MyViewModel ViewModel { get; set; } = new MyViewModel() { MyFieldToValidate = 0 }; 

    public MainPage() 
    { 
     this.InitializeComponent(); 
    } 
} 

そして、私の全体のXAML:

<Page 
    x:Class="SimpleFieldValidation.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:SimpleFieldValidation" 
    xmlns:vm="using:SimpleFieldValidation.ViewModel" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d"> 

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="10*" /> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="10*" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*" /> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 

     <TextBox Grid.Row="1" Grid.Column="0" Text="{x:Bind ViewModel.MyFieldToValidate, Mode=TwoWay}" x:Name="inputText" InputScope="Number" /> 
     <TextBlock Grid.Row="1" Grid.Column="1" Text="{x:Bind ViewModel.MyFieldToValidate, Mode=OneWay}" x:Name="textToDisplay" /> 
    </Grid> 
</Page> 

TextBoxに数値の文字を入力すると、すべてOKです。ベストプラクティスはあり

Imgur

:私は、数値以外の値を入力した場合でも、(それもMyFieldToValidateためset方法の第1のブラケットにブレークポイントに到達していない)(「D」と言います)私は何をしたいのですか?最も簡単な解決策は、ユーザーが最初に数字以外の文字を入力するのを妨げることですが、私は簡単な方法を見つけることなく時間を探していました...もう一つの解決策は、フィールドを離れる際にデータを検証することですUWPとx:Bindに関連するものは見つかりませんでした(WPFの考えではほとんどありませんが、UWPで複製することはできません)。 ありがとう!

+0

だけで、int型にバインド文字列プロパティにバインドして、あなたはsetersを経由して、すべての必要な変換を行いますしていないとgetters(またはカスタムのコンバーターを使用して手動でintに変換する) – RTDev

答えて

4

@RTDevが述べたように、あなたの例外はシステムが文字列をintに変換できないことが原因です。

IValueConverterから継承することで、ソースとターゲットの間でデータのフォーマットを変換できるクラスを作成できます。

機能実装では常にConvert(Object、TypeName、Object、String)を実装する必要がありますが、実装されていない例外が報告されるようにConvertBack(Object、TypeName、Object、String)双方向バインディングのコンバータを使用している場合、またはシリアル化にXAMLを使用している場合は、コンバータでConvertBack(Object、TypeName、Object、String)メソッドのみが必要です。

詳細については、IValueConverter Interfaceを参照してください。例えば

<Page.Resources> 
    <local:IntFormatter x:Key="IntConverter" /> 
</Page.Resources> 
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="10*" /> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="10*" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 
    <TextBox Grid.Row="1" Grid.Column="0" Text="{x:Bind ViewModel.MyFieldToValidate, Mode=TwoWay,Converter={StaticResource IntConverter}}" x:Name="inputText" InputScope="Number" /> 
    <TextBlock Grid.Row="1" Grid.Column="1" Text="{x:Bind ViewModel.MyFieldToValidate, Mode=OneWay}" x:Name="textToDisplay" /> 
</Grid> 

IntFormatterクラス:

internal class IntFormatter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, string language) 
    { 
     if (value != null) 
     { 
      return value.ToString(); 
     } 
     else 
     { 
      return null; 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, string language) 
    { 
     int n; 
     bool isNumeric = int.TryParse(value.ToString(), out n); 
     if (isNumeric) 
     { 
      return n; 
     } 
     else 
     { 
      return 0; 
     } 
    } 
} 
+0

シンプルで非常に便利な答えに感謝します。私はコンバータを見たが、まだそれらを試していない。私の検証のために、別のスレッドを開始すると思います(後で)。 – benichka

関連する問題