2010-03-10 10 views
15

Estoy usando ItemsControl donde el ItemsPanel se establece en Canvas (consulte la pregunta this para obtener más información de fondo). El ItemsControl está funcionando como yo quiero, y funciona como un encanto cuando se añade un elemento secundario manualmente poniéndolo en ItemsControl.Items:Al usar ItemsControl ItemsControl.ItemsPanel se establece en Canvas, ContenPresenter entra y rompe mis propiedades Canvas en los elementos secundarios [WPF]

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

Nota Canvas.Left la propiedad 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 la unión a una lista de un ItemsSource, la 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> 

Mediante la inspección de la aplicación en 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 ContentPresenter? ¿O hay otra forma de resolver este problema?

¡Gracias a todos!

Respuesta

3

hay varias soluciones que vienen a la mente:

  1. utilizar un diseño/RenderTransform lugar de la propiedad adjunta
  2. margen de su uso en lugar de la propiedad adjunta
  3. derivan de ItemsControl, y reemplazar el comportamiento cómo se generan los contenedores para niños. (GetContainerForItemOverride, IsItemItsOwnContainerOverride). En este artículo se explica muy bien como funciona: http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/
25

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

parece extraño, pero esto funcionó para mí. – bryanbcook

+1

También puede enlazar el valor dentro de ItemContainerStyle y usará el mismo elemento que DataTemplate utiliza como fuente. :-) –

+0

Eres mi héroe hoy. Gracias. –

2

botón no tiene una propiedad "lienzo", así lo 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 Canvas.Left no tiene sentido antes del tiempo de ejecución.

por lo tanto, su método no puede encontrar un ajuste de la izquierda por lo que pierde el cambio.

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

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

solamente se ejecutará después de que los objetos se han generado y por lo tanto tienen una relación relativa.

contrario, puede utilizar el margen que no pertenecen al objeto de botón pero de nuevo sólo se interpreta en tiempo de ejecución

Cuestiones relacionadas