При использовании ItemsControl ItemsControl.ItemsPanel устанавливается в Canvas, ContenPresenter входит и разбивает мои свойства Canvas на дочерних [WPF]
Я использую ItemControl, где для параметра ItemsPanel задано значение Canvas (см. этот вопрос для получения дополнительной информации).
Элемент ItemsControl выполняется так, как я хочу, и он работает как шарм при добавлении дочернего элемента вручную, помещая его в ItemControl.Items:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Items>
<Button Canvas.Left="500" Content="Button Text" />
</ItemsControl.Items>
</ItemsControl>
Обратите внимание на свойство Canvas.Left на Button. Это работает как шарм, а кнопка расположена на 500 пикселей слева от левой части ItemsControl. Отлично!
Однако, когда я определяю привязку ItemsSource к списку, Canvas.left не имеет никакого эффекта:
<ItemsControl ItemsSource="{Binding Elements}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Canvas.Left="500" Content="Button Text" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Проверяя приложение во время выполнения, я вижу одно различие. Контейнер ContentPresenter добавлен между холстом и кнопкой.
Как установить свойство Canvas.Left на ContentPresenter? Или есть другой способ решить эту проблему?
Спасибо всем!
Ответы
Ответ 1
Есть несколько решений, которые приходят мне на ум:
- используйте свойство layout/rendertransform вместо прикрепленного свойства
- использовать поля вместо прикрепленного свойства
- выводится из ItemsControl и переопределяет поведение, как генерируются дочерние контейнеры. (GetContainerForItemOverride, IsItemItsOwnContainerOverride). В этой статье очень хорошо объясняется, как это работает: http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/
Ответ 2
Можно установить свойство Canvas.Left с помощью ItemContainerStyle:
<ItemsControl ItemsSource="{Binding Elements}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="Button Text" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="500" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Ответ 3
Кнопка Не имеет свойства "Canvas", поэтому вы делаете относительный вызов элемента управления хостингом, однако, поскольку элемент и холст находятся в разных шаблонах, прямой ссылки нет, из-за этого Canvas.Left не имеет смысла перед выполнением.
следовательно, ваш метод не может найти левое значение, поэтому он теряет изменение.
Однако сеттеры реализованы только во время выполнения, поэтому
<Setter Property="Canvas.Left" Value="500" />
запускается только после того, как объекты были сгенерированы и, следовательно, имеют относительные отношения.
В противном случае вы можете использовать поле, которое принадлежит объекту кнопки, но снова интерпретируется только во время выполнения