XAML-IValueConverter和Behavior相互冲突,导致发生无限循环 - c#

在Xamarin Forms应用程序中,我有一个IValueConverter和Behavior,它们相互冲突,导致无休止的循环发生。我创建了一个简单的应用程序来演示此问题,该应用程序可以下载(下面的链接),并且在下面提供了相关代码。

这是我在这种情况下想要达到的要求。

用户必须能够为int输入一个空值。
仅允许用户输入一个整数值。

对于#1,我在后端模型中使用可为null的int。如果仅使用“ int”,那么如果清除该字段,则该字段始终以“ 0”结尾。因此,IValueConverter实现StringToIntConverter用于将值从字符串转换为int,如果传递了空字符串,则该属性设置为null。

对于#2,Behavior IntegerValidationBehavior检查每个按键并消除所有非整数值,包括句点。另外,在此示例中,我仅显示数字键盘。但是,它允许使用一些非整数字符(如句点),因此需要IntegerValidationBehavior。

对于普通输入,它的效果很好。但是,如果您以“ 0”开头,然后输入另一个数字,则将使干草堆陷入无限循环。我已经在各种XF版本以及iOS和Android平台上对此进行了验证。

如何更改代码以满足我的要求?

重现步骤

运行下面的github仓库中的演示
在输入框中输入“ 05”,应用将陷入死循环

复制链接

https://github.com/JohnLivermore/SampleXamarinApp/tree/endlessloop

整数验证行为

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);
        }
    }
}

StringToIntConverter

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;
}

参考方案

将以下methode替换为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);
                }
            }

Xamarin Forms按钮单击事件在运行时崩溃 - c#

我正在Xamarin中针对Windows,iOS和Android编辑一个应用程序。在可移植项目中,当编辑xaml文件时,我添加了以下按钮:<Button x:Name="Marker_Detection" Text="Marker Detection" Grid.Row="0" Grid.Co…

如何重用WPF用户控件但更改绑定属性? - c#

我有一个WPF用户控件,它使用我的viewmodel中的属性进行绑定。现在,我想使用具有相同视图模型的该用户控件的两个实例,但覆盖其中一个的绑定。代码看起来像这样用户控制<UserControl x:Class="TestWpfApp.UserControl1" xmlns="http://schemas.microsof…

在App.xaml.cs的OnStartup中关闭第一个窗口后,再打开C#WPF第二个窗口 - c#

我有2个WPF窗口。 App.xaml.cs选择“第一个窗口”,并在显示状态时读取一些数据,然后将其关闭。然后App.xaml.cs打开第二个窗口。当我调试代码正确执行但关闭第一个窗口后,它将关闭整个应用程序。我究竟做错了什么? App.xaml.cs中不可能吗?这是代码。 (对于该测试,我在后面使用代码而不是MVVM)在此代码中,我放置了一个按钮以关闭第一…

为什么仍启用此工具提示? - c#

我正在使用WPF应用,正在尝试有条件地启用工具提示。这很奇怪,我意识到,即使我明确地将工具提示设置为未启用(ToolTipService.IsEnabled="False"),工具提示仍然会显示。有人能弄清楚这里发生了什么吗? <TextBlock Grid.Row="2" Grid.Column="0…

Python 3运算符>>打印到文件 - python

我有以下Python代码编写项目的依赖文件。它可以在Python 2.x上正常工作,但是在使用Python 3进行测试时会报告错误。depend = None if not nmake: depend = open(".depend", "a") dependmak = open(".depend.mak&#…