如何在导航事件中保留数据上下文?
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
返回导航时调用构造函数
我设置了一个 属性,它会在调用 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
返回导航时调用构造函数