将子视图中的元素绑定到父ViewModel的属性

时间:2014-05-17 15:36:43

标签: c# wpf xaml mvvm caliburn.micro

就像标题所说,我想将子视图中的元素绑定到父ViewModel的属性。

是否有Caliburn.Micro或默认的WPF XAML语法来执行此操作?我的意思是,这个确切的情况:绑定到父ViewModel的属性。

或者我应该尝试以其他方式实现这一目标吗?是这样,最好/最简单的方法是什么?

这是一个非常基本的Caliburn.Micro App示例:

MainWindowViewModel.cs

namespace BindingToParentVMProperty.MVVM
{
    public class MainWindowViewModel
    {
        public ChildViewModel Child { get; set; }
        public string ParentName { get; set; }

        public MainWindowViewModel()
        {
            Child = new ChildViewModel();
            ParentName = "Peter Griffin";
        }
    }
}

MainWindowView.xaml

<UserControl x:Class="BindingToParentVMProperty.MVVM.MainWindowView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d">
    <Grid Width="200" Height="200">
        <ContentControl Name="Child" />
    </Grid>
</UserControl>

ChildViewModel.cs

using Caliburn.Micro;

namespace BindingToParentVMProperty.MVVM
{
    public class ChildViewModel
    {
        public BindableCollection<GrandChildViewModel> GrandKids { get; set; }
        public string ChildName { get; set; }

        public ChildViewModel()
        {
            ChildName = "Stewie Griffin";
            GrandKids = new BindableCollection<GrandChildViewModel>
                {
                    new GrandChildViewModel {GrandChildName = "Stewie Griffin Jr."},
                    new GrandChildViewModel {GrandChildName = "Rupert Griffin Jr."}
                };
        }
    }
}

ChildView.xaml

<UserControl x:Class="BindingToParentVMProperty.MVVM.ChildView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
        <!-- need to bind to MainWindowViewModel.ParentName-->
        <TextBlock Text="{Binding Path=HowToBindTo_ParentName}"/>
        <ListView Name="GrandKids" />
    </StackPanel>
</UserControl>

GrandChildViewModel.cs

namespace BindingToParentVMProperty.MVVM
{
    public class GrandChildViewModel
    {
        public string GrandChildName { get; set; }
    }
}

GrandChildView.xaml

<UserControl
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             x:Class="BindingToParentVMProperty.MVVM.GrandChildView"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
        <TextBlock x:Name="GrandChildName" />
        <!-- need to bind to ChildViewModel.ChildName -->
        <TextBlock Text="{Binding Path=HowToBindTo_ChildName}"/>
    </StackPanel>
</UserControl>

2 个答案:

答案 0 :(得分:2)

似乎最直接的建议是在孩子ViewModel上保留父母的一些记录(例如Parent属性)。由于您希望将ViewModels绑定到各自的Views,我认为如果您开始绑定到属性并包含超出绑定范围{{1}范围的信息,那么它在概念上将变得相当棘手。 }。

此外,虽然您可能不关心正在处理的特定项目,但如果您开始包含来自其他ViewModel的属性,则您隐式创建链接和依赖项,这可能会回到如果您希望在非分层上下文中的其他位置重新使用控件,则会给您带来不便。

也就是说,您可以遍历UI树以从父控件获取所需的UserControlsDataContext),并使用现有的ViewModel语法绑定到所需的属性,如WPF建议使用KollegosRelativeSource属性。

在您的情况下,它可能看起来像这样:

AncestorType

RelativeSource Documentation

答案 1 :(得分:1)

因此,您可以将MainWindowViewModel用于所有观看次数,但我不知道它如何与Caliburn一起使用。我不知道您如何使用UserControl,但也许RelativeSource可以帮助您(例如,您可以绑定到相对控制的DataContext。)