简体   繁体   English

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

[英]Binding an element in a child View to a property of the parent ViewModel

Like the title says, I would like to bind an element in a child View to a property of the parent ViewModel. 就像标题所说,我想将子视图中的元素绑定到父ViewModel的属性。

Is there a Caliburn.Micro or default WPF XAML syntax to do this? 是否有Caliburn.Micro或默认的WPF XAML语法来执行此操作? I mean, this exact situation: to bind to parent ViewModel's property. 我的意思是,这个确切的情况:绑定到父ViewModel的属性。

Or should I try to achieve this some other way? 或者我应该尝试以其他方式实现这一目标吗? Is so, what would be the best/easiest way to do it? 是这样,最好/最简单的方法是什么?

Here is a very basic Caliburn.Micro App example: 这是一个非常基本的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 : 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 : 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 : 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 : GrandChildViewModel.cs

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

GrandChildView.xaml : 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>

It seems like the most straightforward suggestion would be to keep some record of the parent on the child ViewModel (eg a Parent property). 似乎最直接的建议是在子ViewModel上保留父级的一些记录(例如, Parent属性)。 Since you want to have your ViewModels tied to their respective Views , I think it will become conceptually quite tricky if you start to bind to properties and include information from beyond the scope of the bound ViewModel . 由于您希望将ViewModels绑定到各自的Views ,我认为如果您开始绑定到属性并包含超出绑定ViewModel范围的信息,那么它在概念上将变得非常棘手。

Also, whilst it may not be of concern for the particular project you're working on, if you start including properties from other UserControls , you're implicitly creating a links and dependencies, which may come back to inconvenience you if you wish to re-use the controls elsewhere in a non-hierarchical context. 此外,虽然您可能不关心您正在处理的特定项目,但如果您开始包含来自其他UserControls属性,则会隐式创建链接和依赖项,如果您希望重新启动,可能会给您带来不便 - 在非分层上下文中的其他位置使用控件。

That said, you could traverse up your UI tree to get the required DataContext ( ViewModel ) from a parent control, and bind to the desired property using existing WPF syntax, as Kollegos suggests, by using RelativeSource and the AncestorType property. 也就是说,您可以遍历UI树以从父控件获取所需的DataContextViewModel ),并使用现有的WPF语法绑定到所需的属性,正如Kollegos建议的那样,使用RelativeSourceAncestorType属性。

In your case, it might look something like this: 在您的情况下,它可能看起来像这样:

<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"
         xmlns:local="clr-namespace:YourProjectNamespaceContainingParentView"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
    <!-- Set our DataContext bind to parent MainWindowViews DataContext (ViewModel) -->
    <TextBlock Text="{Binding Path=ParentName}"
        DataContext="{Binding RelativeSource={RelativeSource
                      FindAncestor, AncestorType={x:Type local:MainWindowView}},
                      Path=DataContext}"/>
    <ListView Name="GrandKids" />
</StackPanel>

RelativeSource Documentation RelativeSource文档

So, you can use MainWindowViewModel for all your views, but I don't know how it work with Caliburn. 因此,您可以将MainWindowViewModel用于所有视图,但我不知道它如何与Caliburn一起使用。 I dont know how you use your UserControl s, but maybe RelativeSource can help you (you can bind to DataContext of relative control for example). 我不知道你如何使用你的UserControl ,但也许RelativeSource可以帮助你(你可以绑定到相对控制的DataContext )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM