C# 当调用GoBack()时,NavigationService将导航到不存在的对象
我正在开发一个WPF web应用程序,其主页使用ninject加载页面 基本上,我想知道是否有一种方法可以告诉NavigationService由于用户更新了复合键中的值而更改了Id 我会尽力多解释一点。我的MultiTagPage有一个MultiTagView模型,它显示一个由(MultiTagDef、Key、Value)组成的multitagvalue。还有一个DataGrid,其中包含具有相同键和MultiTagDef的其他值。如果您双击其中一个值,则会显示相应的multitagvalue 在数据库中,multitagvalue使用复合键(Multitagdef.Name、key、value)存储。因此,如果有人更新了一个multitagvalue,则Id会被更改(比如从(a,B,C)到(a,B,D))并保存,然后如果用户继续使用数据网格中的另一个multitagvalue(a,B,E)并可能删除该对象,则navigationservice会尝试加载(a,B,C)而不是(a,B,D) 该体系结构是为具有ID列的对象设计的,当然,ID列永远不会更改。不幸的是,在这种情况下,添加ID列不是一个选项。那么,有人对如何解决这个问题有什么建议吗?我应该在每次有人保存时尝试重新加载页面,还是可以告诉NavigationService当前对象的ID已更改 现在,代码: 从主页:C# 当调用GoBack()时,NavigationService将导航到不存在的对象,c#,wpf,ninject,composite-primary-key,navigationservice,C#,Wpf,Ninject,Composite Primary Key,Navigationservice,我正在开发一个WPF web应用程序,其主页使用ninject加载页面 基本上,我想知道是否有一种方法可以告诉NavigationService由于用户更新了复合键中的值而更改了Id 我会尽力多解释一点。我的MultiTagPage有一个MultiTagView模型,它显示一个由(MultiTagDef、Key、Value)组成的multitagvalue。还有一个DataGrid,其中包含具有相同键和MultiTagDef的其他值。如果您双击其中一个值,则会显示相应的multitagvalue
public partial class MainPage : IUIService
{
public static readonly DependencyProperty MainModelProperty = PropertyHelper.Register<MainPage>(x => x.MainModel);
public MainModel MainModel
{
get { return (MainModel)GetValue(MainModelProperty); }
set { SetValue(MainModelProperty, value); }
}
private static readonly ILog log = LogManager.GetLogger(typeof(MainPage));
public MainPage()
{
// Make doubly sure...
ShowsNavigationUI = false;
InitializeComponent();
App.Kernel.Rebind<IUIService>().ToConstant(this);
MainModel = App.Kernel.Get<MainModel>();
WindowTitle = MainModel.Title;
ContentFrame.Navigating += Navigating;
ContentFrame.Navigated += Navigated;
ContentFrame.NavigationFailed += NavigationFailed;
}
private void Navigating(object sender, NavigatingCancelEventArgs args)
{
object dataContext = null;
if(ContentFrame.Content is FrameworkElement) {
dataContext = ((FrameworkElement)ContentFrame.Content).DataContext;
} else if(ContentFrame.Content is FrameworkContentElement) {
dataContext = ((FrameworkContentElement)ContentFrame.Content).DataContext;
}
if(dataContext is ISaveable && ((ISaveable)dataContext).NeedsSave) {
if(MessageControl.UnsavedSync() != MessageControl.Button.Yes) {
args.Cancel = true;
}
}
}
private void Navigated(object sender, NavigationEventArgs e)
{
var mi = e.ExtraData as MenuItemModel;
if(mi == null) {
var page = e.Content as IMenuItemPage;
if(page != null) {
mi = page.MenuItem;
}
if(mi == null) {
log.DebugFormat("Navigated to {0} ({1}) without menu item", e.Content, e.Uri);
return;
}
}
MainModel.CurrentMenuItem = mi;
if(mi.Type != MenuItemType.Folder) {
Settings.Default.AddRecentMenuItem(new RecentMenuItem(mi.MenuItem));
}
}
#region Generic Edit command
private void EditCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.Handled = true;
e.CanExecute = false;
var param = Unwrap(e.Parameter);
var paramType = GetEditType(param);
if(paramType == null || !editPages.ContainsKey(paramType)) {
return;
}
e.CanExecute = ToConstructorArgument(param) != null;
}
private void EditExecuted(object sender, ExecutedRoutedEventArgs e)
{
Edit(e.Parameter);
}
private void Edit(object param)
{
var paramType = GetEditType(param);
if(paramType == null || !editPages.ContainsKey(paramType)) {
log.WarnFormat("Page for param {0} (type {1}) not found", param, paramType);
return;
}
if(param is IList) {
var list = (IList)param;
if(list.Count > 1000) {
Show("Too many items selected", "Please select no more than 1000 items at a time", messageTheme: MessageTheme.Warning);
return;
}
}
var arg = ToConstructorArgument(param);
if(arg == null) {
log.Warn("Unexpected parameter " + param + " supplied to EditExecuted");
return;
}
var pageType = editPages[paramType];
try {
log.DebugFormat("Got a parameter of type {0}, navigating to edit page {1}", param.GetType(), pageType);
Navigate(MakePage(pageType, arg));
} catch(Exception ex) {
log.Error("Unable to load edit page for parameter " + param, ex);
}
}
private static Page MakePage(Type pageType, params IParameter[] p)
{
var page = (Page)App.Kernel.Get(pageType, p);
var dp = ClientUtil.GetViewModelProperty(page.GetType());
if(dp != null) {
page.Loaded += (o, args) => {
var skrap = App.Kernel.Get(dp.PropertyType, p);
page.SetValue(dp, App.Kernel.Get(dp.PropertyType, p));
};
page.Unloaded += (o, args) => {
try {
page.ClearValue(dp);
} catch(Exception e) {
// Often happens when datagrid is in edit mode when navigating away from page:
// http://connect.microsoft.com/VisualStudio/feedback/details/571967/wpf-datagrid-causes-crash-with-sorting-is-not-allowed-during-an-addnew-or-edititem-transaction
log.Warn("Error while unloading page", e);
}
};
ViewModelBehavior.SetUpdateUIError(page, true);
}
return page;
}
#endregion
#region Navigate command
private void NavigateCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter is Type;
e.Handled = true;
}
private void NavigateExecuted(object sender, ExecutedRoutedEventArgs e)
{
var type = e.Parameter as Type;
if(type == null) {
return;
}
Navigate(MakePage(type));
e.Handled = true;
}
#endregion
#region IUIService implementation
public void Navigate(Type type, params Tuple<string, object>[] parameters)
{
Navigate(MakePage(type, parameters.Select(x => new ConstructorArgument(x.Item1, x.Item2)).ToArray()));
}
public void Navigate(Type type, MenuItemModel menuItem, params Tuple<string, object>[] parameters)
{
Navigate(MakePage(type, parameters.Select(x => new ConstructorArgument(x.Item1, x.Item2))
.Prepend(new ConstructorArgument("menuItem", menuItem))
.Prepend(new ConstructorArgument("props", menuItem.Params))
.ToArray()),
menuItem);
}
public void Navigate(Page content, object extraData = null)
{
if(ContentFrame != null) {
if(ContentFrame.Content is DependencyObject) {
foreach(var dg in WpfUtil.FindDescendants<DataGrid>((DependencyObject)ContentFrame.Content)) {
while(!dg.CommitEdit()) { /* Keep committing */ }
}
}
ContentFrame.Navigate(content, extraData);
}
}
public bool NavigateBack()
{
if(ContentFrame != null && ContentFrame.CanGoBack) {
ContentFrame.GoBack();
return true;
}
if(NavigationService != null && NavigationService.CanGoBack) {
NavigationService.GoBack();
return true;
}
return false;
}
}
public分部类主页面:IUIService
{
公共静态只读DependencyProperty MainModelProperty=PropertyHelper.Register(x=>x.MainModel);
公共main模型main模型
{
获取{return(MainModel)GetValue(MainModelProperty);}
set{SetValue(MainModelProperty,value);}
}
private static readonly ILog log=LogManager.GetLogger(typeof(MainPage));
公共主页()
{
//加倍确保。。。
ShowsNavigationUI=false;
初始化组件();
App.Kernel.Rebind().ToConstant(this);
MainModel=App.Kernel.Get();
WindowTitle=MainModel.Title;
ContentFrame.Navigating+=导航;
ContentFrame.Navigated+=已导航;
ContentFrame.NavigationFailed+=NavigationFailed;
}
私有无效导航(对象发送方、导航取消事件args args)
{
对象dataContext=null;
if(ContentFrame.Content是FrameworkElement){
dataContext=((FrameworkElement)ContentFrame.Content).dataContext;
}else if(ContentFrame.Content是FrameworkContentElement){
dataContext=((FrameworkContentElement)ContentFrame.Content);
}
if(dataContext是ISaveable&((ISaveable)dataContext).NeedsSave){
if(MessageControl.UnsavedSync()!=MessageControl.Button.Yes){
args.Cancel=true;
}
}
}
已导航的专用void(对象发送方,NavigationEventArgs e)
{
var mi=e.ExtraData作为MenuItemModel;
if(mi==null){
var page=e.内容为IMenuItemPage;
如果(第页!=null){
mi=page.MenuItem;
}
if(mi==null){
DebugFormat(“导航到{0}({1}),没有菜单项”,e.Content,e.Uri);
返回;
}
}
MainModel.CurrentMenuItem=mi;
if(mi.Type!=MenuItemType.Folder){
Settings.Default.AddRecentMenuItem(新的RecentMenuItem(mi.MenuItem));
}
}
#区域通用编辑命令
私有void EditCanExecute(对象发送方,CanExecuteRouteEventArgs e)
{
e、 已处理=正确;
e、 CanExecute=false;
var param=展开(即参数);
var paramType=GetEditType(param);
if(paramType==null | |!editPages.ContainsKey(paramType)){
返回;
}
e、 CanExecute=ToConstructorArgument(param)!=null;
}
私有void EditExecuted(对象发送方,ExecutedRoutedEventArgs e)
{
编辑(如参数);
}
私有无效编辑(对象参数)
{
var paramType=GetEditType(param);
if(paramType==null | |!editPages.ContainsKey(paramType)){
log.WarnFormat(“找不到参数{0}(类型{1})的页面”,参数,参数类型);
返回;
}
如果(参数为IList){
变量列表=(IList)参数;
如果(list.Count>1000){
显示(“选择的项目太多”,“请一次选择的项目不超过1000个”,messageTheme:messageTheme.Warning);
返回;
}
}
var arg=ToConstructorArgument(param);
如果(arg==null){
log.Warn(“提供给EditExecuted的意外参数”+param+);
返回;
}
var pageType=editPages[paramType];
试一试{
DebugFormat(“获取类型为{0}的参数,导航到编辑页面{1}”,param.GetType(),pageType);
导航(MakePage(pageType,arg));
}捕获(例外情况除外){
日志错误(“无法加载参数“+param,ex”的编辑页);
}
}
私有静态页面MakePage(类型pageType,参数IPParameter[]p)
{
var page=(page)App.Kernel.Get(pageType,p);
var dp=ClientUtil.GetViewModelProperty(page.GetType());
如果(dp!=null){
页面加载+=(o,参数)=>{
var skrap=App.Kernel.Get(dp.PropertyType,p);
SetValue(dp,App.Kernel.Get(dp.PropertyType,p));
};
页面已卸载+=(o,参数)=>{
试一试{
第页:净价值(dp);
}捕获(例外e){
//在离开页面导航时,datagrid处于编辑模式时经常发生:
// http://connect.microsoft.com/VisualStudio/feedback/details/571967/wpf-datagrid-causes-crash-with-sorting-is-not-allowed-during-an-addnew-or-edititem-transaction