c# - 无法获取内部 XAML 绑定(bind)以针对依赖项属性工作

标签 c# wpf xaml dependency-properties data-binding

我有一个用户控件“CtrlComments”,该控件具有以下 XAML(非常基本)。

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:wpftoolkit="http://schemas.microsoft.com/wpf/2008/toolkit" 
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" 
x:Name="ucRoot">
<Grid>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="ID: " />
        <TextBlock Text="{Binding Path=Deployment.Id}" />
    </StackPanel>
</Grid>

背后的代码如下,这是使控件发挥作用的基础知识。关键是 DependencyObject typeof(DeploymentDto),它有一个 int属性名为 Id我们有兴趣根据上面的 XAML 绑定(bind)在窗口上显示。

public partial class CtrlComments : UserControl, INotifyPropertyChanged
{
    public static readonly DependencyProperty DeploymentProperty =
        DependencyProperty.Register("Deployment", typeof(DeploymentDto),
                                    typeof(CtrlComments), new PropertyMetadata(new DeploymentDto()));

    public DeploymentDto Deployment
    {
        get
        {
            return (DeploymentDto)GetValue(DeploymentProperty);
        }
        set
        {
            SetValue(DeploymentProperty, value);
            OnPropertyChanged(new PropertyChangedEventArgs("Deployment"));
        }
    }

    public CtrlComments()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, e);
    }
}

我们的问题是,尽管父控件和我的用户控件之间通过依赖属性的绑定(bind)正在工作(已验证)并且 OnPropertyChanged方法触发,TextBlock我的 XAML 中的内容没有更新。

我注意到当 OnPropertyChanged方法运行后,事件处理程序为null这意味着没有人会收到有关属性发生更改的通知。

我不明白为什么会这样。如果您能帮助解释我们哪里出了问题,我们将不胜感激。

谢谢!

最佳答案

我尝试复制您的问题,在这样做时,我发现我的问题出在 CtrlComments 中的以下行:

this.DataContext = this;

放弃这条线让它对我有用。另请注意(正如 @Aron 在评论中所写),在 DependencyProperty 的 setter 中不应调用 INotifyPropertyChangedOnPropertyChanged 。至少对我来说根本没有必要实现 INPC。

在使用 UserControl 的 XAML 文件中,您很可能会设置另一个 DataContext(在更高级别上,可能在 Window 中),并且因此,我想如果已经在那里设置(或覆盖),它就不会继承到用户控件。下面是我的工作代码,但也许我完全误解了你在做什么。如果是这种情况,请扩展您的问题以包括您如何使用 UserControl,因为如果这不起作用,这是回答问题的关键:)

CtrlComments.xaml:

<UserControl x:Class="WpfApplication1.CtrlComments"
             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>
    <StackPanel Orientation="Horizontal">
      <TextBlock Text="ID: "/>
      <TextBlock Text="{Binding Path=Deployment.Id}"/>
    </StackPanel>
  </Grid>
</UserControl>

CtrlComments.xaml.cs:

namespace WpfApplication1
{
  public partial class CtrlComments : UserControl
  {
    public static readonly DependencyProperty DeploymentProperty =
      DependencyProperty.Register("Deployment", typeof(DeploymentDto), typeof(CtrlComments), new PropertyMetadata(new DeploymentDto { Id = 5 }));

    public DeploymentDto Deployment
    {
      get { return (DeploymentDto)GetValue(DeploymentProperty); }
      set
      {
        SetValue(DeploymentProperty, value);
      }
    }

    public CtrlComments()
    {
      InitializeComponent();
    }
  }
}

MainWindow.xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:WpfApplication1"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <StackPanel>
    <local:CtrlComments x:Name="testUC" Height="100" Deployment="{Binding Deployment}"/>
    <Button Click="Button_Click" Height="50" Width="100"/>
  </StackPanel>
</Window>

MainWindow.xaml.cs:

namespace WpfApplication1
{
  public partial class MainWindow : Window, INotifyPropertyChanged
  {
    public MainWindow()
    {
      InitializeComponent();
    }

    private DeploymentDto deployment = new DeploymentDto { Id = 2 };
    public DeploymentDto Deployment
    {
      get { return deployment; }
      set { deployment = value; OnPropertyChanged("Deployment"); }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
      Deployment = new DeploymentDto { Id = new Random().Next(100) };
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propName)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
      }
    }
  }
}

部署Dto:

public class DeploymentDto
{
  public int Id { get; set; }
}

MainWindow.DataContext 绑定(bind)到它的代码隐藏是相当难看的,但由于它只是用于示例目的,我希望它没问题:)

关于c# - 无法获取内部 XAML 绑定(bind)以针对依赖项属性工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28871217/

相关文章:

c# - 无法绑定(bind)到 DataContext 的属性

wpf - {x :Null} vs. 透明?

wpf - 如何序列化 xaml "Brush"?

c# - 键入通用值 (C#)

c# - .net core 自定义身份验证中的 User.Identity.IsAuthenticated 始终为 false

c# - WPF 媒体元素的背景图像

c# - 如何动态更新 Assemblyinfo.cs 中的值

c# - 从 URL 和路径中的非法字符获取下载的文件

javascript - asp.net 上的慢速 C# websockets

wpf - 适用于 XAML 的 Windows Metro 中的 DrawingBrush 在哪里