在 MAUI 中,只有当表单的两个输入都不为空时才想要激活按钮。

huangapple go评论88阅读模式
英文:

Want to activate a button only when two inputs of the form are not empty using MAUI

问题

我想使用C# MAUI执行以下操作。
我想要仅在电子邮件输入和电话输入的内容均非空时启用“保存”按钮。
文档中有以下代码:

<Entry x:Name="email"
       Text="" />
<Entry x:Name="phone"
       Text="" />
<Button Text="Save">
    <Button.Triggers>
        <MultiTrigger TargetType="Button">
            <MultiTrigger.Conditions>
                <BindingCondition Binding="{Binding Source={x:Reference email},
                                            Path=Text.Length}"
                                  Value="0" />
                <BindingCondition Binding="{Binding Source={x:Reference phone},
                                            Path=Text.Length}"
                                  Value="0" />
            </MultiTrigger.Conditions>
            <Setter Property="IsEnabled" Value="False" />
            <!-- multiple Setter elements are allowed -->
        </MultiTrigger>
    </Button.Triggers>
</Button>

然而,使用上述代码,只要电子邮件或电话任一不为空,保存按钮都会被启用。
我该如何更改这个行为?

英文:

I would like to do the following using C# MAUI.
I want to enable the Save button only if the contents of the email Entry and the phone Entry are both non-null.
The documentation has the following code

&lt;Entry x:Name=&quot;email&quot;
       Text=&quot;&quot; /&gt;
&lt;Entry x:Name=&quot;phone&quot;
       Text=&quot;&quot; /&gt;
&lt;Button Text=&quot;Save&quot;&gt;
    &lt;Button.Triggers&gt;
        &lt;MultiTrigger TargetType=&quot;Button&quot;&gt;
            &lt;MultiTrigger.Conditions&gt;
                &lt;BindingCondition Binding=&quot;{Binding Source={x:Reference email},
                                            Path=Text.Length}&quot;
                                  Value=&quot;0&quot; /&gt;
                &lt;BindingCondition Binding=&quot;{Binding Source={x:Reference phone},
                                            Path=Text.Length}&quot;
                                  Value=&quot;0&quot; /&gt;
            &lt;/MultiTrigger.Conditions&gt;
            &lt;Setter Property=&quot;IsEnabled&quot; Value=&quot;False&quot; /&gt;
            &lt;!-- multiple Setter elements are allowed --&gt;
        &lt;/MultiTrigger&gt;
    &lt;/Button.Triggers&gt;
&lt;/Button&gt;

However, with the above code, the save button will be enabled as long as neither the email nor the phone is null.
How can I change this?

答案1

得分: 2

你可以在输入框 (Entry) 中添加一个 TextChanged 事件来确定文本是否为空。我编写了一个简单的演示来测试它。你可以参考以下代码:

XAML:

<Entry x:Name="email" TextChanged="OnTextChanged"/>
<Entry x:Name="phone" TextChanged="OnTextChanged"/>
<Button x:Name="Save" Text="点击我" Clicked="OnSaveClicked" IsEnabled="False"/>

.cs 文件:

private void OnTextChanged(object sender, TextChangedEventArgs e) 
{
    if (!string.IsNullOrWhiteSpace(email.Text) && !string.IsNullOrWhiteSpace(phone.Text)) 
    {
        Save.IsEnabled = true;
    }
    else
    {
        Save.IsEnabled = false;
    }
}

希望这对你有帮助。

英文:

You can add a TextChanged event to the Entry to determine whether the Text is empty. I wrote a simple demo to test it. You can refer to the code:

Xaml:

&lt;Entry x:Name=&quot;email&quot; TextChanged=&quot;OnTextChanged&quot;/&gt;
&lt;Entry x:Name=&quot;phone&quot; TextChanged=&quot;OnTextChanged&quot;/&gt;
&lt;Button x:Name=&quot;Save&quot; Text=&quot;Click Me&quot; Clicked=&quot;OnSaveClicked&quot; IsEnabled=&quot;False&quot;/&gt;

.cs file:

private void OnTextChanged(object sender, TextChangedEventArgs e) 
{
    if (!string.IsNullOrWhiteSpace(email.Text) &amp;&amp; !string.IsNullOrWhiteSpace(phone.Text)) 
    {
        Save.IsEnabled = true;
    }
    else
    {
        Save.IsEnabled = false;
    }
}

Hope it can help you.

答案2

得分: 2

有两种方法可以实现此目标,除了从代码后台设置<Button>IsEnabled属性之外。

选项1:使用MVVM模式

在您的ViewModel中,定义一些用于电子邮件和电话的属性,以及一个命令,以及一个用作命令的CanExecute参数的谓词的评估函数,如下所示:

public partial class MyViewModel : ObservableObject
{
    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(SaveCommand))]
    private string email;

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(SaveCommand))]
    private string phone;

    [RelayCommand(CanExecute = nameof(CanSave))]
    private void Save()
    {
        // your logic here
    }

    private bool CanSave() => !string.IsNullOrWhiteSpace(Email) && !string.IsNullOrWhiteSpace(Phone);
}

然后,在View的代码后台(.xaml.cs文件)中,您需要将BindingContext设置为ViewModel:

public partial class MyPage: ContentPage
{
	public MyPage()
	{
		InitializeComponent();
        BindingContext = new MyViewModel();
    }
}

最后,在您的View中,您可以将每个Entry的Text属性绑定到ViewModel中的相应属性,并将Button绑定到Command:

<Entry Text="{Binding Email, Mode=TwoWay}" />
<Entry Text="{Binding Phone, Mode=TwoWay}" />
<Button Text="Save"
        Command="{Binding SaveCommand}">

这样,只有当两个输入都包含文本时,按钮才会启用。

您可以在文档中找到有关Model-View-ViewModel(MVVM)模式的更多信息。此示例还使用了MVVM Community Toolkit的Source Generators,我还写了一个关于根据属性值启用和禁用按钮的主题的博客系列

选项2:使用MultiBinding

您可以使用MultiBinding而不是MultiTrigger,它允许您根据两个输入的绑定来评估它们是否为truefalse

为此,首先需要一个实现IMultiValueConverter接口并检查所有输入是否为字符串类型且非null、空白或空字符串的转换器:

public class AllNotNullOrEmptyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values == null || !targetType.IsAssignableFrom(typeof(bool)))
        {
            return false;
        }

        foreach (var value in values)
        {
            if (value is not string b)
            {
                return false;
            }

            if (string.IsNullOrWhiteSpace(b))
            {
                return false;
            }
        }
        return true;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return default;
    }
}

然后,您可以使用转换器并在XAML中使用MultiBinding

<ContentPage.Resources>
  <converters:AllNotNullOrEmptyConverter x:Key="AllNotNullOrEmptyConverter" />
</ContentPage.Resources>

<VerticalStackLayout>
  <Entry x:Name="Email"/>
  <Entry x:Name="Phone"/>
  <Button>
    <Button.IsEnabled>
      <MultiBinding Converter="{StaticResource AllNotNullOrEmptyConverter}">
        <Binding Path="Text" Source="{x:Reference Email}" />
        <Binding Path="Text" Source="{x:Reference Phone}" />
      </MultiBinding>
    </Button.IsEnabled>
  </Button>
</VerticalStackLayout>

这种方法的美妙之处在于您可以添加更多的Entry,只需为每个添加一行额外的MultiBinding以将它们包括在按钮的IsEnabled属性的评估中。

英文:

There are a couple of ways to achieve this apart from setting the IsEnabled property of the &lt;Button&gt; from the code-behind.

Option 1: Using the MVVM pattern

In your ViewModel, define some properties for E-Mail and Phone, a Command as well as an evaluation function that serves as a predicate for the CanExecute parameter for the Command like follows:

public partial class MyViewModel : ObservableObject
{
    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(SaveCommand))]
    private string email;

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(SaveCommand))]
    private string phone;

    [RelayCommand(CanExecute = nameof(CanSave))]
    private void Save()
    {
        // your logic here
    }

    private bool CanSave() =&gt; !string.IsNullOrWhiteSpace(Email) &amp;&amp; !string.IsNullOrWhiteSpace(Phone);
}

Then, in the code-behind of your View (the *.xaml.cs file), you need to set the BindingContext to the ViewModel:

public partial class MyPage: ContentPage
{
	public MyPage()
	{
		InitializeComponent();
        BindingContext = new MyViewModel();
    }
}

Finally, in your View, you can bind the Text property of each Entry to the appropriate property in the ViewModel and bind the Button to the Command:

&lt;Entry Text=&quot;{Binding Email, Mode=TwoWay}&quot; /&gt;
&lt;Entry Text=&quot;{Binding Phone, Mode=TwoWay}&quot; /&gt;
&lt;Button Text=&quot;Save&quot;
        Command=&quot;{Binding SaveCommand}&quot;&gt;

This way, the Button will only be enabled when both entries contain some text.

You can find more information on the Model-View-ViewModel (MVVM) pattern in the documentation. This example also uses the Source Generators of the MVVM Community Toolkit, which I've also written a blog series about which also covers the topic of enabling and disabling buttons based on property values.

Option 2: Using MultiBinding

Instead of a MultiTrigger, you could use a MultiBinding instead, which allows you evaluate your bindings to either true or false based on both entries.

For this, you first need a converter that implements the IMultiValueConverter interface and checks if all the inputs are of type string and not null, whitespace or empty:

public class AllNotNullOrEmptyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values == null || !targetType.IsAssignableFrom(typeof(bool)))
        {
            return false;
        }

        foreach (var value in values)
        {
            if (value is not string b)
            {
                return false;
            }

            if (string.IsNullOrWhiteSpace(b))
            {
                return false;
            }
        }
        return true;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return default;
    }
}

You can then consume the converter and use a MultiBinding in your XAML:

&lt;ContentPage.Resources&gt;
  &lt;converters:AllNotNullOrEmptyConverter x:Key=&quot;AllNotNullOrEmptyConverter&quot; /&gt;
&lt;/ContentPage.Resources&gt;

&lt;VerticalStackLayout&gt;
  &lt;Entry x:Name=&quot;Email&quot;/&gt;
  &lt;Entry x:Name=&quot;Phone&quot;/&gt;
  &lt;Button&gt;
    &lt;Button.IsEnabled&gt;
      &lt;MultiBinding Converter=&quot;{StaticResource AllNotNullOrEmptyConverter}&quot;&gt;
        &lt;Binding Path=&quot;Text&quot; Source=&quot;{x:Reference Email}&quot; /&gt;
        &lt;Binding Path=&quot;Text&quot; Source=&quot;{x:Reference Phone}&quot; /&gt;
      &lt;/MultiBinding&gt;
    &lt;/Button.IsEnabled&gt;
  &lt;/Button&gt;
&lt;/VerticalStackLayout&gt;

The beauty of this approach is that you can add more entries and only need to add one extra line to the MultiBinding for each to include them in the evaluation for the IsEnabled property of the button.

huangapple
  • 本文由 发表于 2023年2月18日 17:06:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75492283.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定