2011-11-30 131 views
1

我试图让自己从Control派生的ContentControl完全理解黑暗的wpf树概念。目前,我刚刚实现了ContentControl的逻辑部分(Content)。WPF:绑定找不到源

我后面的代码:

[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 Error: 4 : Cannot find source for binding with reference 'ElementName=textBlock'. BindingExpression:Path=Text; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

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

任何idee?

感谢您的时间。

乔纳斯

回答

1

我刚申请FrameworkElement.AddLogicalChild和FrameworkElement.RemoveLogicalChild当ContentChanged,并且绑定是正确应用(已验证与WPF检查员)。

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

我的代码:

[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(); 
     } 
    } 
} 
4

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

结合你想要的是不可能的,因为MyContentControl的同一实例理论上可以在其他地方的应用程序,其中的元素“文本块”不在范围内使用。

如果你想要做这种类型的结合,你可以使用,而不是资源:

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> 
+0

谢谢您的回答。我需要再考虑一下,但你的链接非常有帮助。我不想更改xaml,但我想知道在哪种方式下,我应该修改MyContentControl后面的代码,使其可以具有与ContentControl完全相同的行为。 – Jonas