【问题标题】:WPF Binding inner control with parent data contextWPF 绑定内部控件与父数据上下文
【发布时间】:2014-12-20 07:12:19
【问题描述】:

我做了一个用户控件

<UserControl x:Class="MyApp.MyControl"
         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"  x:Name="uc">
<Grid Width="Auto" Height="Auto">
    <TextBlock Text="{Binding Path=DataContext.TextContent, ElementName=uc}"/>
    <TextBlock Text="{Binding Path=DataContext.TextContent2, ElementName=uc}"/>
</Grid>

我希望定义的控件(uc)中的子控件将绑定到 uc.DataContext 的属性。我使用定义的控件如下:

<Window x:Class="Tms.TMSClient.Views.MainWindow" Name="window"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:control="clr-namespace:MyApp"
    xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary">      

    <control:MyControl DataContext="{Binding Path=MyControlVM}"/>

分配给窗口的DataContext具有这样的结构:WindowVM.MyControlVM.TextContent。

给定的代码不起作用,因为文本框的 DataContext 已绑定到 WindowVM。我认为问题可能是因为内部文本框是在定义的控件(uc)之前绑定的,因此 uc 的有界 DataContext 尚未生效。

我想要的是:自定义控件(MyControl)将绑定到其对应的视图模型(MyControlVM),而MyControl的内部元素将绑定到MyControlVM的属性。

你有解决这个问题的办法吗?

【问题讨论】:

  • 您是否有机会在MyApp.MyControl 中执行DataContext = this 之类的操作?另外,如果你不改变DataContext控制{Binding TextContent}应该足够了
  • 您将MyControlVM.DataContext 设置为MyControlVM,并且由于它是通过可视化树继承的,因此默认情况下以及在您更改之前,它内部的所有内容都将具有DataContext。在您的情况下,TextBlockGridUserControl 将具有相同的 DataContext 从外部设置为 MyControlVM

标签: c# wpf binding user-controls


【解决方案1】:

如果我理解正确,您希望将MyControl 视图模型中的属性数据绑定到MyControl UserControl 内的TextBox.Text 属性。如果正确,那么您可以使用 RelativeSource Binding 或您已经在使用的 ElementName 语法。

首先,确保您的视图模型设置为DataContextUserControl

public MyControl()
{
    DataContext = new YourControlViewModel();
}

由于子控件自动继承其父级的DataContext 对象,您现在可以通过UserControl 的XAML 中的MyControl.DataContext 属性从TextBox 引用此视图模型:

<TextBlock Text="{Binding DataContext.TextContent, 
    RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />

这就是你所需要的。

【讨论】:

    【解决方案2】:
    <TextBlock Text="{Binding Path=TextContent}"/>
    

    在我的测试应用程序中为我工作。

    MainWindow.xaml

    <Window x:Class="DataContextTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:DataContextTest"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <my:MyOuterDataContext />
    </Window.DataContext>
    <Grid>
        <my:MyControl DataContext="{Binding Path=MyInnerDataContext}" />
    </Grid>
    

    MyControl.xaml

    <UserControl x:Class="DataContextTest.MyControl"
             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">
    <Grid>
        <TextBlock Text="{Binding Path=TextContent}" />
    </Grid>
    

    数据上下文:

    public class MyOuterDataContext
    {
        public MyInnerDataContext MyInnerDataContext { get; set; }
    
        public MyOuterDataContext()
        {
            MyInnerDataContext = new MyInnerDataContext();
        }
    }
    
    public class MyInnerDataContext
    {
        public string TextContent { get { return "foo"; } }
    }
    

    【讨论】:

      【解决方案3】:

      默认情况下,每个控件都从其父控件继承其 DataContext。因此无需显式绑定到它。

      确实,当您想将控件的 DataContext 绑定到嵌套属性时,您必须指定以下内容:

      <control:MyControl DataContext="{Binding Path=TextContent}"/>
      

      【讨论】:

      • 定义的控件可能有很多内部元素,所以按照你的建议直接绑定是不好的。我想要的是:自定义控件(MyControl)将绑定到其对应的视图模型(MyControlVM),而MyControl的内部元素将绑定到MyControlVM的属性
      • 哇@ThomasLee,你真的没有在听这里的任何人,是吗? DataContext 默认由所有子控件自动继承。我看不出你的代码有任何问题,所以你一定有其他东西干扰它。
      猜你喜欢
      • 1970-01-01
      • 2010-11-10
      • 2013-01-20
      • 2016-03-15
      • 2015-03-12
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 2015-11-04
      相关资源
      最近更新 更多