2011-11-30 147 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