【问题标题】:Can't move to Next Entry and Set Focus on it in Xamarin无法移动到下一个条目并在 Xamarin 中设置焦点
【发布时间】:2020-11-27 21:20:44
【问题描述】:

在我的 Xamarin 应用程序中,我希望在条目中输入值时,它会自动查找下一个条目字段并将焦点设置为它。

我可以使用键盘上的下一步按钮移至下一个条目,但我想在输入值时自动将焦点设置在下一个条目上(最大长度为 1 个字符)。

我也试过this code,但没用。

.xml

xmlns:behaviors="clr-namespace:Mobile.App.Behaviors"
<Grid Grid.Column="1">
    <Frame CornerRadius="12">
        <BoxView Color="#EEEEEE" />
    </Frame>
    <Entry
        x:Name="PasswordOne"
        Text="{Binding PasswordOne}"
        IsPassword="True"
        Keyboard="Numeric"
        MaxLength="1"
        ReturnType="Next"
        Unfocused="Password_Unfocused">
        <Entry.Behaviors>
            <behaviors:FocusOnReturnBehavior FocusOn="{x:Reference PasswordTwo}" />
        </Entry.Behaviors>
    </Entry>
</Grid>

<Grid Grid.Column="2">
    <Frame CornerRadius="12">
        <BoxView Color="#EEEEEE" />
    </Frame>
    <Entry
        x:Name="PasswordTwo"
        Text="{Binding PasswordTwo}"
        IsPassword="True"
        Keyboard="Numeric"
        MaxLength="1"
        ReturnType="Next"
        Unfocused="Password_Unfocused">
        <Entry.Behaviors>
            <behaviors:FocusOnReturnBehavior FocusOn="{x:Reference PasswordThree}" />
        </Entry.Behaviors>
    </Entry>
</Grid>

FocusOnReturnBehavior.cs

public class FocusOnReturnBehavior : Behavior<Entry>
{
    public VisualElement FocusOn { get; set; }

    protected override void OnAttachedTo(Entry bindable)
    {
        base.OnAttachedTo(bindable);
        bindable.Completed += BindableOnCompleted;
    }


    protected override void OnDetachingFrom(Entry bindable)
    {
        base.OnDetachingFrom(bindable);
        bindable.Completed -= BindableOnCompleted;
    }

    private void BindableOnCompleted(object sender, EventArgs args)
    {
        FocusOn?.Focus();
    }
}

【问题讨论】:

  • 您尝试过调试它吗?你的行为有依恋吗?是否分配了事件?处理程序是否被调用?
  • 我用@FabriBertani 更新了行为并对其进行了调试。 OnAttachedTo() 在我从页面导航到 PasswordPage 时触发,但在 PasswordPage 中使用 Entry 时,未触发行为(断点) ..

标签: c# .net xamarin xamarin.forms


【解决方案1】:

我将更改以下行为:

public class FocusOnReturnBehavior : Behavior<Entry>
{
    public static readonly BindableProperty FocusOnProperty = BindableProperty.Create(
        nameof(FocusOn),
        typeof(object),
        typeof(FocusOnReturnBehavior),
        null
    );

    public object FocusOn
    {
        get => (object)GetValue(FocusOnProperty);
        set => SetValue(FocusOnProperty, value);
    }

    protected override void OnAttachedTo(Entry bindable)
    {
        base.OnAttachedTo(bindable);
        bindable.Completed += BindableOnCompleted;
    }


    protected override void OnDetachingFrom(Entry bindable)
    {
        base.OnDetachingFrom(bindable);
        bindable.Completed -= BindableOnCompleted;
    }

    private void BindableOnCompleted(object sender, EventArgs args)
    {
        if (FocusOn == null)
            return;
        else if (FocusOn is Entry entry)
            entry.Focus();
        else if (FocusOn is Button button)
        {
            button.Focus();
            button.Command.Execute(null)
        }
        else if (FocusOn is VisualElement element)
            element.Focus();
    }
}

【讨论】:

  • 感谢您的回复.. 但仍然没有任何改变..
  • 我也调试过。 OnAttachedTo() 在我从页面导航到 PasswordPage 时触发,但在 PasswordPage 中使用 Entry 时,未触发行为(断点) ..
【解决方案2】:

在您的问题中,当您在条目中输入 1 个字符时,不会触发 completed 事件。

当当前entry.text.length 为 1 时,您可以将条目添加到列表中并让下一个条目成为焦点。

我写了一个简单的例子来实现这一点:

<StackLayout>
    <!-- Place new controls here -->
    <Entry  MaxLength="1" TextChanged="Entry_TextChanged"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
    <Entry  MaxLength="1" TextChanged="Entry_TextChanged"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
    <Entry  MaxLength="1" TextChanged="Entry_TextChanged"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
    <Entry  MaxLength="1" TextChanged="Entry_TextChanged"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
</StackLayout>

在后面的代码中:

private void Entry_TextChanged(object sender, TextChangedEventArgs e)
{

    var entry = sender as Entry; // .. and check for null

    if (entry.Text.Length == 1)
    {
        var list = (entry.Parent as StackLayout).Children; //assumes a StackLayout
        var index = list.IndexOf(entry); // 
        var nextIndex = (index + 1) >= list.Count ? 0 : index + 1; //first or next element?
        var next = list.ElementAt(nextIndex);
        next?.Focus();
    }

}

更新:

在后面的代码中:

public partial class MainPage : ContentPage
{

    public List<Entry> myEntryList { get; set; }
    public MainPage()
    {
        InitializeComponent();

        myEntryList = new List<Entry>();
        myEntryList.Add(this.PasswordOne);
        myEntryList.Add(this.PasswordTwo);
    }

    private void Entry_TextChanged(object sender, TextChangedEventArgs e)
    {

        var entry = sender as Entry; // .. and check for null

        if (entry.Text.Length >= 1)
        {                
            var index = myEntryList.IndexOf(entry); // 
            var nextIndex = (index + 1) >= myEntryList.Count ? 0 : index + 1; //first or next element?
            var next = myEntryList.ElementAt(nextIndex);
            next?.Focus();
        }
    }
}

在 Xaml 中:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="2*" />
        <RowDefinition Height="100" />
        <RowDefinition Height="100" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="1">
        <Frame CornerRadius="12">
            <BoxView Color="#EEEEEE" />
        </Frame>
        <Entry
            x:Name="PasswordOne"
            Text="PasswordOne"
            IsPassword="True"
            Keyboard="Numeric"
            MaxLength="1"
            ReturnType="Next"
           
            TextChanged="Entry_TextChanged"
            >
        </Entry>
    </Grid>

    <Grid Grid.Column="2">
        <Frame CornerRadius="12">
            <BoxView Color="#EEEEEE" />
        </Frame>
        <Entry
            x:Name="PasswordTwo"
            Text="PasswordTwo"
            IsPassword="True"
            Keyboard="Numeric"
            MaxLength="1"
            ReturnType="Next"
                            
            TextChanged="Entry_TextChanged"

            >   
        </Entry>
    </Grid>

</Grid>

【讨论】:

  • EventHandler "Entry_Completed" with correct signature not found.. 这是在哪里定义的?
  • 去掉就好了,我没有使用“Entry_Completed”。
  • 正如我在答案You can add you entries to a list 中所说,为每个条目命名并将它们添加到列表中,然后在Entry_TextChanged 事件中使用此列表。我在答案中的代码是一个向您展示如何实现这一目标的示例。
  • 如果你需要,我可以用你的 xaml 代码更新我的答案。
  • 检查条目的名称,例如 If (next == lastEntry), STOP。
猜你喜欢
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多