Я пытаюсь использовать PopUpService для отображения всплывающего окна, которое, с одной стороны, принимает параметр и возвращает его.
К сожалению, после возвращения всплывающее окно, похоже, не завершает асинхронную задачу, и я не знаю, почему. Я предполагаю, что требуется какой-то CancellationToken.
Вот необходимый код: В одной ViewModel PopUp вызывается:
public partial class SomeViewModel
{
private readonly IPopupService _popupService;
// ...
public SomeViewModel(
IPopupService popupService)
{
_popupService = popupService;
}
[RelayCommand]
private async Task OnCallingPopUpAsync()
{
var result = await _popupService.ShowPopupAsync<PopupViewModel>(
onPresenting: viewModel => viewModel.TransferValue(true)
);
if (result is bool boolResult)
Debug.WriteLine("Success!!");
else
return;
}
}
В PopupViewModel получено значение. Кроме того, в представлении можно просто закрыть PopupView, нажав кнопку и вызвав ClosePopupCommand:
public partial class PopupViewModel : Popup
{
public ImagePickerViewModel() {}
[RelayCommand]
private async Task OnClosePopup()
{
await CloseAsync(true);
}
public void TransferValue(bool value)
{
Debug.WriteLine($"The transferred value is {value}");
}
}
Тем не менее, всплывающее окно не закрывается.
Я попробовал передать CancellationToken (аналогично тому, как это делается в MS Docs, например:
[RelayCommand]
private async Task OnClosePopup()
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
await CloseAsync(true, token: cts.Token);
}
Однако это привело к исключению: System.Threading.Tasks.TaskCanceledException: 'A task was canceled.'
Как я могу это решить?
Что такое версия dotnet и MAUI и какую платформу iOS или Android вы тестируете?
Шаблон Модель-Представление-ViewModel (MVVM) обеспечивает разделение между тремя уровнями программного обеспечения — пользовательским интерфейсом XAML, называемым представлением, базовыми данными, называемыми моделью, и посредником между представлением и моделью, называемым моделью представления.
Таким образом, использование CloseAsync()
во ViewModel не приведет к закрытию всплывающего окна.
Самый простой способ — закрыть всплывающее окно в коде.
Предположим, мы закрываем всплывающее окно при нажатии кнопки,
private async void Button_Clicked(object sender, EventArgs e)
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
await CloseAsync(true, token: cts.Token);
}
Или, если вы хотите закрыть всплывающее окно во ViewModel, вы можете попробовать передать всплывающее окно через CommandParameter
, используя Относительную привязку,
<Button Text = "click me" Command = "{Binding ClosePopupCommand}" CommandParameter = "{Binding Source = {RelativeSource AncestorType = {x:Type toolkit:Popup}}}"/>
и разрешите его и закройте в ViewModel,
[RelayCommand]
private void OnClosePopup(object o)
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
var p = o as MyPopupPage;
p.CloseAsync(false, token: cts.Token);
}
Обновлять
Если относительная привязка не работает, вы также можете попробовать выражение x:Reference Binding.
Установите имя всплывающего окна «это»,
<toolkit:Popup
...
x:Name = "this">
...
<Button Text = "click me" Command = "{Binding ClosePopupCommand}" CommandParameter = "{Binding Source = {x:Reference this}}"/>
и передайте всплывающее окно, используя выражение x:Reference Binding, и закройте его в ViewModel,
[RelayCommand]
private void OnClosePopup(object o)
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
var p = o as MyPopupPage;
p.CloseAsync(false, token: cts.Token);
}
Надеюсь, поможет!
Это странно. Это работает на моей стороне. Вы зарегистрировали всплывающее окно и модель представления, builder.Services.AddTransientPopup< MyPopupPage, PopupViewModel >();
?
@user25033240 user25033240 Если способы, описанные в моем ответе, не работают, могу ли я узнать, какую версию и платформу .NET вы используете? Кстати, я также обновляю новый способ использования выражения привязки x:Reference
.
Да, я зарегистрировал всплывающее окно // Register PupUps builder.Services.AddTransientPopup<ImagePickerView, ImagePickerViewModel>();
для MauiAppBuilder.
Я нацелен на net8.0-windows10.0.19041.0. Вы это имели в виду?
Только что протестировал ваше обновление! Привязка x:Refrence работает!! Большое спасибо!
Когда я пытаюсь использовать решение ViewModel (которое я предпочитаю), я получаю при вызове
p.CloseAsync(false, token
: cts.Token)` исключениеSystem.NullReferenceException: 'Object reference not set to an instance of an object.'
Знаете, почему?