【问题标题】:DependencyObject cannot find governing FrameworkElement for target element, even when that object is in the Logical Tree of a FrameworkElementDependencyObject 无法找到目标元素的管理 FrameworkElement,即使该对象位于 FrameworkElement 的逻辑树中
【发布时间】:2016-04-14 11:25:30
【问题描述】:

在对Cannot find governing FrameworkElement or FrameworkContentElement for target element 错误进行了一些研究后,我发现依赖对象不能真正具有可绑定的依赖属性,除非它们是 FrameworkElements 或在其中的元素树中。

但是,我有一个拥有 DependencyObjects 的 FrameworkElement,我无法将绑定发送到这些 DependencyObjects 属性,即使它们是 FrameworkElement 逻辑树的一部分。

我正在编写一个带有子元素的复杂自定义控件,我需要这些子元素是 DependencyObjects(但不是 FrameworkElements,因为它们会被许多未使用的属性污染,并且可能会使用户感到困惑) ,并且我还需要它们的 DependencyProperties 是可绑定的。

我错过了什么?还有什么我需要告诉 DependencyObjects 以便他们知道他们在逻辑树中的吗?即使冻结它们没有意义,我是否应该将它们设为 Freezable?

干杯

【问题讨论】:

  • 任何依赖属性都是可绑定的,只是没有明确的 Source 就不能工作。至于您的问题:到目前为止,如果您的属性不属于可视化树或逻辑树,那么您唯一让它继承父数据上下文的选择确实是使其可冻结。
  • @Evk:经过一番研究和玩耍,我发现我的属性不会出现在 Live Tree Inspector 中。我需要进一步调查,因为我确信覆盖 LogicalChildren 枚举器就足够了。

标签: c# .net wpf


【解决方案1】:

我认为你的结论和推论并不完全正确。

第一件事WPF 中,一切都源自DependencyObjectFrameworkElement 类没有任何不同。如果您查看FrameworkElement 类的层次结构,如下所示:

DependencyObject --> Visual --> UIElement --> FrameworkElement

因此,如果您尝试在派生自上述任何类的类中创建 Dependency Property,它将正常工作(不包括直接绑定,但其他方式绑定工作(参见下面的示例))。您的CustomControl(不确定您使用的是CustomControl 还是UserControl)代码一定有问题。

但是从UIElement派生的类也可以有DependencyProperties,可以绑定到其他元素。

UIElement类,它有很多DependencyProperties

请分享您的控件代码,我们可以调查一下。

更新:

这是一个如何绑定DependecyObject's DependencyProperty 的示例:

DependencyObject 实施:

public class MyClass : DependencyObject
{
    public MyClass()
    {
        this.Button = new Button();
        Button.Width = 500;
        Button.Height = 400;
        Button.Content = "Bound to Window Height";
    }

    private Binding height;
    public Binding Height
    {
        get { return height; }
        set 
        {
            height = value;
            ApplyBinding();
        }
    }

    public Button Button { get; set; }
    private void ApplyBinding()
    {
        this.Button.SetBinding(Button.HeightProperty, this.Height);
    }

}

使用我们的DependencyObject 实现的UserControl

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

    public MyClass MyClass
    {
        get { return (MyClass)GetValue(MyClassProperty); }
        set { SetValue(MyClassProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyClass.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyClassProperty =
        DependencyProperty.Register("MyClass", typeof(MyClass), typeof(MyUserControl), new UIPropertyMetadata(new PropertyChangedCallback(MyClassPropertyChanged)));


    private static void MyClassPropertyChanged(DependencyObject DO, DependencyPropertyChangedEventArgs e)
    {
        var MUC = DO as MyUserControl;
        if (e.NewValue != null)
        {
            var myClass = e.NewValue as MyClass;                
            MUC.MyCanvas.Children.Add(myClass.Button);
        }
    }

}

最后绑定:

<Window x:Class="WpfStackOverflowTempProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow"  Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
    xmlns:local="clr-namespace:WpfStackOverflowTempProject"     
    Height="{Binding ElementName=UIContent,Path=MyClass.HeightReplica,Mode=OneWayToSource}"
    >
<local:MyUserControl x:Name="UIContent" >
    <local:MyUserControl.MyClass>
        <local:MyClass Height="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=ActualHeight,Mode=OneWay}" />
    </local:MyUserControl.MyClass>
</local:MyUserControl>

所以当我们的WindowHeight 发生变化时,上述程序的输出, 它将反射回我们的MyClass 组件的按钮element 就像我们在 XAML 代码中绑定到 Button 本身一样。 所以 Myclass 是它的逻辑父控件和它的 用于指定公开属性/绑定的子元素 并定义它们对应于子元素的行为, 这实际上将在 UI 上可见,MyClass 仅适用 就像一个习惯用法的过滤器。

【讨论】:

  • 作者的意思不同。尝试做 你会看到问题出在哪里(它不起作用)。现在从 Freezable 继承你的 MyClass ,然后它就可以工作了。
  • @Evk 不确定此处是否使用 Freezable,但除此之外,您有点重复我上面解释的内容。我的意思是说,如果 OP 正在做一些事情,比如将 DP 绑定到 dependencyObject 中,他可以以与其他 UI 元素相反的方式来做这件事,如果对他来说可行的话。
  • @Evk 谈到 Freezable 我记得它导致了绑定和/或绑定行为的问题(我记得 DP 值反射,虽然不太确定),所以使用起来有点冒险
  • WPF 开发人员以一种特殊的方式处理可冻结对象,以完全允许上述用例,例如允许在 Button.Background 中绑定 SolidColorBrush.Color。例如,请参见此处:blogs.msdn.microsoft.com/nickkramer/2006/08/17/…。在大多数情况下,您无法反转该绑定。虽然我不喜欢仅仅为了允许这种行为而从 freezable 继承 - 它似乎是目前唯一的选择。
  • 不幸的是,我不能要求我的组件的用户为其编写反向绑定而不是常规绑定。我了解 DependencyProperties 在 DependencyObjects 上工作,但除非我们谈论的是 Freezable 或 FrameworkElement / FrameworkContentElement,否则不会继承 DataContext。而且这两个课程都有很多包袱。
猜你喜欢
  • 2021-08-22
  • 2016-06-02
  • 2013-08-22
  • 2020-02-10
  • 2013-08-17
  • 2014-02-03
  • 2023-03-18
  • 2013-03-24
相关资源
最近更新 更多