C# Xamarin Android-从OnOptions ItemSelected()调用确认对话框弹出窗口

C# Xamarin Android-从OnOptions ItemSelected()调用确认对话框弹出窗口,c#,xamarin.android,async-await,android-alertdialog,android-toolbar,C#,Xamarin.android,Async Await,Android Alertdialog,Android Toolbar,我正在Android平台上使用Xamarin,C#,当用户单击我顶部操作栏上的图标时,需要弹出一个是/否确认对话框。 假设这个图标会触发一个“删除表中的所有行”,这个操作需要用户的确认 我应该如何实现这个自定义对话框弹出窗口并获得用户的选择? 有没有可行的例子 以下代码来自我的MainActivity:ActionBarActivity,以下代码无法按预期工作。 不显示弹出对话框,几秒钟后应用程序停止响应 public override bool OnOptionsItemSelected(IM

我正在Android平台上使用Xamarin,C#,当用户单击我顶部操作栏上的图标时,需要弹出一个是/否确认对话框。 假设这个图标会触发一个“删除表中的所有行”,这个操作需要用户的确认

我应该如何实现这个自定义对话框弹出窗口并获得用户的选择? 有没有可行的例子

以下代码来自我的MainActivity:ActionBarActivity,以下代码无法按预期工作。 不显示弹出对话框,几秒钟后应用程序停止响应

public override bool OnOptionsItemSelected(IMenuItem item)
{
    var res = OnOptionsItemSelectedAsync(item);

    if (res.Result) return true;
    else return false;
}

public async Task<bool> OnOptionsItemSelectedAsync(IMenuItem item)
{
    var tcs = new TaskCompletionSource<bool>();
    tcs.SetResult(true);

    switch (item.ItemId)
    {
        case Resource.Id.action_delete:
            // Show Yes/No confirmation dialog here, blocking (sync)
            string dialogResponse = await DisplayCustomDialog("Confirm delete", "Are you sure you want to delete all rows?", "YES", "NO");
            //string dialogResponse = DisplayCustomDialog("Confirm delete", "Are you sure you want to delete all rows?", "YES", "NO");
            if ("YES" == dialogResponse)
            {
                //...
                Toast.MakeText(this, "Deleted!", ToastLength.Short).Show();
            }
            break;
        //...
        default: break;
    }
    return tcs.Task.Result;
}

private Task<string> DisplayCustomDialog(string dialogTitle, string dialogMessage, string dialogPositiveBtnLabel, string dialogNegativeBtnLabel)
{
    var tcs = new TaskCompletionSource<string>();

    Android.App.AlertDialog.Builder alert = new Android.App.AlertDialog.Builder(this);
    alert.SetTitle(dialogTitle);
    alert.SetMessage(dialogMessage);
    alert.SetPositiveButton(dialogPositiveBtnLabel, (senderAlert, args) => {
        //Toast.MakeText(this, dialogPositiveBtnLabel + "!", ToastLength.Short).Show();
        tcs.SetResult(dialogPositiveBtnLabel);
    });
    alert.SetNegativeButton(dialogNegativeBtnLabel, (senderAlert, args) => {
        //Toast.MakeText(this, dialogNegativeBtnLabel + "!", ToastLength.Short).Show();
        tcs.SetResult(dialogNegativeBtnLabel);
    });
    Dialog dialog = alert.Create();
    dialog.Show();

    // Test with DisplayAlert()
    //var answer = await DisplayAlert(dialogTitle, dialogMessage, dialogPositiveBtnLabel, dialogNegativeBtnLabel);
    //Debug.WriteLine("Answer: " + answer);

    return tcs.Task;
}
public override bool OnOptionsItemSelected(IMenuItem)
{
var res=onOptions ItemSelectedAsync(项目);
如果(res.Result)返回true;
否则返回false;
}
选项项SelectedAsync(IMenuItem项)上的公共异步任务
{
var tcs=new TaskCompletionSource();
tcs.SetResult(真);
开关(item.ItemId)
{
案例资源.Id.action\u删除:
//在此处显示是/否确认对话框,阻止(同步)
string dialogResponse=Wait DisplayCustomDialog(“确认删除”、“确实要删除所有行吗?”、“是”、“否”);
//string dialogResponse=DisplayCustomDialog(“确认删除”、“确实要删除所有行吗?”、“是”、“否”);
如果(“是”==对话框响应)
{
//...
Toast.MakeText(这个“已删除!”,ToastLength.Short.Show();
}
打破
//...
默认:中断;
}
返回tcs.Task.Result;
}
专用任务显示自定义对话框(字符串对话框标题、字符串对话框消息、字符串对话框正EBTNLabel、字符串对话框负EBTNLabel)
{
var tcs=new TaskCompletionSource();
Android.App.AlertDialog.Builder alert=新的Android.App.AlertDialog.Builder(此);
alert.SetTitle(dialogTitle);
alert.SetMessage(dialogMessage);
alert.SetPositiveButton(对话框PositiveButton标签,(senderAlert,args)=>{
//Toast.MakeText(这是对话框positivebtnlab+“!”,ToastLength.Short).Show();
tcs.SetResult(对话框positivebtnlab);
});
alert.SetNegativeButton(对话框NegativeButton标签,(senderAlert,args)=>{
//Toast.MakeText(此对话框为NegativeBTNLABLE+“!”,ToastLength.Short.Show();
tcs.SetResult(对话框NegativeBtnLabel);
});
Dialog=alert.Create();
dialog.Show();
//使用DisplayAlert()进行测试
//var answer=等待显示警报(dialogTitle、dialogMessage、dialogPositiveBtnLabel、dialogNegativeBtnLabel);
//Debug.WriteLine(“回答:+Answer”);
返回tcs.Task;
}

您已经对等待用户选择选项的代码进行了注释,因此响应将始终为空。按以下方式更改代码:

private Task<string> DisplayCustomDialog(string dialogTitle, string dialogMessage, string dialogPositiveBtnLabel, string dialogNegativeBtnLabel)
{
    var tcs = new TaskCompletionSource<string>();

    Android.App.AlertDialog.Builder alert = new Android.App.AlertDialog.Builder(this);
    alert.SetTitle(dialogTitle);
    alert.SetMessage(dialogMessage);
    alert.SetPositiveButton(dialogPositiveBtnLabel, (senderAlert, args) => {
        tcs.SetResult(dialogPositiveBtnLabel);
    });

    alert.SetNegativeButton(dialogNegativeBtnLabel, (senderAlert, args) => {
        tcs.SetResult(dialogNegativeBtnLabel);
    });

    Dialog dialog = alert.Create();
    dialog.Show();

    return tcs.Task;
}
private Task DisplayCustomDialog(字符串对话框标题、字符串对话框消息、字符串对话框正EBTNLabel、字符串对话框负EBTNLabel)
{
var tcs=new TaskCompletionSource();
Android.App.AlertDialog.Builder alert=新的Android.App.AlertDialog.Builder(此);
alert.SetTitle(dialogTitle);
alert.SetMessage(dialogMessage);
alert.SetPositiveButton(对话框PositiveButton标签,(senderAlert,args)=>{
tcs.SetResult(对话框positivebtnlab);
});
alert.SetNegativeButton(对话框NegativeButton标签,(senderAlert,args)=>{
tcs.SetResult(对话框NegativeBtnLabel);
});
Dialog=alert.Create();
dialog.Show();
返回tcs.Task;
}
然后,实现async helper以同步执行任务:

string dialogResponse = AsyncHelpers.RunSync<string>(() => DisplayCustomDialog("Confirm delete", "Are you sure you want to delete all rows?", "YES", "NO"));
string dialogResponse=asynchhelpers.RunSync(()=>DisplayCustomDialog(“确认删除”、“是否确实要删除所有行?”、“是”、“否”));

需要使用帮助程序是因为如果您等待()任务结束,这将阻止de UI线程,因为UI线程是显示对话框的负责人,因此会出现死锁,应用程序将挂起。

是的,您提到的异步帮助程序似乎可以完成这项工作(我还没有测试它),但这是一种复杂的方法。如果你想阻止代码响应,这是唯一的方法,Android上的警报是异步的,它们不会阻止,当用户选择一个选项时,它们会执行一个委托,因此你需要一种创建异步任务并等待它的方法,除非将代码更改为完全异步,否则没有简单的解决方案,这将是最好的解决方案。要解决我的用例(在用户单击顶部操作栏上的图标并通过AlertDialog是/否弹出窗口确认后删除表行,我将AlertDialog代码移动到我的OnOptions ItemSelected()中)。在alert.SetPositiveButton的Click处理程序中,我对表行执行删除操作。似乎是这样工作的,而且非常简单,因为我不必处理sync/async。基本上,我在AlertDialog的肯定按钮的OnClick处理程序中执行我的操作。这种方法有什么缺点吗?好吧,您所做的更改已经完成了etely修改了您发布的代码,您的OnOptions ItemSelected现在不能返回任何内容或始终返回true/false,因为您没有等待响应。我认为一个问题是,如果您在结束前调用OnOptions ItemSelected两次,它将执行两次,不确定在显示另一个警报时调用警报的行为…Gusman,谢谢你的反馈。我已经设置了一个信号量,以防止出现你描述的情况。应该可以,只有在未设置标志的情况下才会执行该操作。