通过后退按钮取消 MvxAppCompatDialogFragment 不完全有效
MvxAppCompatDialogFragment cancellation via Back button is not completely working
通过后退按钮关闭 MvxAppCompatDialogFragment
似乎并不完全有效。关闭对话框后,我单击以触发对话框的按钮仍处于禁用状态。这几乎就像 Task
被卡住了。如果我更改为 MvxDialogFragment
然后后退按钮将按预期关闭对话框,并且我单击以触发对话框的按钮在对话框关闭后再次启用。我正在尝试使用 MvxAppCompatDialogFragment
,因为我正在使用 MvxAppCompatActivity
。我做错了什么或者这是 MvvmCross 5.2.1 中的错误?
这是视图模型:
public class ConfirmationViewModel : MvxViewModel<ConfirmationConfiguration, bool?>, IMvxLocalizedTextSourceOwner
{
private readonly IMvxNavigationService _mvxNavigationService;
public ConfirmationViewModel(IMvxNavigationService mvxNavigationService)
{
_mvxNavigationService = mvxNavigationService;
}
public override void Prepare([NotNull] ConfirmationConfiguration parameter)
{
if (parameter == null) throw new ArgumentNullException(nameof(parameter));
Title = parameter.Title;
Body = parameter.Body;
PositiveCommandText = !string.IsNullOrEmpty(parameter.YesCommandText)
? parameter.YesCommandText
: LocalizedTextSource.GetText("Yes");
NegativeCommandText = !string.IsNullOrEmpty(parameter.NoCommandText)
? parameter.NoCommandText
: LocalizedTextSource.GetText("No");
}
private bool? _confirmationResult;
public bool? ConfirmationResult
{
get => _confirmationResult;
private set => SetProperty(ref _confirmationResult, value);
}
private string _title;
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
private string _body;
public string Body
{
get => _body;
set => SetProperty(ref _body, value);
}
private string _positiveCommandText;
public string PositiveCommandText
{
get => _positiveCommandText;
set => SetProperty(ref _positiveCommandText, value);
}
private string _negativeCommandText;
public string NegativeCommandText
{
get => _negativeCommandText;
set => SetProperty(ref _negativeCommandText, value);
}
private IMvxAsyncCommand _yesCommand;
public IMvxAsyncCommand PositiveCommand => _yesCommand ?? (_yesCommand = new MvxAsyncCommand(OnPositiveCommandAsync));
private async Task OnPositiveCommandAsync()
{
ConfirmationResult = true;
await _mvxNavigationService.Close(this, ConfirmationResult);
}
private IMvxAsyncCommand _noCommand;
public IMvxAsyncCommand NegativeCommand => _noCommand ?? (_noCommand = new MvxAsyncCommand(OnNegativeCommandAsync));
private async Task OnNegativeCommandAsync()
{
ConfirmationResult = false;
await _mvxNavigationService.Close(this, ConfirmationResult);
}
public IMvxLanguageBinder LocalizedTextSource => new MvxLanguageBinder("", GetType().Name);
public IMvxLanguageBinder TextSource => LocalizedTextSource;
}
public class ConfirmationConfiguration
{
public string Title { get; set; }
public string Body { get; set; }
public string YesCommandText { get; set; }
public string NoCommandText { get; set; }
}
视图如下:
[MvxDialogFragmentPresentation(Cancelable = true)]
[Register(nameof(ConfirmationFragment))]
public class ConfirmationFragment : MvxAppCompatDialogFragment<ConfirmationViewModel>
{
public ConfirmationFragment()
{
RetainInstance = true;
}
public ConfirmationFragment(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
RetainInstance = true;
}
public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
var builder = new AlertDialog.Builder(Activity)
.SetTitle(ViewModel.Title)
.SetMessage(ViewModel.Body)
.SetPositiveButton(ViewModel.PositiveCommandText, OnPositiveButton)
.SetNegativeButton(ViewModel.NegativeCommandText, OnNegativeButton);
return builder.Create();
}
private async void OnNegativeButton(object sender, DialogClickEventArgs e)
{
if (ViewModel.NegativeCommand.CanExecute())
{
await ViewModel.NegativeCommand.ExecuteAsync();
}
}
private async void OnPositiveButton(object sender, DialogClickEventArgs e)
{
if (ViewModel.PositiveCommand.CanExecute())
{
await ViewModel.PositiveCommand.ExecuteAsync();
}
}
}
我正在导航到这样的对话框:
var confirmation = await Mvx.Resolve<IMvxNavigationService>().Navigate<ConfirmationViewModel, ConfirmationConfiguration, bool?>(
new ConfirmationConfiguration()
{
Body = "Hello, World!",
Title = "Testing"
});
如果我将基数 class 从 MvxAppCompatDialogFragment
更改为 MvxDialogFragment
那么一切都会按预期工作。
我已经调查过了。发生的情况是,当您按下后退按钮时,它会在不调用 NavigationSerivce.Close()
的情况下关闭视图。这可以防止调用结果 Task
并设置或取消操作。我不确定这是错误还是只是行为。解决方法是从 ConfirmationViewModel
ViewDissapearing
调用 Close
,或者自己取消 Task
。
这确实是 MvvmCross v5.2.1 中的一个问题(感谢报告!)。作为目前的解决方法,您可以在 DialogFragment class:
中添加此代码
public override void OnCancel(IDialogInterface dialog)
{
base.OnCancel(dialog);
ViewModel?.ViewDestroy();
}
public override void DismissAllowingStateLoss()
{
base.DismissAllowingStateLoss();
ViewModel?.ViewDestroy();
}
public override void Dismiss()
{
base.Dismiss();
ViewModel?.ViewDestroy();
}
通过后退按钮关闭 MvxAppCompatDialogFragment
似乎并不完全有效。关闭对话框后,我单击以触发对话框的按钮仍处于禁用状态。这几乎就像 Task
被卡住了。如果我更改为 MvxDialogFragment
然后后退按钮将按预期关闭对话框,并且我单击以触发对话框的按钮在对话框关闭后再次启用。我正在尝试使用 MvxAppCompatDialogFragment
,因为我正在使用 MvxAppCompatActivity
。我做错了什么或者这是 MvvmCross 5.2.1 中的错误?
这是视图模型:
public class ConfirmationViewModel : MvxViewModel<ConfirmationConfiguration, bool?>, IMvxLocalizedTextSourceOwner
{
private readonly IMvxNavigationService _mvxNavigationService;
public ConfirmationViewModel(IMvxNavigationService mvxNavigationService)
{
_mvxNavigationService = mvxNavigationService;
}
public override void Prepare([NotNull] ConfirmationConfiguration parameter)
{
if (parameter == null) throw new ArgumentNullException(nameof(parameter));
Title = parameter.Title;
Body = parameter.Body;
PositiveCommandText = !string.IsNullOrEmpty(parameter.YesCommandText)
? parameter.YesCommandText
: LocalizedTextSource.GetText("Yes");
NegativeCommandText = !string.IsNullOrEmpty(parameter.NoCommandText)
? parameter.NoCommandText
: LocalizedTextSource.GetText("No");
}
private bool? _confirmationResult;
public bool? ConfirmationResult
{
get => _confirmationResult;
private set => SetProperty(ref _confirmationResult, value);
}
private string _title;
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
private string _body;
public string Body
{
get => _body;
set => SetProperty(ref _body, value);
}
private string _positiveCommandText;
public string PositiveCommandText
{
get => _positiveCommandText;
set => SetProperty(ref _positiveCommandText, value);
}
private string _negativeCommandText;
public string NegativeCommandText
{
get => _negativeCommandText;
set => SetProperty(ref _negativeCommandText, value);
}
private IMvxAsyncCommand _yesCommand;
public IMvxAsyncCommand PositiveCommand => _yesCommand ?? (_yesCommand = new MvxAsyncCommand(OnPositiveCommandAsync));
private async Task OnPositiveCommandAsync()
{
ConfirmationResult = true;
await _mvxNavigationService.Close(this, ConfirmationResult);
}
private IMvxAsyncCommand _noCommand;
public IMvxAsyncCommand NegativeCommand => _noCommand ?? (_noCommand = new MvxAsyncCommand(OnNegativeCommandAsync));
private async Task OnNegativeCommandAsync()
{
ConfirmationResult = false;
await _mvxNavigationService.Close(this, ConfirmationResult);
}
public IMvxLanguageBinder LocalizedTextSource => new MvxLanguageBinder("", GetType().Name);
public IMvxLanguageBinder TextSource => LocalizedTextSource;
}
public class ConfirmationConfiguration
{
public string Title { get; set; }
public string Body { get; set; }
public string YesCommandText { get; set; }
public string NoCommandText { get; set; }
}
视图如下:
[MvxDialogFragmentPresentation(Cancelable = true)]
[Register(nameof(ConfirmationFragment))]
public class ConfirmationFragment : MvxAppCompatDialogFragment<ConfirmationViewModel>
{
public ConfirmationFragment()
{
RetainInstance = true;
}
public ConfirmationFragment(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
RetainInstance = true;
}
public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
var builder = new AlertDialog.Builder(Activity)
.SetTitle(ViewModel.Title)
.SetMessage(ViewModel.Body)
.SetPositiveButton(ViewModel.PositiveCommandText, OnPositiveButton)
.SetNegativeButton(ViewModel.NegativeCommandText, OnNegativeButton);
return builder.Create();
}
private async void OnNegativeButton(object sender, DialogClickEventArgs e)
{
if (ViewModel.NegativeCommand.CanExecute())
{
await ViewModel.NegativeCommand.ExecuteAsync();
}
}
private async void OnPositiveButton(object sender, DialogClickEventArgs e)
{
if (ViewModel.PositiveCommand.CanExecute())
{
await ViewModel.PositiveCommand.ExecuteAsync();
}
}
}
我正在导航到这样的对话框:
var confirmation = await Mvx.Resolve<IMvxNavigationService>().Navigate<ConfirmationViewModel, ConfirmationConfiguration, bool?>(
new ConfirmationConfiguration()
{
Body = "Hello, World!",
Title = "Testing"
});
如果我将基数 class 从 MvxAppCompatDialogFragment
更改为 MvxDialogFragment
那么一切都会按预期工作。
我已经调查过了。发生的情况是,当您按下后退按钮时,它会在不调用 NavigationSerivce.Close()
的情况下关闭视图。这可以防止调用结果 Task
并设置或取消操作。我不确定这是错误还是只是行为。解决方法是从 ConfirmationViewModel
ViewDissapearing
调用 Close
,或者自己取消 Task
。
这确实是 MvvmCross v5.2.1 中的一个问题(感谢报告!)。作为目前的解决方法,您可以在 DialogFragment class:
中添加此代码public override void OnCancel(IDialogInterface dialog)
{
base.OnCancel(dialog);
ViewModel?.ViewDestroy();
}
public override void DismissAllowingStateLoss()
{
base.DismissAllowingStateLoss();
ViewModel?.ViewDestroy();
}
public override void Dismiss()
{
base.Dismiss();
ViewModel?.ViewDestroy();
}