Caliburn.Micro在导航GoBack时重新绑定ContentControl。

9

我将在WinRT应用程序中使用Caliburn.Micro。

这是我的主要VM:

public class MainViewModel : Conductor<Screen>
{
    protected override void OnActivate()
    {
        if (ActiveItem == null)
        {
           ActivateItem(
               ViewModelLocator.LocateForViewType(typeof(NewsFeedView)) as Screen);
        }

        base.OnActivate();
    }
}

我在这里使用 Conductor 是因为我想要在 ContentControl 中加载不同的控件,但现在我只有这段代码。以下是我的主视图中的内容控件:

<ContentControl x:Name="ActiveItem" Grid.Column="1" Grid.Row="1" />

当我运行应用程序时,一切都正常,MainViewModel.Activate被调用,并将ActiveItem设置为NewsFeedViewModelContentControl加载NewsFeedView
问题是:当我在NewsFeedView控件中使用NavigationService.NavigateToViewModel方法导航到另一个视图,然后在该视图中使用NavigationService.GoBack,返回到MainView时,在调用MainViewModel.Activate时,ActiveItem不是null,但ContentControl.Contentnull。 我尝试使用ContentControlView.Model附加属性,但没有成功,如何重新绑定?
编辑:最后,我在Caliburn中设置记录器以查看发生了什么,并找到了一个错误-当在导航回来后加载MainView时,会出现以下事件:
Attaching ***.Views.MainView to ***.ViewModels.MainViewModel.
ViewModel bound on ActiveItem.
Using cached view for ***.ViewModels.NewsFeedViewModel.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Exception: Unspecified error
at Windows.UI.Xaml.Controls.ContentControl.put_Content(Object value)
... some winRT stack
at Caliburn.Micro.View.SetContentPropertyCore(...

虽然信息不是很详细,但我使用了InteliTrace来获取更多信息,并得到了这个消息:“元素已经是另一个元素的子元素”。我想NewsFeedView在某个地方被存储了起来,当将其放入ContentControl中时就会抛出此异常。 如何解决这个问题?


你检查过 MainViewModel 对象是否仍然是之前的同一实例了吗?"Element is already child of another element" 这个错误提示似乎是你正在导航到一个新的 MainViewModel 实例,而旧的实例仍保留着 NewsFeedViewModel。你能分享一下你的引导程序配置吗? - T045T
请分享您的引导程序,这将告诉您拥有哪些可能性。我已经在 .net 4.0 / wpf 场景下解决了类似的问题。 - Mare Infinitus
@MareInfinitus 在WinRT应用程序中没有引导程序,MainViewModel在Caliburn IoC容器中注册为Singleton。 - Alexander
2个回答

3

你应该首先采用视图模型优先的方法。换句话说,激活视图模型的实例,Caliburn.Micro将为您执行视图定位和绑定。

看起来你想在构造函数或OnInitialise中仅实例化视图模型:

public MainViewModel()
{
    this.ActivateItem(new NewsFeedViewModel());
}

感谢您的回答,但我真的不明白您所说的“先采用视图模型方法”的意思,我在调用 ActivateItem 和在视图间导航时调用 NavigateToViewModel 时使用了视图模型,因此我并没有采用视图优先的方法。 - Alexander
是的,你是对的,但从你上面包含的MainViewModel代码来看,你的方法非常绕。你正在使用ViewModelLocator和视图类型来获取视图模型。直接使用视图模型实例即可。 - devdigital
好的,我明白了。但是最终这对数据绑定没有影响,当从视图返回时,ContentControl仍然为空,尽管ActiveItem不为null,我已经尝试调用NotifyOfPropertyChange(()=>ActiveItem),但结果仍然相同。 - Alexander
抱歉,我有点困惑,你是在进行Windows Phone开发还是WinRT开发? - devdigital

1

按照@devdigital所说,只需在构造函数中初始化新闻源视图模型一次,为什么不使用Conductor.Collection.OneActive呢?因为您每次只有一个活动项,这种情况下会用到它,这可能会解决您的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接