【问题标题】:Expose Parent's DataContext to children through Resource通过 Resource 将 Parent 的 DataContext 暴露给孩子
【发布时间】:2015-04-30 05:44:33
【问题描述】:

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

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

我想找到一种更简洁的方式来引用父级的 DataContext。有没有办法,例如,父级可以通过父级中定义的 Resource 公开对它的 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();
        }
    }
}

【问题讨论】:

  • 你为什么不喜欢 relativesource 的东西?
  • &lt;Button Content="{Binding Bar.SomeBarProperty}"/&gt; 怎么样?不需要其他任何东西。
  • @blindmeis - 对于一次性情况来说很好,但我希望有一种更简洁/可读/不易出错的方式来引用父级 DataContext 中的某些内容。如果有某种别名我可以设置它会是一半的字符和更简单的语法。
  • @Clemens - 抱歉,我不明白这个建议。 Bar 不是 ChildView.DataContext 包含的属性。你的意思是如果 ChildViewModel 有对 MainViewModel 的引用会怎样?
  • 在RelativeSource 示例中,您将Button 的内容绑定到MainWindow 的DataContext 中的Bar 属性。您不需要这样做,因为 DataContext 被继承到 MainWindow 的子元素。绑定可以写成Content="{Binding Bar}"

标签: c# wpf xaml resourcedictionary


【解决方案1】:

渴望评论...我也使用RelativeSource Binding。但我将它与“标记接口”一起使用。这意味着我在 Views/UserControls 上放置的只是空接口。

 public interface IMainWindowMarker {}


 public Window MainWindow : IMainWindowMarker {}

绑定看起来和你的差不多,但对我来说更具可读性。

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

【讨论】:

  • 不幸的是,这看起来与我的目的基本相同。我的目标是减少对一个标记的绑定引用,可能是父级公开的资源。 `
  • 但是如果你做这样的事情你必须看两个点来检查发生了什么。
猜你喜欢
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 2020-08-17
  • 2011-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-06
相关资源
最近更新 更多