【问题标题】:WPF : Binding cannot find sourceWPF:绑定找不到源
【发布时间】:2011-11-30 14:07:34
【问题描述】:

我尝试制作自己的从 Control 派生的 ContentControl,以完全理解深色 wpf 树的概念。目前,我只是实现了 ContentControl 的逻辑部分(内容)。

我的代码:

[ContentProperty("Content")]
public class MyContentControl : Control
{
    public MyContentControl()
    {

    }

    public Object Content
    {
        get { return (Object)GetValue(ContentProperty); }
        set { SetValue(ContentProperty, value); }
    }

    public static readonly DependencyProperty ContentProperty =
        DependencyProperty.Register("Content", typeof(Object), typeof(MyContentControl), new UIPropertyMetadata());

}

XAML:

<StackPanel x:Name="stackPanel">
    <TextBlock Visibility="Collapsed" x:Name="textBlock" Text="Hello World"/>
    <ContentControl>
        <TextBlock Background="LightBlue" Text="{Binding Text, ElementName=textBlock}"/>
    </ContentControl>
    <local:MyContentControl>
        <TextBlock Text="{Binding Text, ElementName=textBlock}"/>
    </local:MyContentControl>
</StackPanel>

我收到以下绑定错误:

System.Windows.Data 错误:4:找不到引用“ElementName=textBlock”的绑定源。绑定表达式:路径=文本;数据项=空;目标元素是'TextBlock'(名称='');目标属性是“文本”(类型“字符串”)

这就像内部的 TextBlock 无法在逻辑树中找到它应该绑定的原始文本块。我无法将 myContentControl 设置为 Content 对象的父级。

有什么想法吗?

感谢您的宝贵时间。

乔纳斯

【问题讨论】:

    标签: wpf binding custom-controls


    【解决方案1】:

    相关问题:Binding ElementName. Does it use Visual Tree or Logical Tree

    您想要的绑定是不可能的,因为 MyContentControl 的相同实例理论上可以在应用程序中元素“textBlock”不在范围内的其他地方使用。

    如果您想进行这种类型的绑定,您可以改用 Resource:

    xmlns:clr="clr-namespace:System;assembly=mscorlib"
    
    <StackPanel>
        <StackPanel.Resources>
            <clr:String x:Key="MyText">Hanky Panky</clr:String>
        </StackPanel.Resources>
        <TextBlock Text="{StaticResource MyText}" />
    
        <ContentControl>
            <TextBlock Text="{Binding Source={StaticResource MyText}}" />
        </ContentControl>
    </StackPanel>
    

    【讨论】:

    • 感谢您的回答。我需要再考虑一下,但是您的链接非常有帮助。我不想更改 xaml,但我想知道我应该以哪种方式修改 MyContentControl 背后的代码,因为它可以具有与 ContentControl 完全相同的行为。
    【解决方案2】:

    我只需要在 ContentChanged 和绑定正确应用时应用 FrameworkElement.AddLogicalChild 和 FrameworkElement.RemoveLogicalChild(使用 WPF Inspector 验证)。

    所以这一切都是关于 LogicalTree 的(也许 xaml 名称范围是从逻辑父级继承的)。当 MyContentControl.AddLogicalChild(TextBlock) 被调用时,MyContentControl 中的 TextBlock 将 MyContentControl 作为 Parent。

    我的代码:

    [ContentProperty("Content")]
    public class MyContentControl : Control
    {
        public MyContentControl()
        {
            Content = new UIElementCollection(this, this);
        }
    
    
        public Object Content
        {
            get { return (Object)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }
    
        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register("Content", typeof(Object), typeof(MyContentControl), new UIPropertyMetadata(new PropertyChangedCallback(OnContentChanged)));
    
        public static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MyContentControl c = (MyContentControl)d;
    
            if (e.OldValue != null)
            {
                c.RemoveLogicalChild(e.OldValue);
            }
    
            c.AddLogicalChild(e.NewValue);
        }
    
        protected override System.Collections.IEnumerator LogicalChildren
        {
            get
            {
                List<Object> l = new List<object>();
                if (Content != null)
                    l.Add(Content);
    
                return l.GetEnumerator();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-31
      • 2018-04-01
      • 2016-01-12
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多