在MVVM应用程序切换的ViewModels时BindingEx pression路径错误应用程序、路径、错误、MVVM

2023-09-07 03:47:56 作者:眸七

首先第一件事情,一些背景。如果你熟悉的问题,直接跳到了 BindingEx pression 部分。这是WPF我的第一个大项目,所以我还是很新的MVVM模式。 Here是唯一的其他类似的问题,我发现,他的表现平淡的回答并没有真正热血沸腾,我很多。

First things first, some context. If you're familiar with the problem, skip down to the BindingExpression part. This is my first major project in WPF, so I am still quite new to the MVVM pattern. Here is the only other similar question I have found, whose lacklustre answer doesn't really enthuse me much.

我/我构建.NET 3.5 WPF应用程序,我使用MVVM(实现我自己,没有任何框架)。在此,我有许多浏览的ViewModels 。这些位于主内 ApplicationView ApplicationViewModel 分别。

I have/am building a .NET 3.5 WPF application and I am using MVVM (implemented myself, no framework). Within this, I have a number of Views and ViewModels. These reside within a master ApplicationView and ApplicationViewModel respectively.

我改变看法的方式是通过使用XAML的DataTemplate元素在 ApplicationView ,像这样:

The way I change views is through using XAML DataTemplate elements in the ApplicationView, like so:

<DataTemplate DataType="{x:Type viewmodels:InitViewModel}">
    <views:InitView />
</DataTemplate>

然后在主体我有一个ContentControl中结合到属性 ApplicationViewModel

<ContentControl Content="{Binding CurrentPageViewModel}"/>

当我运行应用程序,这一切似乎做工精细,并且不正是意。然而,当我看运行后的调试输出,我得到了很多的 BindingEx pression 错误。

When I run the application, all of this appears to work fine, and does exactly what is intended. However, when I look at the Debug output after the run, I get a lot of BindingExpression errors.

下面是一个用于例子。我有一个属性, SplashText ,在我的 InitViewModel 。这势必会在启动画面一个文本块( InitView )。当启动画面结束,我切换出视图模型,我得到如下:

Here is one for example. I have a property, SplashText, in my InitViewModel. This is bound to a textblock in the splash screen (InitView). When the splash screen ends and I switch out the viewmodel, I get the following:

System.Windows.Data错误:39:BindingEx pression路径错误:SplashText'属性不是'对象'''MainMenuViewModel发现'(哈希code = 680171)' 。 BindingEx pression:路径= SplashText; DataItem的='MainMenuViewModel'(哈希code = 680171);目标元素是'文本框'(名称='FeedBackBox'); target属性是文本(类型'字符串')​​

据我所知,这是因为绑定仍然存在,但在DataContext的CurrentPageViewModel属性发生变化。所以我想知道的是:

I understand that this is because the bindings still exist, but the CurrentPageViewModel property of the DataContext has changed. So what I want to know is:

这是一个稍纵即逝的问题,即是在处理意见时,不使用的还是他们(和坏的绑定)坐在那里,在内存中无限期地? 有没有一种方法,我可以清理或关闭这些绑定,而认为是无效的? 是一个什么样的表现敲会对我的应用程序,如果我离开这些人吗? 是否有视图切换,避免了这个问题?更好的办法

在此先感谢和道歉的整体问题。

Thanks in advance, and apologies for the monolithic question.

编辑13年3月9日 - 得益于Jehof,弗朗西斯德丽丝和更快的解决方案指出,这是毫无意义的设置子视图的DataContext为 {结合DataContext.CurrentPageViewModel,的RelativeSource = {的RelativeSource AncestorType = {X:类型窗口}}} 因为ContentControl中负责在DataContext的

Edit 03/09/13 - Thanks to Jehof, Francesco De Lisi and Faster Solutions for pointing out that it is pointless to set sub-views datacontext as {Binding DataContext.CurrentPageViewModel, RelativeSource={RelativeSource AncestorType={x:Type Window}}} because the ContentControl takes care of the datacontext.

推荐答案

您具体的例子是不可再生的.NET 4.5,这可能意味着微软已经修复了这个问题其间。

Your specific example is not reproducible in .NET 4.5, which probably means Microsoft has fixed the problem meantime.

然而,当内容和的ContentTemplate都是数据绑定类似的问题存在。我要解决这个问题,这也是可能的,如果有人还在用它来解决.NET 3.5的问题。例如:

Nevertheless, a similar problem exists when Content and ContentTemplate are both data-bound. I am going to address that problem, which is also likely to solve problems in .NET 3.5 if anyone is still using it. For example:

<ContentControl Content="{Binding Content}" ContentTemplate="{Binding Template}" />

或者当的ContentTemplate由DataTrigger决定:

Or when ContentTemplate is determined by DataTrigger:

<ContentControl Content="{Binding Content}">
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Choice}" Value="1">
                    <Setter Property="ContentTemplate" Value="{StaticResource TemplateA}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Choice}" Value="2">
                    <Setter Property="ContentTemplate" Value="{StaticResource TemplateB}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Style>
</ContentControl>

在这两种情况下,一个得到类似于OP观察到的结合的错误。

In both cases, one gets binding errors similar to those OP observed.

这里的关键是要确保修改内容,并在的ContentTemplate拿捏的顺序执行,以prevent绑定错误。我已经写 DelayedContentControl ,从而确保内容和的ContentTemplate是在同一时间,并在正确的顺序改变。

The trick here is to ensure that changes to Content and ContentTemplate are performed in just the right order to prevent binding errors. I've written DelayedContentControl, which ensures that Content and ContentTemplate are changed at the same time and in the right order.

<jc:DelayedContentControl Content="{Binding Content}" ContentTemplate="{Binding Template}">

类似地,对于DataTrigger情况

Similarly for the DataTrigger case.

您可以从我的开源 JungleControls库。

You can get DelayedContentControl from my opensource JungleControls library.