1

x:BindUWPとデータ検証に少し苦労しています。非常に単純な使用例があります。ユーザーが を離れたらすぐにに を入力しint、 にTextBox数字を表示するようにします。に を設定できますが、キーボードで入力する人がアルファ文字を入力する (または何かを貼り付ける) ことを妨げません。問題は、フィールドを でバインドすると、バインドするフィールドが として宣言されている場合、a を防ぐことができないように見えることです。入力が数値かどうかをメソッドにチェックインしたかったのですが、その直前で例外が発生します。私の(非常に単純な)ViewModel(ここにはモデルはありません。できるだけ単純にしようとしました):TextBlockTextBoxInputScope="Number"TextBoxMode=TwoWaySystem.ArgumentExceptionintset

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、すべて問題ありません。setしかし、数値以外の値 (「d」など) を入力すると (メソッドの最初のブラケットでブレークポイントに到達しませんMyFieldToValidate):

イムグル

私がやりたいことをするためのベストプラクティスはありますか? 最も簡単な解決策は、ユーザーが最初に数値以外の文字を入力できないようにすることですが、簡単な方法を見つけることなく何時間も検索してきました...別の解決策は、フィールドを離れるときにデータを検証することですが、私はUWP に関連するものは見つかりませんでしたx:Bind(WPF の考えはほとんどありませんが、UWP で複製することはできません)。ありがとう!

4

2 に答える 2

4

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

IValueConverter から継承することにより、ソースとターゲットの間でデータの形式を変換できるクラスを作成できます。

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

詳細については、IValueConverter インターフェイスを参照してください。

例えば:

<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;
        }
    }
}
于 2017-03-06T02:23:59.067 に答える