无法有条件地取消XAML框架的导航请求

j13ufse2  于 2023-04-18  发布在  其他
关注(0)|答案(1)|浏览(88)

我目前正在尝试在我的WinUI3应用程序中处理导航,该应用程序使用Microsoft.UI.Xaml作为UI。我的情况是,我想提示用户当前页面中有未保存的更改,并让他们决定是否忽略更改并导航到请求的页面或停留在当前页面。

public CompanyFormView() {
    InitializeComponent();

    Loaded += (object sender, RoutedEventArgs args) => {
        MainWindow.Window_MainFrame.Navigating += new NavigatingCancelEventHandler(NavigationRequest);
            ...
    };

    Unloaded += (object sender, RoutedEventArgs args) => {
        MainWindow.Window_MainFrame.Navigating -= new NavigatingCancelEventHandler(NavigationRequest);
    }; 
}

在处理程序中,我有一个ContentDialog,它要求处理程序是异步的。发生的情况是,我从ContentDialog得到提示,但是所请求的页面在没有考虑异步操作的情况下被导航到,因此e.Cancel不能按预期工作。我试图注解掉await操作,然后e.Cancel工作,所以问题很可能与等待有关。

private async void NavigationRequest(object sender, NavigatingCancelEventArgs e) {
    if (Model.IsCommitted)
        return;

    var updated = Model.GetUpdatedFields(GetFieldList());
    if (updated.Count == 0)
        return;

    bool stay = await PopUpDialog.UnsavedChanges(XamlRoot, updated);

    if (!leaveApproved) {
        e.Cancel = true;
    }
}

我该如何解决这个问题呢?我更愿意用类似的方法来处理,但我愿意接受任何建议。

egdjgwm8

egdjgwm81#

我自己用一种稍微不同的方法解决了这个问题。(XAML NavigationViewItem)。侧边栏中的click事件是通过调用navigation方法来通知的,然后如果有订阅视图则调用该事件。一般来说,每当加载新页面时,它都会订阅该事件。
我不确定这个解决方案是否是最好的,但我认为它符合MVP模式。另外,我在某个地方读到事件处理程序不应该返回值,但我不明白为什么添加另一个事件或其他东西会更好,因为在我看来,它增加了更多的复杂性。
无论如何,希望这能帮助到一些人,如果有人比我更了解我所做的事情,请发表评论,并指出这是为了帮助其他有同样问题的人。

// .xaml.cs file
public CompanyFormView() {
    InitializeComponent();

    Loaded += (object sender, RoutedEventArgs args) => {
        Navigation.OnNavigationRequested += NavigationRequest;
        ...
    };

    Unloaded += (object sender, RoutedEventArgs args) => {
        Navigation.OnNavigationRequested -= NavigationRequest;
    };
}

private async Task<bool> NavigationRequest() {
    if (Model.IsCommitted)
        return true;

    var updated = Model.GetUpdatedFields(GetFieldList());
    if (updated.Count == 0)
        return true;

    bool leaveAllowed = await PopUpDialog.UnsavedChanges(XamlRoot, updated);

    if (leaveAllowed) {
        return true;
    } else {
        return false;
    }
}
// navigation file
public static async Task<bool> NavigationRequested(NavigationViewItem item) {
    if (item.Tag.ToString() == currentPage)
        return false; // since invoked is called for all clicks

    bool navigationApproved = await (OnNavigationRequested?.Invoke() ?? Task.FromResult(true));

    if (navigationApproved) {
        currentPage = item.Tag.ToString();
        return true;
    } else {
        return false;
    }
}
// view where the navigation attempt can be requested from
private async void SidebarMenu_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs e) {
    var item = e.InvokedItemContainer as NavigationViewItem
    if (item == null)
        return;

    bool approved = await Navigation.NavigationRequested(item);

    if (approved) { // doesn't seem to work!
        ((SidebarMenu.SelectedItem = item) as NavigationViewItem).IsSelected = true;
        Navigation.HandleRequest(item.Tag.ToString());
    }
}

相关问题