在 Xamarin.Forms 中,如何将按钮指定为页面的默认按钮?
例如,在 UWP 上,当用户在页面具有焦点时按下 Enter 键时,应触发DefaultButton的单击处理程序。
在 Xamarin.Forms 中,如何将按钮指定为页面的默认按钮?
例如,在 UWP 上,当用户在页面具有焦点时按下 Enter 键时,应触发DefaultButton的单击处理程序。
假设您正在尝试复制您对 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;
}
}
我最终编写了连接每个条目的代码,以有条件地调用默认按钮的命令。在我的例子中,每个条目都在页面根目录的单个 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);
};
我们最终为完成的事件实现了入口行为。我们希望从 .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
您不必说“在 Xamarin.Forms 中,如何将按钮指定为页面的默认按钮?” 因为 Xamarin.Forms 仅可视化特定于平台的控件。
您应该问“在 Android(或 iOS)中,如何将按钮指定为页面的默认按钮?”。
我认为这是焦点按钮,所以你可以尝试类似
Button b = new Button {Text = "This is the focused button"};
b.Focus();
但我不确定这一点。
在 Xamarin 论坛中查看这里