Я думаю, что у вас есть все в вашем вопросе для добавления пунктов в Canvas
вашего ListBox
. Я просто собрал простое тестовое приложение WPF, используя код в вашем вопросе, и это просто сработало. Всякий раз, когда я добавлял элементы к ObservableCollection
, который привязан к ItemsSource
из ListBox
, WPF создавал ListBoxItem
для этого объекта, и на основе стиля ListBoxItem
элемент отображался в правильном месте по Canvas
.
Вы не смогли заставить работать свой код выше? Если это так, какую ошибку вы получили или что не сработало, как вы ожидали?
Редактировать : После прочтения вопроса я думаю, что путаница связана с неправильным пониманием того, как работает привязка WPF. Когда вы связываете коллекцию с ItemsSource
*1016*, все, что вам нужно сделать, это добавить элементы в эту коллекцию (при условии, что коллекция реализует INotifyCollectionChanged
, что ObservableCollection
делает). WPF подписывается на события, предоставляемые этим интерфейсом, и создает / уничтожает ListBoxItems
на основе изменений, внесенных в список.
Редактировать 2 : хотя для этого лучше использовать DataTemplate
, чтобы строка автоматически добавлялась при добавлении элемента в коллекцию, я не уверен, как вы может получить позицию ранее добавленного элемента, чтобы строка начиналась в нужном месте.
Один из возможных вариантов работы - подкласс Canvas
и значение ItemsPanelTemplate
для ListBox
. Я считаю, что у него есть функция, которую вы можете переопределить, которая вызывается всякий раз, когда к ней добавляется элемент управления. В этой функции вы можете получить позицию ранее добавленного элемента управления (которая будет кэшироваться в вашем подклассе Canvas
), а затем добавить элемент управления строкой к элементам управления Canvas
напрямую. Это предполагает, что положение элементов управления в Canvas
не может измениться. Если это возможно, вам, вероятно, придется подписаться на событие PropertyChanged
объекта и соответствующим образом обновить строки.
Редактировать 3 : Поскольку привязка не выглядит как вариант из-за ваших требований, наименее плохой вариант - просто добавить дочерние элементы напрямую. Это можно сделать, выполнив поиск по визуальному дереву с помощью VisualTreeHelper.GetChild () :
private T FindChild<T>(FrameworkElement parent, string name)
where T : FrameworkElement
{
FrameworkElement curObject = null;
T obj = default(T);
int count = VisualTreeHelper.GetChildrenCount(parent);
for(int i = 0; i < count; i++)
{
curObject = VisualTreeHelper.GetChild(parent, i) as FrameworkElement;
obj = curObject as T;
if(null != obj && obj.Name.Equals(name))
{
break;
}
obj = FindChild<T>(curObject, name);
if(null != obj)
{
break;
}
}
return obj;
}
Используйте это так:
Canvas canvas = FindChild<Canvas>(lstAwesome, "cnvAwesome");
Этот код рекурсивно ищет в визуальном дереве parent
элемент управления указанного типа и имени. Здесь было бы лучше использовать DependencyObject
сверх FrameworkElement
(поскольку именно это возвращает VisualTreeHelper.GetChild()
), однако Name
определяется только для FrameworkElement
.
Если вы хотите получить фантазию, вы даже можете сделать это методом расширения.