Xamarin Layout 无法获得焦点

Xamarin Layout can't receive focus

我正在尝试在 Xamarin Forms 中创建一个名为 FormElement 的复合视图组件,它由两个标签和一个条目组成:

<?xml version="1.0" encoding="UTF-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:custom="clr-namespace:Mynamespace;assembly=Mynamespace"
         x:Class="Mynamespace.Components.FormEntry">
    <StackLayout Orientation="Horizontal">
        <Label x:Name="formRequiredStar"
               IsVisible="{Binding IsRequired}"
               Text="*" TextColor="Red"
               FontSize="15"
               FontAttributes="Bold"
               Margin="-12,0,0,0"
               HorizontalOptions="Start" />
        <Label x:Name="formLabel"
               HorizontalOptions="Start"
               Text="{Binding LabelText}"
               TextColor="{Binding LabelTextColor}"
               FontSize="{Binding LabelTextFontSize}"
               FontAttributes="{Binding LabelTextFontStyle}" />
    </StackLayout>
    <Frame BorderColor="Black"
           CornerRadius="7"
           Padding="5,0"
           Margin="0,-3,0,0"
           HasShadow="false">
        <Entry x:Name="mainEntry"
               Keyboard="{Binding KeybdType}"
               Placeholder="{Binding EntryPlaceHolder}"
               TextColor="Black"
               FontSize="Default"
               HeightRequest="{Binding EntryHeight}" />
    </Frame>
</StackLayout>

接下来,我想在用户点击“完成”按钮时将焦点从 Entry 切换到 "next" 元素,所以我这样做:

    namespace Mynamespace.Components
    {
        public partial class FormEntry : StackLayout
        {
            public VisualElement NextFocus
            {
                get { return (VisualElement)GetValue(NextFocusProperty); }
                set { SetValue(NextFocusProperty, value); }
            }

            public static readonly BindableProperty NextFocusProperty =
                BindableProperty.Create(nameof(NextFocus),
                                        typeof(VisualElement),
                                        typeof(FormEntry),
                                        null,
                                     Xamarin.Forms.BindingMode.OneWay);

            public FormEntry()
            {
                InitializeComponent();
                BindingContext = this;

                mainEntry.Completed += (s, e) =>
                {
                    if (NextFocus != null)
                    {
                        NextFocus.Focus();
                    }
                };
            }
        }
    }

接下来,为了让 FormEntry 成为 NextFocus 的目标,我尝试添加

    this.Focused += (s,e) => { mainEntry.Focus(); };

到构造函数,但从未调用处理程序,我也尝试覆盖

    public new void Focus() {
        mainEntry.Focus();
    }

但是这个方法从来没有被调用过。布局 类 是 VisualElement 的后代,因此它们应该继承 Focused。我缺少有关 Layout 对象的某些信息吗?我可以理解 Layout 对象通常不是焦点的目标,但事件处理程序应该在那里,所以我应该能够使用它。

这是我如何在登录屏幕上使用 FormEntry 的示例:

    <!-- Email -->
    <controls:FormEntry x:Name="usernameEntry"
                        Margin="25,40,25,0"
                        IsRequired="true"
                        EntryHeight="40"
                        KeybdType="Email"
                        NextFocus="{x:Reference passwordEntry}"
                        LabelText="{il8n:Translate Emailorusername}"
                        EntryPlaceHolder="{il8n:Translate EnterUsername}">
    </controls:FormEntry>

    <!-- Password -->
    <controls:FormEntry x:Name="passwordEntry"
                        Margin="25,0,25,0"
                        IsRequired="true"
                        EntryHeight="40"
                        LabelText="{il8n:Translate Password}"
                        EntryPlaceHolder="{il8n:Translate EnterPassword}" />

我想你已经得到了 nextfocus 元素,你可以从 nextfocus 得到 mainEntry,像这样:

 public FormEntry ()
    {
        InitializeComponent ();
        BindingContext = this;

        mainEntry.Completed += (s, e) =>
        {
            if (NextFocus != null)
            {
                FormEntry formentry = (FormEntry)NextFocus;
                Entry entry = formentry.mainEntry;
                entry.Focus();
            }
        };
    }

然后你会发现你会得到焦点。