我正在开发一个包含TextBoxes的ItemsControl的UserControl。我有一个标题类,用于控制TextBlock的位置/文本
在Window XAML中
<local:UserControl1>
<local:UserControl1.Captions>
<local:Caption Foreground="Black" Size="10" Text="{Binding Path=SomeText}" X="100" Y ="100"></local:Caption>
</local:UserControl1.Captions>
</local:UserControl1>
ItemsControl是一个画布,其中dataTemplate是一个TextBox
<ItemsControl ItemsSource="{Binding Path=Captions}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Beige" Width="{Binding Path=Width}" Height="{Binding Path=Height}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Text}" Foreground="{Binding Path=Foreground}" FontSize="{Binding Path=Size}" ></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Top" Value="{Binding Path=Y,PresentationTraceSources.TraceLevel=High}" />
<Setter Property="Canvas.Left" Value="{Binding Path=X,PresentationTraceSources.TraceLevel=High}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
在UserControl中是一个ObservableCollection“Caption”,它派生自Framework元素
public class Caption :FrameworkElement
{
/// <summary>
/// The actual text to display
/// </summary>
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
/// <summary>
/// The font size
/// </summary>
public int Size
{
get { return (int)GetValue(SizeProperty); }
set { SetValue(SizeProperty, value); }
}
/// <summary>
/// The text foreground color
/// </summary>
public Brush Foreground
{
get { return (Brush)GetValue(ForegroundProperty); }
set { SetValue(ForegroundProperty, value); }
}
/// <summary>
/// The Top location of the text
/// </summary>
public double Y
{
get { return (double)GetValue(YProperty); }
set { SetValue(YProperty, value); }
}
/// <summary>
/// The left location of the text
/// </summary>
public double X
{
get { return (double)GetValue(XProperty); }
set { SetValue(XProperty, value); }
}
public override string ToString()
{
return string.Format("Caption:{0}//{1}.{2}", this.X, this.Y, this.Text);
}
private static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string),
typeof(Caption),
new PropertyMetadata(
OnPropertyChanged));
private static readonly DependencyProperty SizeProperty = DependencyProperty.Register("Size", typeof(int),
typeof(Caption),
new PropertyMetadata(
OnPropertyChanged));
private static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register("Foreground",
typeof(Brush),
typeof(Caption),
new PropertyMetadata
(OnPropertyChanged));
private static readonly DependencyProperty YProperty = DependencyProperty.Register("Y", typeof(double),
typeof(Caption),
new PropertyMetadata(
OnPropertyChanged));
private static readonly DependencyProperty XProperty = DependencyProperty.Register("X", typeof(double),
typeof(Caption),
new PropertyMetadata(
OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var caption = (Caption)d;
}
}
每次将标题添加到集合时,它都会添加到逻辑树
void Captions_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if(e.Action == NotifyCollectionChangedAction.Add)
{
foreach(Caption c in e.NewItems)
{
AddLogicalChild(c);
c.DataContext = this.DataContext;
}
}
}
问题是Canvas.Top
和Canvas.Left
的绑定无法正常工作
调试产生以下
System.Windows.Data警告:54:创建BindingExpression (hash = 14626603)用于绑定(hash = 8360729)
System.Windows.Data警告:56:路径:'X'
System.Windows.Data警告:58:BindingExpression(hash = 14626603): 默认模式已解决为OneWay
System.Windows.Data警告:59:BindingExpression(hash = 14626603): 默认更新触发器已解析为PropertyChanged
System.Windows.Data警告:60:BindingExpression(hash = 14626603): 附加到WpfApplicationQuery.Caption.Left(hash = 33822626)
System.Windows.Data警告:65:BindingExpression(hash = 14626603): 解决来源
System.Windows.Data警告:68:BindingExpression(hash = 14626603): 找到数据上下文元素:Caption(hash = 33822626)(OK)
System.Windows.Data警告:76:BindingExpression(hash = 14626603): 使用根项目激活
System.Windows.Data警告:104:BindingExpression(hash = 14626603): 级别0的项目为空 - 无访问者
System.Windows.Data警告:78:BindingExpression(hash = 14626603): TransferValue - 获得原始值{DependencyProperty.UnsetValue}
System.Windows.Data警告:86:BindingExpression(hash = 14626603): TransferValue - 使用后备/默认值'NaN'
System.Windows.Data警告:87:BindingExpression(hash = 14626603): TransferValue - 使用最终值'NaN'
System.Windows.Data错误:26:ItemTemplate和ItemTemplateSelector 对于已经属于ItemsControl容器类型的项目,将被忽略; 类型= '标题'
所以它似乎绑定不正确,我不知道最后一个错误意味着什么
此外,之前,我有从DependencyObject派生的Caption,并且一切正常(.i.e显示的东西),但Databinding除外。因此切换到framworkElement,如stackoverflow上的某处所述(以及我现在找不到的博客帖子)
修改2012-02-14 更改了第一个XAML示例代码
修改2012-02-14 Caption派生自FrameworkElement,因此它可以参与此处所述的数据绑定 http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/aff23943-5483-40b2-816b-4ce687bc6bf8/ 和这里 http://kentb.blogspot.com/2008_10_01_archive.html
如果Caption实现了INotifyPropertyChanged
<local:UserControl1>
<local:UserControl1.Captions>
<local:Caption Foreground="Black" Size="10" Text="Hello" X="100" Y ="100"></local:Caption>
<local:Caption Foreground="Black" Size="10" Text="{Binding Path=Title}" X="100" Y ="100"></local:Caption>
</local:UserControl1.Captions>
</local:UserControl1>
第一行有效。第二个没有,这个错误被追踪。
无法为目标元素
找到管理FrameworkElement或FrameworkContentElement
但是,如果Caption派生自FrameworkElement,它现在提供它自己的ItemTemplate 因此产生了与ItemTemplate / Selector相关的绑定错误。