2017-03-05 77 views
0

我正在用UWP,x:Bind和數據驗證掙扎了一下。 我有一個非常簡單的用例:我希望用戶在TextBox中輸入int,並在用戶離開TextBox後立即在TextBlock中顯示該號碼。 我可以爲TextBox設置InputScope="Number",但這並不妨礙使用鍵盤輸入字符的人(或粘貼某個東西)。 問題是,當我綁定字段與Mode=TwoWay,看來你不能防止System.ArgumentException如果您綁定字段聲明爲int。如果輸入是一個數字,我想檢查set方法,但在此之前發生異常。 我的(很簡單)視圖模型(在這裏沒有模式,我試圖保持儘可能簡單):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中鍵入數字字符,則一切正常。但是,如果我輸入一個非數值(說「d」)(它甚至沒有在set方法的第一支撐爲MyFieldToValidate到達斷點):

Imgur

是否有一個最佳實踐做我想做的事情?最簡單的解決方案是防止用戶輸入其他字符而不是數字,但是我一直在尋找幾個小時而沒有找到簡單的方法......另一個解決方案是在離開字段時驗證數據,但是我沒有發現與UWP和x:Bind相關的東西(WPF認爲很少有東西,但它們不能用UWP複製)。 謝謝!

+0

只是不將其綁定到int,將其綁定到字符串屬性,你將通過seters做所有必要的轉換和getters(或使用自定義Converter並手動將輸入轉換爲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