Я разрабатываю UserControl, который содержит ItemsControl TextBoxes. У меня есть класс титров, который используется для контроля местоположения / Текст TextBlock
В окне 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: создано выражение привязки
(хэш = 14626603) для привязки (хэш = 8360729)
System.Windows.Data Предупреждение: 56: Путь: 'X'
System.Windows.Data Предупреждение: 58: BindingExpression (хэш = 14626603):
Режим по умолчанию разрешен в OneWay
System.Windows.Data Предупреждение: 59: BindingExpression (хэш = 14626603):
Триггер обновления по умолчанию разрешен в PropertyChanged
System.Windows.Data Предупреждение: 60: BindingExpression (хэш = 14626603):
Присоединить к WpfApplicationQuery.Caption.Left (hash = 33822626)
System.Windows.Data Предупреждение: 65: BindingExpression (хэш = 14626603):
Разрешающий источник
System.Windows.Data Предупреждение: 68: BindingExpression (хэш = 14626603):
Найденный элемент контекста данных: заголовок (хэш = 33822626) (ОК)
System.Windows.Data Предупреждение: 76: BindingExpression (хэш = 14626603):
Активировать с помощью корневого элемента
System.Windows.Data Предупреждение: 104: BindingExpression (хэш = 14626603):
Элемент на уровне 0 нулевой - нет доступа
System.Windows.Data Предупреждение: 78: BindingExpression (хэш = 14626603):
TransferValue - получил необработанное значение {DependencyProperty.UnsetValue}
System.Windows.Data Предупреждение: 86: BindingExpression (хэш = 14626603):
TransferValue - использование запасного значения / значения по умолчанию 'NaN'
System.Windows.Data Предупреждение: 87: BindingExpression (хэш = 14626603):
TransferValue - использование окончательного значения 'NaN'
Ошибка System.Windows.Data: 26: ItemTemplate и ItemTemplateSelector
игнорируются для элементов, уже имеющих тип контейнера ItemsControl;
Тип = 'Заголовок'
Так что, похоже, он привязан неправильно, и я не знаю, что означает последняя ошибка
Кроме того, ранее у меня был Caption, полученный из DependencyObject, и все работало (т.е. все отображалось), кроме привязки данных. Отсюда переход к framworkElement, как описано где-то на stackoverflow (и в блоге, который я сейчас не могу найти)
Редактировать 2012-02-14
Изменен первый пример кода XAML
Редактировать 2012-02-14
Заголовок происходит от 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.