C# 即使编辑器不可见,Xamarin表单仍然存在(如何等待其他任务线程完成?)
复制问题。 我正在使用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"
<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上应用了代码您忘记在那里更新OnPropertyChanged
和OnPropertyChanged
。顺便说一句,您可以完全删除这些方法。可能无限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