wpf canvas itemscontrol

wpf - Cuando se utiliza ItemsControl ItemsControl.ItemsPanel se establece en Canvas, ContenPresenter entra y rompe mis propiedades Canvas en los elementos



(3)

Estoy usando ItemsControl donde el Panel de elementos está configurado en Lienzo (consulte esta pregunta para obtener más información de fondo). ItemsControl funciona como yo quiero, y funciona como un amuleto al agregar un elemento hijo manualmente al ponerlo en ItemsControl.Items:

<ItemsControl> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Canvas IsItemsHost="True" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.Items> <Button Canvas.Left="500" Content="Button Text" /> </ItemsControl.Items> </ItemsControl>

Tenga en cuenta la propiedad Canvas.Left en el botón. Esto funciona como un amuleto, y el botón se coloca a 500 píxeles de la izquierda del lado izquierdo de ItemsControl. ¡Estupendo!

Sin embargo, cuando estoy definiendo un enlace de ItemsSource a una lista, el Canvas.left no tiene ningún efecto:

<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>

Al inspeccionar la aplicación durante el tiempo de ejecución, veo una diferencia. El contenedor ContentPresenter se ha agregado entre el lienzo y el botón.

¿Cómo puedo establecer la propiedad Canvas.Left en el ContentPresenter mismo? ¿O hay otra forma de resolver este problema?

¡Gracias a todos!


El botón no tiene una propiedad "Lienzo", por lo que lo que está haciendo es hacer una llamada relativa al control de alojamiento, sin embargo, debido a que el artículo y el lienzo están en plantillas diferentes, no hay un enlace directo, debido a esto, el lienzo.Left no tiene sentido antes del tiempo de ejecución.

por lo tanto, su método no puede encontrar un elemento a la izquierda para perder el cambio.

Sin embargo Setters solo se implementan en tiempo de ejecución por lo

<Setter Property="Canvas.Left" Value="500" />

solo se ejecutará después de que los objetos hayan sido generados y, por lo tanto, tengan una relación relativa.

De lo contrario, puede usar el margen que pertenece al objeto del botón, pero de nuevo solo se interpreta en tiempo de ejecución


Es posible establecer la propiedad Canvas.Left con 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>


hay varias soluciones que vienen a mi mente:

  1. utilice un layout / rendertransform en lugar de la propiedad adjunta
  2. usar margen en lugar de la propiedad adjunta
  3. derivan de ItemsControl y anulan el comportamiento de cómo se generan los contenedores secundarios. (GetContainerForItemOverride, IsItemItsOwnContainerOverride). Este artículo explica muy bien cómo funciona: http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/