通过Resource向子项公开Parent的DataContext

时间:2015-04-30 05:44:34

标签: c# wpf xaml resourcedictionary

我遇到父DataContext与子DataContext不同的情况,我想从子进程中的绑定访问父DataContext。这可以使用详细的RelativeSource来完成,如下所示:

 <Button Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}, Path=DataContext.Bar}"/>

我想找到一种以更简洁的方式引用父级DataContext的方法。有没有办法,例如,父级可以通过父级中定义的资源公开对它的DataContext(或其任何属性)的引用?理想情况下,孩子的绑定看起来像下面这样(原谅我使用StaticResource作为例子)。

 <Button Path=Bar, Content="{StaticResource parentDataContextReference}"/>

理想情况下,避免代码隐藏,但对该解决方案持开放态度。一个人为的例子:

MainWindow.xaml

<Window x:Class="BindingTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:BindingTest"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <x:ArrayExtension x:Key="children" Type="{x:Type local:ChildViewModel}">
        <local:ChildViewModel Name="Child 1"/>
        <local:ChildViewModel Name="Child 2"/>
    </x:ArrayExtension>
</Window.Resources>

<StackPanel>
    <Button Content="{Binding Foo}" Height="20" Width="60"></Button>
    <ListView ItemsSource="{StaticResource children}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <local:ChildView/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackPanel>
</Window>

MainWindow.xaml.cs

namespace BindingTest
{
    public class MainViewModel
    {
        public string Foo { get; set; }
        public string Bar { get; set; }

        public MainViewModel()
        {
            Foo = "Foo";
            Bar = "Bar";
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new MainViewModel();
        }
    }
}

ChildView.xaml

<UserControl x:Class="BindingTest.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:BindingTest"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel Orientation="Horizontal">
        <Button Content="{Binding Name}"/>
        <Button Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}, Path=DataContext.Bar}"/>
    </StackPanel>
</UserControl>

ChildView.xaml.cs

namespace BindingTest
{
    public class ChildViewModel
    {
        public string Name { get; set; }

        public ChildViewModel()
        {
            Name = "Undefined";
        }
    }

    public partial class ChildView : UserControl
    {
        public ChildView()
        {
            InitializeComponent();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

渴望评论......我也使用RelativeSource Binding。但我用“Marker Interfaces”。这意味着我只是把它放在Views / UserControls上的空接口。

 public interface IMainWindowMarker {}


 public Window MainWindow : IMainWindowMarker {}

绑定与你的看起来大致相同但对我来说更具可读性。

<Button Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:IMainWindowMarker}}, Path=DataContext.Bar}"/>