C# 即使编辑器不可见,Xamarin表单仍然存在(如何等待其他任务线程完成?)

C# 即使编辑器不可见,Xamarin表单仍然存在(如何等待其他任务线程完成?),c#,.net,multithreading,xamarin,xamarin.forms,C#,.net,Multithreading,Xamarin,Xamarin.forms,复制问题。 我正在使用Xamarin表单创建一个应用程序 <StackLayout> <Editor x:Name="Editor" Text="{Binding Text, Mode=TwoWay}"> </Editor> <Button x:Name="Button" Text="Complete"

复制问题。

我正在使用Xamarin表单创建一个应用程序

<StackLayout>
    <Editor x:Name="Editor"
            Text="{Binding Text, Mode=TwoWay}">
    </Editor>
    <Button x:Name="Button"
            Text="Complete"
            Command="{Binding CompleteCommand}" />
</StackLayout>
ContentView.IsVisible
属性更改如下时,我注册和注销
oneditor unfocused
方法

public partial class MyView : ContentView
{
    private void OnEditorUnfocused(object sender, FocusEventArgs e)
    {
        if (IsVisible)
        {
            Editor.Focus();
        }
    }
}
public partial class MyView : ContentView
{
    protected override void OnPropertyChanging([CallerMemberName] string propertyName = null)
    {
        // IsVisible changes from "True" to "False"
        if (propertyName.Equals("IsVisible") && IsVisible)
        {
            Editor.Unfocused -= OnEditorUnfocused;
            Editor.Unfocus();
        }

        base.OnPropertyChanging(propertyName);
    }

    protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // IsVisible changed from "False" to "True"
        if (propertyName.Equals("IsVisible") && IsVisible)
        {
            Editor.Unfocused += OnEditorUnfocused;
            Editor.Focus();
        }

        base.OnPropertyChanged(propertyName);
    }
}
这里我遇到了一个问题
Editor.Focus()
Editor.Unfocus()
不会立即应用。当
ContentView
不可见时,第一个
Editor.Focus()
不起作用。此外,当通过
按钮
ContentView.Visible
True
更改为
False
时,键盘仍保持在屏幕上

因此,我更改了我的代码,如下所示

public partial class MyView : ContentView
{
        private Task _focusEditorTask;
        private Task _unfocusEditorTask;

        public event EventHandler LostFocused;

        public MyView()
        {
            InitializeComponent();

            _focusEditorTask = _unfocusEditorTask = Task.CompletedTask;
        }

        private void OnEditorUnfocused(object sender, FocusEventArgs e)
        {
            if (IsVisible)
            {
                FocusEditor();
                Console.WriteLine($"<Unfocused> Editor: Focused {Editor.IsFocused}");
            }
        }

        private void FocusEditor()
        {
            _unfocusEditorTask.Wait();
            _focusEditorTask.Wait();

            _focusEditorTask = Task.Factory.StartNew(async () =>
            {
                Console.WriteLine($"<FocusEditor> START {Editor.IsFocused}");

                while (!Editor.IsFocused)
                {
                    Editor.Focus();
                    await Task.Delay(100);
                    Console.WriteLine($"<FocusEditor> PROGRESS {Editor.IsFocused}");
                }
                Console.WriteLine($"<FocusEditor> END {Editor.IsFocused}");
            });
        }

        private void UnfocusEditor()
        {
            _focusEditorTask.Wait();
            _unfocusEditorTask.Wait();

            _unfocusEditorTask = Task.Factory.StartNew(async () =>
            {
                Console.WriteLine($"<!UnfocusEditor> START {Editor.IsFocused}");
                while (Editor.IsFocused)
                {
                    Editor.Unfocus();
                    await Task.Delay(100);
                    Console.WriteLine($"<!UnfocusEditor> PROGRESS {Editor.IsFocused}");
                }

                Console.WriteLine($"<!UnfocusEditor> END {Editor.IsFocused}");

                return Task.CompletedTask;
            });
        }

        protected override void OnPropertyChanging([CallerMemberName] string propertyName = null)
        {
            if (propertyName.Equals("IsVisible") && IsVisible)
            {
                Console.WriteLine($"<IsVisibleChanging> InputView: IsVisible ({IsVisible}) -> {!IsVisible}");
                Editor.Unfocused -= OnEditorUnfocused;
                UnfocusEditor();
            }

            base.OnPropertyChanging(propertyName);
        }

        protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (propertyName.Equals("IsVisible") && IsVisible)
            {
                Console.WriteLine($"<IsVisibleChanged> InputView: IsVisible {!IsVisible} -> ({IsVisible})");
                Editor.Unfocused += OnEditorUnfocused;
                FocusEditor();
            }

            base.OnPropertyChanged(propertyName);
        }
}

2.通过
按钮将
ContentView.IsVisible
true更改为false
TextEditor:聚焦为False
开始错误
InputView:IsVisible(真)->False
//开始不应该开火。。。
开始错误
结束错误
//因此,即使ContnetView不可见,键盘也不会消失。
进展顺利
结束真实

  • Task.Factory.StartNew()。因为它在这里返回
    Task
    ,而不是
    Task
    ,然后必须等待内部
    Task
    。但您只需将其更改为
    Task.Run()
    ,并完全修复此问题。最后,这里不需要线程。只需使用异步调用即可完成此任务,而无需调用
    Task.Run()

  • 您正在从池线程与UI交互,这不好

  • 您使用
    .Wait()
    锁定UI线程,这是一种错误的做法,在某些情况下可能会冻结UI或导致死锁

  • 您可以订阅该活动一次

  • 我对Xamarin不太熟悉,但我很了解

    下面是我重写代码的尝试

    公共部分类MyView:ContentView
    {
    公共MyView()
    {
    初始化组件();
    }
    private void Oneditor未聚焦(对象发送方,聚焦目标e)
    {
    if(Editor.IsVisible)
    {
    Editor.Focus();
    WriteLine($“Editor:Focused{Editor.IsFocused}”);
    }
    }
    受保护的重写无效OnPropertyChanged([CallerMemberName]字符串propertyName=null)
    {
    base.OnPropertyChanged(propertyName);
    if(propertyName==nameof(IsVisible))
    {
    如果(可见)
    {
    Editor.Focus();
    Editor.Unfocused+=oneditor Unfocused;
    }
    其他的
    {
    Editor.Unfocused-=oneditor Unfocused;
    编辑:Unfocus();
    }
    WriteLine($“InputView:IsVisible{!IsVisible}->({IsVisible})”;
    }
    }
    }
    
    Editor.Unfocus()
    -如果您将焦点放在其他控件上,该怎么办?@aepot不幸的是,我已经尝试过了。聚焦
    按钮
    无效。我将您的解决方案应用于复制代码,并无限期地等待
    FocusEditorAsync()
    它一定是由
    while
    循环引起的<代码>编辑器。IsFocused
    不会更改!我认为这不仅仅与异步编程有关。。。所以悲哀的是,@ibocon可能会作为初始关注点有所帮助。您提供的答案,仅在出现
    页面时有效一次。我所做的是更改按钮单击时可见的
    。初始值
    可见
    。另外,@ibocon中不存在
    OnAppearing()
    方法。是否可以检查
    Editor.IsVisible
    而不是视图的
    IsVisible
    ?更新了答案。@ibocon在Github上应用了代码您忘记在那里更新OnPropertyChangedOnPropertyChanged。顺便说一句,您可以完全删除这些方法。可能无限
    Wait
    导致死锁,因为那里不允许
    .Wait()
    。如我所示,将事件子选项移动到构造函数中。
        <IsVisibleChanged> InputView: IsVisible False -> (True)
        <FocusTextEditor> START False
        <FocusTextEditor> PROGRESS False
        <FocusTextEditor> PROGRESS True
        <FocusTextEditor> END True
    
        <Unfocused> TextEditor: Focused False
        <FocusTextEditor> START False
        <IsVisibleChanging> InputView: IsVisible (True) -> False
        // START should not fire...
        <!UnfocusTextEditor> START False
        <!UnfocusTextEditor> END False
        // because of this, keyboard does not disappear even ContnetView is not visible.
        <FocusTextEditor> PROGRESS True
        <FocusTextEditor> END True