WPF:设置UserControl的DataContext,绑定不在XAML中

时间:2010-04-18 11:09:23

标签: mvvm binding

我正在尝试让我的第一个WPF应用程序使用MVVM,我遇到了一些绑定问题。

设置是我有一个视图& viewModel保存用户详细信息(父级),并尝试保持简单我已将该视图的一部分放入单独的视图& viewModel(孩子)。子视图定义为UserControl。

我遇到的问题是如何设置子视图的DataContext(UserControl)。我的父ViewModel有一个公开子ViewModel的属性,如下所示:

class ParentViewModel: INotifyPropertyChanged
{
    public ChildViewModel childViewModel { get; set; }
    //...
}

在我的父视图的XAML中(将其DataContext设置为ParentViewModel),我尝试按如下方式设置子视图的DataContext:

<views:ChildView 
    x:Name="ChildView"
    DataContext="{Binding childViewModel}"/>

然而,这不起作用。子视图的DataContext设置为与父视图(即ParentViewModel)相同的DataContext,就像我根本没有设置它一样。我也尝试在子视图中设置DataContext,这也不起作用:

<UserControl x:Class="DietRecorder.Client.View.ChildView"
    DataContext="childViewModel"

我找到了几种方法。在子视图中,我可以通过在路径中包含ChildViewModel来绑定所有内容:

<SomeControl Visibility="{Binding Path=childViewModel.IsVisible}">

但我不希望子视图对层次结构具有这种级别的意识。在代码中设置DataContext也可以 - 但是,我必须在显示父视图后执行此操作,否则当我调用Show()时,DataContext会被覆盖:

parentView.Show();
parentView.ChildView.DataContext = parentViewModel.childViewModel;

这段代码也让我感到不安,LOD违规行为和所有内容。

这只是DataContext似乎是问题 - 我可以绑定孩子中的其他东西,例如我尝试将FontSize绑定到int属性只是为了测试它:

<views:ChildView 
    x:Name="ChildView"
    FontSize="{Binding Path=someVal}"/>

这很好。

但我确信DataContext的绑定应该有效 - 我已经看到了类似的这种事情的例子。我错过了一些明显的东西吗?有什么理由不行吗?某处有拼写错误吗? (为了你的利益我改名了,所以无论如何你都无法帮助我。)

欢迎任何想法。

修改

再次查看此代码,似乎我在某个地方犯了一个错误,因为父视图中的以下XAML现在似乎有效:

<views:ChildView 
    x:Name="ChildView"
    DataContext="{Binding childViewModel}"/>

我不确定为什么我不能让它最初工作,或者我可能已经改变它以使它工作。也许就像其中一个答案所暗示的那样是INotifyPropertyChanged问题。哦,好吧,向上和向上......

3 个答案:

答案 0 :(得分:2)

我怀疑是因为childViewModel属性不会引发PropertyChanged事件。在评估绑定时,此属性可能为null(在这种情况下,DataContext将回退到父级的属性)。稍后实例化childViewModel时,不会引发PropertyChanged事件,并且永远不会通知绑定现在存在DataContext。

尝试在childViewModel属性中引发PropertyChanged事件。

干杯, 劳伦

答案 1 :(得分:2)

我一直在寻找同样的东西,我找到了一种方法。基本上,我使用

将子的DataContext绑定到某个父级(窗口)的DataContext
DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}"

我在某个父控件(窗口)上设置了x:Name="_topLevel"

我尝试使用RelativeSource/FindAncestor而不是ElementName,但它没有用 - 但这可能是我的错。

感觉像是对我的黑客攻击,但比绑定到顶级视图模型更好。

答案 2 :(得分:2)

这不是问题的答案,但可能在同样的情况下帮助其他人。

我确实遇到了这个问题并发现了

parentView.ChildView.DataContext = parentViewModel.childViewModel;

方法有效(虽然我发现它在做Show()之前有效),但与原始提问者有相同的疑虑,所以尝试了

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}"

方法,似乎也有效。但后来我再次尝试回到原始代码和原始XAML,现在它突然也起作用了。这反映了原始提问者的行为,即作者认为他们在某处犯了一个错误,因为XAML似乎没有明显的原因开始工作。

我能看到的唯一变化是Visual Studio现在在设计时在UserControl中显示示例数据,因此它已经在某处缓存了一些示例数据,这似乎使它工作。不幸的是,我不确定这两次变化中的哪一次发生了。

样本数据的出现让我想知道这个问题是否与使用d:DataContext有关,我在父和子XAML文件中有这个问题,但这只是推测。