2010-02-10 5 views
14

Je reposter cette question que je n'ai pas eu beaucoup d'une réponse dernière fois, je l'espère un peu de re-formulation pourrait aider ...WPF Toile Mise à l'échelle/Transformer pour Fit

Essentiellement ce que je suis essayer de faire est de créer un canevas de databound, qui mettra automatiquement à l'échelle son contenu pour «remplir» l'espace disponible. Un peu comme un zoom pour s'adapter à l'opération. Malheureusement, mes compétences WPF ne sont pas encore très solides, et j'ai du mal à trouver comment faire cette dernière partie. J'ai suivi quelques exemples de liaison de données pour obtenir la toile liée, mais je ne sais pas si c'est peut-être faux et me gêner.

J'ai deux problèmes de base au moment en fonction de la façon dont je tente de faire face à la solution, soit:

  • Je ne sais pas comment faire la ré-échelle de la toile automatiquement par XAML si c'est possible en utilisant une transformation .
  • Je ne peux pas sembler à référence la toile dans le code derrière, je devine parce que sa partie d'un ItemsControl?

Un exemple de ce que je suis en train de réaliser, j'ai AI veulent essayer d'obtenir B:

(enlevé lien a expiré à une img)

Le code I « m actuellement à l'aide est assez simple, ce qui crée à seulement 4 points avec une coordonnée donnée, et un modèle autre vue pour envelopper dans ces.

public class PointCollectionViewModel 
{ 
    private List<PointViewModel> viewModels; 
    public PointCollectionViewModel() 
    { 
     this.viewModels = new List<PointViewModel>(); 
     this.viewModels.Add(new PointViewModel(new Point(1, 1))); 
     this.viewModels.Add(new PointViewModel(new Point(9, 9))); 
     this.viewModels.Add(new PointViewModel(new Point(1, 9))); 
     this.viewModels.Add(new PointViewModel(new Point(9, 1))); 
    } 

    public List<PointViewModel> Models 
    { 
     get { return this.viewModels; } 
    } 
} 

public class PointViewModel 
{ 
    private Point point; 
    public PointViewModel(Point point) 
    { 
     this.point = point; 
    } 

    public Double X { get { return point.X; } } 
    public Double Y { get { return point.Y; } } 
} 

Ensuite, le PointCollectionViewModel est utilisé comme DATACON tente pour mes AutoResizingCanvas, qui a la XAML suivante pour mettre en œuvre la liaison:

<UserControl x:Class="WpfCanvasTransform.AutoResizingCanvas" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfCanvasTransform" 
    x:Name="parent"> 
    <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Path=Models}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
     <Canvas x:Name="canvas" Background="DarkSeaGreen" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
      <Canvas.LayoutTransform> 
      <ScaleTransform ScaleY="-1" /> 
      </Canvas.LayoutTransform> 

     </Canvas> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate DataType="{x:Type local:PointViewModel}"> 
     <Ellipse Width="3" Height="3" Fill="Red"/> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
    <ItemsControl.ItemContainerStyle> 
     <Style> 
     <Setter Property="Canvas.Top" Value="{Binding Path=Y}"/> 
     <Setter Property="Canvas.Left" Value="{Binding Path=X}"/> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
    </ItemsControl> 
</UserControl> 

Répondre

17

Comme votre Canvas je n'inclure semble pas avoir fixé la largeur et la hauteur, en un Viewbox:

<ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <Viewbox Stretch="Uniform"> 
      <Canvas x:Name="canvas" Background="DarkSeaGreen"> 
       <Canvas.LayoutTransform> 
       <ScaleTransform ScaleY="-1" /> 
       </Canvas.LayoutTransform> 
      </Canvas> 
     </Viewbox> 
    </ItemsPanelTemplate> 
</ItemsControl.ItemsPanel> 

Vous pouvez également placer votre UserControl entier dans un ViewBox.

+3

@Mart: Très intéressant, on dirait qu'il est proche de ce que je veux. Si je change mon code comme vous l'avez suggéré, j'obtiens une InvalidOperationException "VisualTree de ItemsPanelTemplate doit contenir un Panel." System.Windows.Controls.Viewbox "n'est pas un Panel." – Ian

+0

@Mart: Si je place mon AutoResizingCanvas UserControl dans la vue en fonction de votre suggestion, mes points sont mis à l'échelle, mais ils apparaissent dans un endroit étrange et je perds ma couleur de fond. Voir la capture d'écran: http://img62.imageshack.us/img62/4481/imagejc.jpg – Ian

+2

Votre problème vient du fait que le Canvas n'a pas de dimension. Son conteneur parent lui fait prendre tout l'espace disponible. Si vous connaissez les limites des points X et Y de vos points, définissez-les sur Largeur de toile et Hauteur. De cette façon, en plaçant une Viewbox autour du contrôle UserControl ou ItemsControl l'étendra réellement. – Mart