如何在导航事件中保留数据上下文?

How to preserve data context on navigation event?

我设置了一个 属性,它会在调用 setter 时触发自定义导航事件 (NavigateTo)。到目前为止,导航在第一次尝试时就可以正常工作,即从列表视图中 selected 项目,其中 selected 项目绑定到 属性,然后 属性 setter 触发并依次触发导航事件。

但是当我导航回 MainPage 并且 select 列表视图中的一个项目 时,导航事件不会触发。

我已经调试了 'NavigateTo' 的调用,它在我第二次从列表视图导航回 MainPage 和 select 时没有被调用。这向我指出尚未调用页面的构造函数并且未设置 VM 的数据上下文,这反过来意味着不会调用 setter 导航事件。

问题:

如何在页面之间的导航生命周期中保留数据上下文?

MainViewModel - 在 SelectedCouncilName setter 中调用导航事件,它传递一个用于导航的 int 参数:

    private CouncilName _selectedCouncilName;
    public CouncilName SelectedCouncilName
    {
        get
        {
            return _selectedCouncilName;
        }
        set
        {
            if (_selectedCouncilName != value)
            {
                _selectedCouncilName = value;
                RaisePropertyChanged("SelectedCouncilName");
                _navCallBack.NavigateTo(_selectedCouncilName.ID);            
            }
        }

    }

MainPage.xaml 列表视图 - selected 项目绑定到 SelectedCouncilName 属性:

<ListView x:Name="ZonesListView"
                      Margin="0,0,-12,0"
                      ItemsSource="{Binding CouncilNameItems}"
                      SelectedItem="{Binding SelectedCouncilName,
                                             Mode=TwoWay}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Margin="0,0,0,17">
                            <TextBlock Style="{ThemeResource ListViewItemTextBlockStyle}"
                                       Text="{Binding CouncilAcronym}"
                                       TextWrapping="Wrap" />
                            <TextBlock Margin="12,-6,12,0"
                                       Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"
                                       Text="{Binding CouncilFullName}"
                                       TextWrapping="Wrap" />
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

MainPage.xaml.cs - 在 SelectedCouncilName 属性 上触发 setter 之后触发导航事件的代码。 (我在后面包含了整个页面代码,以显示如何设置数据上下文和导航方法的详细信息):

public sealed partial class MainPage : Page, INavigationCallback
{
    MainViewModel vm;

    private NavigationHelper navigationHelper;

    public MainPage()
    {

        this.navigationHelper = new NavigationHelper(this);
        this.navigationHelper.LoadState += navigationHelper_LoadState;
        this.navigationHelper.SaveState += navigationHelper_SaveState;

        //init data context
        this.NavigationCacheMode = NavigationCacheMode.Required;
        this.InitializeComponent();

        vm = new MainViewModel(this);
        this.DataContext = vm;
        vm.LoadCouncilNamesData();
    }

    private void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
    {
        throw new NotImplementedException();
    }

    void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// Invoked when this page is about to be displayed in a Frame.
    /// </summary>
    /// <param name="e">Event data that describes how this page was reached.
    /// This parameter is typically used to configure the page.</param>
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {


        // TODO: Prepare page for display here.

        // TODO: If your application contains multiple pages, ensure that you are
        // handling the hardware Back button by registering for the
        // Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
        // If you are using the NavigationHelper provided by some templates,
        // this event is handled for you.

    }

    void INavigationCallback.NavigateTo(string ItemID)
    {
        Frame.Navigate(typeof(RequestTagPage), ItemID);
    }
}

如果问题是未调用构造函数,那么我建议将您的视图模型设为 StaticResource 或将其放在 ViewModel 定位器中。当您在 XAML 中绑定它时,数据上下文将保持不变。

人口可以在您的视图模型的构造函数中实例化,因为它将在需要时生成。

删除this.NavigationCacheMode = NavigationCacheMode.Required 返回导航时调用构造函数