导航回视图时引发InvalidOperationException

时间:2012-08-03 13:03:40

标签: c# wpf exception-handling prism

我有一个子视图(SharedView),它在两个父视图之间共享,所以我通过像这样的Region将它添加到每个父视图

<StackPanel>
  <ContentControl cal:RegionManager.RegionName="SharedViewRegion" />
</StackPanel>

在父视图的ViewModel中,我像这样注册子视图

regionManager.RegisterViewWithRegion("SharedViewRegion", typeof(SharedView));

当我运行应用程序时如果我只打开其中一个父视图,它按预期工作但如果我打开两个父视图,那么我得到以下异常

  

创建名称区域时发生异常   'SecondRegion'。例外是:System.InvalidOperationException:   指定的元素已经是另一个元素的逻辑子元素。   首先断开它。

我一直在谷歌上搜索,这是我发现问题的最接近的解决方案InvalidOperationException occurs when the same view instance is added to multiple ContentControl regions

但是我正在使用棱镜导航功能,因此我正在实现像这样的父视图

regionManager.RequestNavigate("ModuleRegion", new Uri("ParentView1", UriKind.Relative));

有人可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

尝试执行以下操作:

为托管区域的ContentControl添加名称

  

现在您必须在离开父视图之前删除该区域的内容,以便在ViewModel中将以下代码添加到OnNavigatedFrom方法

public void OnNavigatedFrom(NavigationContext navigationContext)
{
  ParentView.MyContentControl.Content = null;
}

注意:您可以访问在ViewModel中导入它的父视图。

现在您需要手动将内容添加到区域,因为您在离开区域之前将其删除了。这是代码

public void OnNavigatedTo(NavigationContext navigationContext)
{
  SharedView view = (SharedView)ServiceLocator.Current.GetInstance(typeof(SharedView));
  ParentView.MyContentControl.Content = view;
}

注意:在此方法中,您必须添加一些变通方法,因为第一次打开此视图时,您将获得System.InvalidOperationException,因为PRISM将尝试将SharedView添加到MyContentControl。

这是一种可行的解决方法

bool isFirstTime = true;

public void OnNavigatedTo(NavigationContext navigationContext)
{
  if (isFirstTime)
  {
    isFirstTime = false;
    return;
  }
  SharedView view = (SharedView)ServiceLocator.Current.GetInstance(typeof(SharedView));
  ParentView.MyContentControl.Content = view;
}

您必须在共享SharedView的所有父视图中执行相同的工作

我希望这可以帮到你

答案 1 :(得分:0)

对于这种情况,您应该直接向区域添加视图而不是视图发现。为父视图指定唯一的名称(您可以使用计数器来组成唯一的名称)。

var region = this.regionManager.Regions["SharedViewRegion"];
var viewName = string.Format("SharedView{0}", this.countParent+1);

//Only add if it doesn't exist
var view = region.GetView(viewName);
if (null==view)
{
 //Use container to get new instance of the parent view.
 view = this.container.Resolve<SharedView>();
 region.Add(view, name);
 //Increment the counter as you added a new parent view 
 this.countParent++;
}

//Now activate the view
region.Activate(view);