После возврата на страницу XAML UWP ContentDialog.RunAsyn c () вызывает «Значение не попадает в ожидаемый диапазон». - PullRequest
2 голосов
/ 17 января 2020

Используя UWP и MVVM Light, у меня есть программа, которая использует одну и ту же страницу и ViewModel несколько раз с разными данными. Каждой паре страница / модель представления назначается соответствующий идентификатор, чтобы им было легче ссылаться друг на друга. На странице есть кнопка, которая показывает ContentDialog.

При первом открытии одной из страниц ContentDialog открывается правильно, но если страницу оставить, а затем вернуть, вызов ShowAsyn c для ContentDialog вызывает очень описательное ArgumentException: «Значение не попадают в ожидаемый диапазон. '

ViewModel

public RelayCommand LockButtonCommand => new RelayCommand(() => lockButtonClicked());

private void lockButtonClicked()
{
    System.Diagnostics.Debug.WriteLine("Button clicked on VM " + myID);
    Messenger.Default.Send(new ShowPassphraseDialogMessage(), myID);
}

Код страницы позади

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (!idsRegistered.Contains(myID))
    {
        Messenger.Default.Register<ShowPassphraseDialogMessage>(this, myID, showDiag);

        System.Diagnostics.Debug.WriteLine("Registered messages for " + myID);

        idsRegistered.Add(myID);
    }
}

private async void showDiag(object msg)
{
    System.Diagnostics.Debug.WriteLine("Showing dialog for " + myID);
    if (activePageID != myID)
        return;
    await PassphraseDialog.ShowAsync();
}

ContentDialog XAML

<ContentDialog x:Name="PassphraseDialog"
                       x:Uid="Page_PassDialog"
                       PrimaryButtonText="Enter"
                       SecondaryButtonText="Cancel"
                       PrimaryButtonCommand="{x:Bind ViewModel.PassDialogEnterCommand}"
                       Closing="PassphraseDialog_Closing">
    <StackPanel>
        <TextBlock x:Uid="Page_PassDialogText" />
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
            <PasswordBox x:Name="PassphraseDialogInput"
                         Password="{x:Bind ViewModel.PassDialogInputText, Mode=TwoWay}"
                         helper:EnterKeyHelpers.EnterKeyCommand="{x:Bind ViewModel.PassDialogEnterCommand}" />
            <ProgressRing Margin="8,0,0,12"
                                  IsActive="{x:Bind ViewModel.PassDialogLoading, Mode=OneWay}" />
        </StackPanel>
        <TextBlock Text="{x:Bind ViewModel.PassDialogErrorText, Mode=OneWay}"
                   Foreground="{ThemeResource SystemErrorTextColor}"/>
    </StackPanel>
</ContentDialog>

Моя первая проблема Было то, что каким-то образом в моей настройке метод showDiag вызывался несколько раз. Итак, я провел несколько тестов, чтобы узнать следующее:

  1. Сообщение регистрируется один раз для каждого идентификатора в коде позади.
  2. Сообщение отправляется один раз.
  3. showDiag вызывается один раз.

Я не уверен, связано ли это с этим, но я обнаружил, что при такой настройке конструктор страницы вызывается при каждом переходе на страницу.

1 Ответ

2 голосов
/ 19 января 2020

Если вам нужно использовать одну и ту же страницу несколько раз, кэшируйте страницу.

Попробуйте:

private bool _isInit = false;
public MyPage()
{
    this.InitializeComponent();
    NavigationCacheMode = NavigationCacheMode.Enabled;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (e.NavigationMode == NavigationMode.Back || _isInit)
        return;

    // Do Somethings...

    _isInit = true;
}

Когда страница кэшируется, она сохраняет текущее состояние страница, что означает две вещи:

  1. Созданная вами ContentDialog не будет заменена на ContentDialog только что созданной страницы, что приведет к ошибке.
  2. При выходе и возвращаясь со страницы, страница не будет создаваться повторно.

С уважением.

...