.NET MAUI 自定义控件属性未附加

.NET MAUI custom control property not got attached

提问人:Wasyster 提问时间:10/22/2023 更新时间:10/23/2023 访问量:64

问:

我正在使用 .Net Maui,我试图弄清楚如何为组件编写一个简单的验证。例如,我创建了一个名为 ValidatonFor 的包装器,我希望在其中收到要验证的模型字段的名称,但我卡在第一步中。

我的自定义包装器组件未收到为可绑定属性(FieldName 和 ShowValidationError)设置的值。

这是我的组件(这是我演奏的开始):

public partial class ValidationFor : ContentView
{
    public event EventHandler PropertyChanged;

    public static readonly BindableProperty FieldNameProperty = BindableProperty.Create(nameof(FieldName), typeof(string), typeof(ValidationFor));
    public static readonly BindableProperty ShowValidationErrorProperty = BindableProperty.Create(nameof(ShowValidationError), typeof(bool), typeof(ValidationFor));
    
    public string FieldName
    {
        get => (string)GetValue(FieldNameProperty);
        set => SetValue(FieldNameProperty, value);
    }

    public bool ShowValidationError
    {
        get => (bool)GetValue(ShowValidationErrorProperty);
        set => SetValue(ShowValidationErrorProperty, value);
    }

    private string ErrorMessage = string.Empty;
    private Visibility IsValid = Visibility.Hidden;
    private object chiledElement;

    public ValidationFor()
    {
        InitializeComponent();

        chiledElement = this.GetTemplateChild(this.FieldName);
        
        if(chiledElement is not null)
            (chiledElement as INotifyPropertyChanged).PropertyChanged += ValueChanged;
    }

    public void ValueChanged(object model, PropertyChangedEventArgs args)
    {
        if (args.PropertyName == FieldName.Split('.').Last()) { Validate(chiledElement); }
    }

    private void Validate(object chiledElement)
    {
        dynamic value = chiledElement.GetType().GetProperty(FieldName.Split('.').Last()).GetValue(chiledElement);
        var  results = new List<ValidationResult>();

        ValidationContext context = new ValidationContext(chiledElement) { MemberName = FieldName.Split('.').Last() };
        Validator.TryValidateProperty(value, context, results);

        if (results.Any())
        {
            if (!ShowValidationError)
            {
                this.ErrorMessage = results.First().ErrorMessage;
                this.IsValid = Visibility.Visible;
            }
        }
        else
        {
            this.ErrorMessage = null;
            this.IsValid = Visibility.Hidden;
        }

        PropertyChanged?.Invoke(this, null);
    }
}

在我的测试应用程序中,我是这样使用它的:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:validation="clr-namespace:ValidationLibrary;assembly=ValidationLibrary"
             xmlns:viewModel="clr-namespace:Validation.TestApp"
             x:Class="Validation.TestApp.MainPage"
             x:DataType="viewModel:TestViewModel">

    <VerticalStackLayout VerticalOptions="Start">
        <Frame BorderColor="Black">
            <validation:ValidationFor FieldName="Name" ShowValidationError="False">
                <Entry x:Name="Name" Text="{Binding Name, Mode=TwoWay, UpdateSourceEventName=PropertyChanged}" />
            </validation:ValidationFor>
        </Frame>
    </VerticalStackLayout>
    
</ContentPage>
C# .NET 验证 MAUI

评论

0赞 Liqun Shen-MSFT 11/23/2023
为什么您认为未收到 FieldName 值?该值已更改,但 setter 方法未触发。如果要监视更改,可以使用属性更改回调方法

答:

0赞 Guangyu Bai - MSFT 10/23/2023 #1

您需要编写一个静态验证回调方法,该方法可以通过指定 BindableProperty.Create 方法的 validateValue 参数来注册到可绑定属性。

首先,需要编写带有参数的 BindableProperty 方法。validateValue

public static readonly BindableProperty AngleProperty = BindableProperty.Create("Angle", typeof(double), typeof(MainPage), 0.0, validateValue: IsValidValue);

然后,您需要创建一个方法:IsValidValue

static bool IsValidValue(BindableObject view, object value)
{
    //logic here
}