C# XAML-IValueConverter和行为相互冲突,导致无休止的循环发生
对于Xamarin表单应用程序,我有一个IValueConverter和行为,它们相互冲突,导致无休止的循环发生。我已经创建了一个简单的应用程序来演示这个问题,可以下载(下面的链接),并在下面包含了相关代码 以下是我在这个场景中试图实现的需求C# XAML-IValueConverter和行为相互冲突,导致无休止的循环发生,c#,xaml,xamarin,xamarin.forms,C#,Xaml,Xamarin,Xamarin.forms,对于Xamarin表单应用程序,我有一个IValueConverter和行为,它们相互冲突,导致无休止的循环发生。我已经创建了一个简单的应用程序来演示这个问题,可以下载(下面的链接),并在下面包含了相关代码 以下是我在这个场景中试图实现的需求 用户必须能够为int输入空值 用户只允许输入整数值 对于#1,我在后端模型中使用可为null的int。如果我只使用一个“int”,那么如果该字段被清除,它将始终以一个“0”结尾。因此,IValueConverter实现StringToIntConverte
IntegerValidationBehavior
public class IntegerValidationBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry entry)
{
entry.TextChanged += OnEntryTextChanged;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.TextChanged -= OnEntryTextChanged;
base.OnDetachingFrom(entry);
}
private static void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
if (!string.IsNullOrWhiteSpace(args.NewTextValue))
{
//make sure all characters are numbers
var isValid = args.NewTextValue.ToCharArray().All(x => char.IsDigit(x));
((Entry)sender).Text = isValid ? args.NewTextValue : args.NewTextValue.Remove(args.NewTextValue.Length - 1);
}
}
}
public class StringToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return "";
else
return ((int)value).ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var val = value as string;
if (string.IsNullOrWhiteSpace(val))
return null;
else
{
var result = 0;
int.TryParse(val, out result);
return result;
}
}
}
XAML
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:behaviors="clr-namespace:SampleApp"
mc:Ignorable="d"
x:Class="SampleApp.MainPage">
<StackLayout>
<Entry Keyboard="Numeric"
Text="{Binding Model.Length, Mode=TwoWay, Converter={StaticResource StringToInt}}">
<Entry.Behaviors>
<behaviors:IntegerValidationBehavior />
</Entry.Behaviors>
</Entry>
<Label Text="{Binding Model.LengthString}"
TextColor="Black" />
<Button Text="Process"
Command="{Binding Process}" />
</StackLayout>
</ContentPage>
型号
public class MainPageModel : FreshBasePageModel
{
public MainPageModel()
{
Model = new Model();
}
public Model Model { get; set; }
}
public class Model : INotifyPropertyChanged
{
private int? _length;
public int? Length
{
get { return _length; }
set { SetProperty(ref _length, value); }
}
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(storage, value))
{
return false;
}
storage = value;
OnPropertyChanged(propertyName);
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
}
公共类MainPageModel:FreshBasePageModel
{
公共主页模型()
{
模型=新模型();
}
公共模型模型{get;set;}
}
公共类模型:INotifyPropertyChanged
{
私有整数长度;
公共整数长度
{
获取{return_length;}
set{SetProperty(ref _length,value);}
}
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
受保护的bool SetProperty(ref T storage,T value,[CallerMemberName]string propertyName=null)
{
if(EqualityComparer.Default.Equals(存储,值))
{
返回false;
}
储存=价值;
OnPropertyChanged(propertyName);
返回true;
}
公共事件属性更改事件处理程序属性更改;
}
在IntegerValidationBehavior文件中将下面的方法替换为您的OnEntryTextChanged方法,并检查其是否有效
private static void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
if (!string.IsNullOrWhiteSpace(args.NewTextValue))
{
//make sure all characters are numbers
var isValid = args.NewTextValue.ToCharArray().All(x => char.IsDigit(x));
if (isValid && args.NewTextValue.Length > 1 && args.NewTextValue.StartsWith("0"))
return;
((Entry)sender).Text = isValid ? args.NewTextValue : args.NewTextValue.Remove(args.NewTextValue.Length - 1);
}
}
我把你的密码改成
public class StringToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return null;
else
return ((int)value).ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var val = value as string;
if ( int.TryParse( val, out var result ) )
return result;
else
return null;
}
}
public类IntegerValidationBehavior:Behavior
{
受保护的覆盖无效附加到(条目)
{
entry.TextChanged+=OnEntryTextChanged;
基本数据(条目);
}
受保护的覆盖无效OnDetachingFrom(条目)
{
entry.TextChanged-=OnEntryTextChanged;
base.OnDetachingFrom(条目);
}
私有静态void OnEntryTextChanged(对象发送方,textchangedventargs args)
{
如果(args.NewTextValue!=null)
{
//确保所有字符都是数字
var isValid=int.TryParse(args.NewTextValue,out 2;);
如果(!isValid)
((条目)sender.Text=args.OldTextValue;/=isValid?args.NewTextValue:args.NewTextValue.Remove(args.NewTextValue.Length-1);
}
}
}
无止境的循环消失了。谢谢,这样更好。但是一旦属性有了值,就不能再将其设为null。为了进行测试,我输入了'02',它变为'2',但是我不能将2倒出来,使字段为空。
public class IntegerValidationBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry entry)
{
entry.TextChanged += OnEntryTextChanged;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.TextChanged -= OnEntryTextChanged;
base.OnDetachingFrom(entry);
}
private static void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
if (args.NewTextValue != null)
{
//make sure all characters are numbers
var isValid = int.TryParse( args.NewTextValue, out _ );
if ( !isValid )
((Entry)sender).Text = args.OldTextValue; // = isValid ? args.NewTextValue : args.NewTextValue.Remove(args.NewTextValue.Length - 1);
}
}
}