我尝试创建自己的ContentControl,它来自Control,以完全理解黑暗的wpf树概念。目前,我刚刚实现了ContentControl的逻辑部分(Content)。
我的代码背后:
[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'的绑定源。 BindingExpression:路径=文本;的DataItem = NULL; target元素是'TextBlock'(Name =''); target属性是'Text'(类型'String')
就像内部TextBlock无法在逻辑树中上升并找到它应该绑定的原始文本块。我无法将myContentControl设置为Content对象的父级。
任何想法?
感谢您的时间。
纳斯
答案 0 :(得分:4)
相关问题:Binding ElementName. Does it use Visual Tree or Logical Tree
您想要的绑定是不可能的,因为MyContentControl的相同实例理论上可以在应用程序中的其他位置使用,其中元素“textBlock”不在范围内。
如果你想做这种类型的绑定,你可以改用资源:
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>
答案 1 :(得分:2)
当ContentChanged和绑定正确应用时,我必须应用FrameworkElement.AddLogicalChild和FrameworkElement.RemoveLogicalChild(使用WPF检查器验证)。
所以这一切都与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();
}
}
}