6

在 Xamarin.Forms 中,如何将按钮指定为页面的默认按钮?

例如,在 UWP 上,当用户在页面具有焦点时按下 Enter 键时,应触发DefaultButton的单击处理程序。

4

4 回答 4

4

假设您正在尝试复制您对 Alessandro 的第一条评论中所述的行为,您希望声明控件的Completed字段Entry以使用与按钮相同的事件处理程序。

例如,在 XAML 中:

<Entry Placeholder="Enter PIN Here"
       Completed="DefaultButton_Clicked"/>

<Button Text="OK"
        Clicked="DefaultButton_Clicked"/>

然后在你的代码后面:

void DefaultButton_Clicked(object sender, EventArgs e)
{
    //Do stuff
}

如果您希望像您回答的那样在后面的代码中完成这一切,我建议您这样做,这样您就可以取消订阅您的事件。您会发现使用匿名函数更加痛苦。您应该在 OnAppearing/OnDisappearing 中订阅和取消订阅您的事件。

void DefaultButton_Clicked(object sender, EventArgs e)
{
    if (model.MyCommand.CanExecute(null))
            model.MyCommand.Execute(null);
}

protected override void OnAppearing()
{
    base.OnAppearing();
    foreach (var child in ((StackLayout)Content).Children)
    {
        if (child is Entry entry)
            entry.Completed += DefaultButton_Clicked;
    }
}

protected override void OnDisappearing()
{
    base.OnDisappearing();
    foreach (var child in ((StackLayout)Content).Children)
    {
        if (child is Entry entry)
            entry.Completed -= DefaultButton_Clicked;
    }
}
于 2017-05-02T22:49:11.120 回答
0

我最终编写了连接每个条目的代码,以有条件地调用默认按钮的命令。在我的例子中,每个条目都在页面根目录的单个 StackLayout 中,因此页面的构造函数具有如下代码:

foreach (var child in ((StackLayout)Content).Children)
    if (child is Entry entry)
        entry.Completed += delegate {
            if (model.MyCommand.CanExecute(null))
                model.MyCommand.Execute(null);
        };
于 2017-05-03T17:50:30.160 回答
0

我们最终为完成的事件实现了入口行为。我们希望从 .xaml 中绑定它,并且能够在字段之间导航并在最后一个字段上提交。这需要一些研究,所以我在这里分享,希望它对其他人也有用:

            <Entry TabIndex="0" Placeholder="{ui:Resource ID_STR_USERNAME}" Text="{Binding Username, Mode=TwoWay}" Style="{StaticResource EntryText}">
                <Entry.Behaviors>
                    <behaviors:EntryCompletedBehavior />
                </Entry.Behaviors>
            </Entry>
            <Entry TabIndex="1" Placeholder="{ui:Resource ID_STR_PASSWORD_HINT}" IsPassword="True" Text="{Binding Password.Value, Mode=TwoWay}" Style="{StaticResource EntryText}">
                <Entry.Behaviors>
                    <behaviors:EntryTextChangeCommandBehavior Command="{Binding Password.ValidateCommand}" />
                    <behaviors:EntryCompletedBehavior Command="{Binding LoginCommand, Mode=TwoWay}" CommandParameter="{Binding Password}" />
                </Entry.Behaviors>
            </Entry>

和行为:

public class EntryCompletedBehavior : Behavior<Entry>
{
    public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(EntryCompletedBehavior), null);
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(EntryCompletedBehavior), null);
    public object CommandParameter
    {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    protected override void OnAttachedTo(Entry bindable)
    {
        base.OnAttachedTo(bindable);

        if(bindable.BindingContext != null)
            BindingContext = bindable.BindingContext;

        bindable.BindingContextChanged += Bindable_BindingContextChanged;

        bindable.Completed += Bindable_Completed;
    }
    protected override void OnDetachingFrom(Entry bindable)
    {
        base.OnDetachingFrom(bindable);

        bindable.BindingContextChanged -= Bindable_BindingContextChanged;

        bindable.Completed -= Bindable_Completed;
    }

    private void Bindable_Completed(object sender, System.EventArgs e)
    {
        if(sender is Entry entry)
        {
            var ix = entry.TabIndex;
            int allIndexesOnPage;
            var coll = entry.GetTabIndexesOnParentPage(out allIndexesOnPage);
            foreach(var item in coll)
            {
                if(ix < item.Key)
                {
                    item.Value.First().Focus();
                    return;
                }
            }
        }

        if(Command == null)
            return;

        if(Command.CanExecute(CommandParameter))
        {
            Command.Execute(CommandParameter);
        }
    }

    void Bindable_BindingContextChanged(object sender, EventArgs e)
    {
        base.OnBindingContextChanged();

        if(!(sender is BindableObject bindable))
            return;

        BindingContext = bindable.BindingContext;
    }
}

作为一个额外的好处,该行为可以单独使用,只是在标签索引字段之间导航。

基于这篇文章:https ://forums.xamarin.com/discussion/124714/how-to-fire-a-complete-event-from-viewmodel

于 2019-04-24T11:22:20.833 回答
-1

您不必说“在 Xamarin.Forms 中,如何将按钮指定为页面的默认按钮?” 因为 Xamarin.Forms 仅可视化特定于平台的控件。

您应该问“在 Android(或 iOS)中,如何将按钮指定为页面的默认按钮?”。

我认为这是焦点按钮,所以你可以尝试类似

Button b = new Button {Text = "This is the focused button"};
b.Focus();

但我不确定这一点。

在 Xamarin 论坛中查看这里

于 2017-05-01T18:18:05.057 回答