2009-10-13 8 views
1

Je suis un nfob WPF et je me bats avec la sélection du contrôle approprié pour obtenir la mise en page que je veux.Nouveauté de WPF - Quel contrôle utiliser/démarrer?

Ce que j'essaie de faire est de dessiner un tas de carrés (notes post-it virtuelles) sur l'écran. Chaque note va être d'une taille décente (environ 150 pixels) et il pourrait y avoir des centaines de ces notes. Je veux que l'ensemble soit défilable de sorte que vous puissiez redimensionner la fenêtre comme bon vous semble et que tout soit zoomable.

J'ai fait ceci et cela fonctionne.
Mais ce que j'ai fait semble terriblement faux ....

Dans le code, je crée dynamiquement des notes et les ajoute à un canevas géant. Je fais manuellement les calculs pour déterminer où placer chaque note et quelle devrait être la taille de la toile. J'ai ajouté quelques étiquettes en haut et j'ai dû revenir en arrière et ajouter une valeur 'Y Offset' pour pousser tous les carrés vers le bas. En fait, je génère trois contrôles de canevas différents, puis j'ajoute chacun d'entre eux à un panneau de pile qui se trouve à l'intérieur d'un ScrollViewer. J'ai ajouté une barre de défilement et réglé le panneau de la pile pour faire un zoom avant et arrière pendant que vous ajustez la barre. Cela fonctionne, mais j'ai l'impression de ne pas vraiment utiliser WPF de la façon dont il est censé être utilisé. J'ai essayé d'atteindre la même chose avec une grille, mais la grille ne semblait pas vouloir se dimensionner correctement. Quelqu'un peut-il me dire un «meilleur» moyen de parvenir au même look?

Voici mon code Xaml - comme vous pouvez le voir; il n'y a pas grand-chose à lui ....

<Window x:Class="Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 
<Grid x:Name="LayoutRoot"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="25" /> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 
    <Slider x:Name="ZoomSlider" Minimum="0.01" Value="1" Maximum="2" Margin="0,0,0,6" /> 
    <ScrollViewer x:Name="MyScroller" Grid.Row="1" HorizontalScrollBarVisibility="Visible" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"> 
     <StackPanel x:Name="TicketsGrid" Background="White" HorizontalAlignment="Center"> 

     </StackPanel> 
    </ScrollViewer> 
</Grid>    

Et voici ce que je fais dans le code (laid !!!)

For Each myWorkItem As WorkItem In myWorkItems 
     Dim newRect As New Border 

     newRect.Width = TicketSizeX 
     newRect.Height = TicketSizeY 

     If myWorkItem.State.ToUpper.Contains("HOLD") Then 
      newRect.Background = New SolidColorBrush(Colors.Purple) 
     Else 
      newRect.Background = New SolidColorBrush(Color) 
     End If 

     newRect.CornerRadius = New System.Windows.CornerRadius(5) 
     newRect.BorderThickness = New System.Windows.Thickness(1) 
     newRect.BorderBrush = New SolidColorBrush(Colors.Black) 

     Dim myPanel As New StackPanel 
     newRect.Child = myPanel 

     Dim lblTitle As New Label 
     lblTitle.Content = myWorkItem.Id 
     lblTitle.FontWeight = System.Windows.FontWeights.Bold 

     Dim lblDesc As New TextBlock 
     lblDesc.Text = myWorkItem.Title 
     lblDesc.TextWrapping = TextWrapping.Wrap 


     myPanel.Children.Add(lblTitle) 
     myPanel.Children.Add(lblDesc) 

     newRect.SetValue(Canvas.LeftProperty, CType(((TicketCount Mod TicketsXPerUser) * TicketStepX) + (xOffset * TicketStepX * TicketsXPerUser), Double)) 
     newRect.SetValue(Canvas.TopProperty, CType(((Math.Floor((TicketCount/TicketsXPerUser)) * TicketStepY)) + NameLabelHeight, Double)) 

     myCanvas.Children.Add(newRect) 
     TicketCount += 1 
    Next 

    MyCanvas.Width = (TicketStepX * TicketsXPerUser) * myTFS.SharedCodeTeam.Count 
    MyCanvas.Height = (CType(((Math.Floor((MaxTicket/TicketsXPerUser)) + 1) * TicketStepY), Double)) 

    TicketsGrid.Children.Add(MyCanvas) 

Répondre

6
  1. ScrollViewer avec ItemsControl à l'intérieur.
  2. Liez le ItemsSource propriété du ItemsControl à un ObservableCollection < PostIt> (où PostIt est un objet ancien CLR simple avec toutes les informations qui se passe le poste lui).
  3. Ajouter un DataTemplate au ItemsTemplate propriété des ItemsControl
  4. Ajouter des contrôles à la DataTemplate et les lier directement à une instance de PostIt
  5. Ajouter PostIt cas au ObservableCollection < PostIt> dans votre code.

Le ScrollViewer gère tout le défilement. C'est tout ce dont tu as besoin.Le ItemsControl est conçu pour se lier à une collection. Pour chaque instance de la collection, elle détermine le DataTemplate à utiliser, crée une copie du modèle, définit le DataContext de la racine sur l'instance extraite de la collection et ajoute le modèle à lui-même. Il le fait pour chaque instance trouvée dans la collection.

Dans votre codebehind, tout ce que vous avez à faire est de créer un tas de PostIts et de les ajouter à la collection. Pas de construction démoniaque des éléments de l'interface utilisateur comme vous le faites. Urgh.

Si vous pouvez vous familiariser avec ce concept, vous ne connaissez pas encore le modèle MVVM, le modèle Model-View-Controller dans WPF. Lisez à ce sujet, essayez-le. C'est un moyen très simple de faire des applications très complexes avec une interface utilisateur complexe, mais avec un minimum de code (et aucune de ces conneries que vous faites actuellement).

+4

Écrit exactement la même prescription, la seule chose que je pense que vous avez omis était de mentionner qu'il pourrait choisir différentes dispositions en utilisant en réglant le ItemsPanel aussi bien. Par défaut, c'est StackPanel avec l'orientation verticale, mais je pense qu'il voulait avoir WrapPanel comme fonctionnalité. –

+0

Oui, je parie que vous avez raison sur celui-là. +1 – Will

+0

Bon, sinon légèrement choquant, intro à MVVM ici: http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/432/MVVM-for-Tarded-Folks-Like-Me-or- MVVM et What-it-Means-to-Me.aspx – Will